diff --git a/src/SuperColliderEngine.cpp b/src/SuperColliderEngine.cpp index f330765..334ee98 100644 --- a/src/SuperColliderEngine.cpp +++ b/src/SuperColliderEngine.cpp @@ -4,6 +4,7 @@ #include "LangSource/SC_LanguageConfig.hpp" #include "LangSource/SCBase.h" #include "LangSource/VMGlobals.h" +#include "LangSource/PyrObject.h" #include #include @@ -52,6 +53,10 @@ public: private: std::string buildScProcessBlockString(const ProcessBlock* block) const noexcept; int getResultAsInt(const char* text) noexcept; + bool isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept; + + // converts top of stack back to ProcessBlock data + void readScProcessBlockResult(ProcessBlock* block) noexcept; SuperColliderEngine* _engine; bool _ok = true; @@ -151,6 +156,7 @@ std::string SC_VcvPrototypeClient::buildScProcessBlockString(const ProcessBlock* std::ostringstream builder; // TODO so expensive + builder << std::fixed; // to ensure floats aren't actually treated as Integers builder << "^~vcv_process.value(VcvPrototypeProcessBlock.new(" << block->sampleRate << ',' << block->sampleTime << ',' @@ -214,6 +220,92 @@ std::string SC_VcvPrototypeClient::buildScProcessBlockString(const ProcessBlock* return builder.str(); } +bool SC_VcvPrototypeClient::isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept { + // TODO + return true; +} + +void SC_VcvPrototypeClient::readScProcessBlockResult(ProcessBlock* block) noexcept { + auto* resultSlot = &scGlobals()->result; + if (!isVcvPrototypeProcessBlock(resultSlot)) { + FAIL("Result of ~vcv_process must be an instance of VcvPrototypeProcessBlock"); + return; + } + + constexpr unsigned outputsSlotIndex = 4; + constexpr unsigned knobsSlotIndex = 5; + constexpr unsigned lightsSlotIndex = 7; + constexpr unsigned switchLightsSlotIndex = 8; + + PyrObject* object = slotRawObject(resultSlot); + + { + // OUTPUTS + PyrSlot* outputsSlot = &object->slots[outputsSlotIndex]; + // TODO check is array + // TODO check size + PyrObject* outputsObj = slotRawObject(outputsSlot); + for (int i = 0; i < NUM_ROWS; ++i) { + PyrSlot* floatArraySlot = &outputsObj->slots[i]; + // TODO check is floatarray + // TODO check size + PyrObject* floatArrayObj = slotRawObject(floatArraySlot); + PyrFloatArray* floatArray = reinterpret_cast(floatArrayObj); + for (int j = 0; j < block->bufferSize; ++j) { + block->outputs[i][j] = floatArray->f[j]; + } + } + } + + { + // KNOBS + PyrSlot* knobsSlot = &object->slots[knobsSlotIndex]; + // TODO check is floatarray + // TODO check size + PyrObject* knobsObj = slotRawObject(knobsSlot); + PyrFloatArray* floatArray = reinterpret_cast(knobsObj); + for (int i = 0; i < NUM_ROWS; ++i) { + block->knobs[i] = floatArray->f[i]; + } + } + + { + // LIGHTS + PyrSlot* lightsSlot = &object->slots[lightsSlotIndex]; + // TODO check is array + // TODO check size + PyrObject* lightsObj = slotRawObject(lightsSlot); + for (int i = 0; i < NUM_ROWS; ++i) { + PyrSlot* floatArraySlot = &lightsObj->slots[i]; + // TODO check is floatarray + // TODO check size + PyrObject* floatArrayObj = slotRawObject(floatArraySlot); + PyrFloatArray* floatArray = reinterpret_cast(floatArrayObj); + block->lights[i][0] = floatArray->f[0]; + block->lights[i][1] = floatArray->f[1]; + block->lights[i][2] = floatArray->f[2]; + } + } + + { + // SWITCH LIGHTS + PyrSlot* switchLightsSlot = &object->slots[switchLightsSlotIndex]; + // TODO check is array + // TODO check size + PyrObject* switchLightsObj = slotRawObject(switchLightsSlot); + for (int i = 0; i < NUM_ROWS; ++i) { + PyrSlot* floatArraySlot = &switchLightsObj->slots[i]; + // TODO check is floatarray + // TODO check size + PyrObject* floatArrayObj = slotRawObject(floatArraySlot); + PyrFloatArray* floatArray = reinterpret_cast(floatArrayObj); + block->switchLights[i][0] = floatArray->f[0]; + block->switchLights[i][1] = floatArray->f[1]; + block->switchLights[i][2] = floatArray->f[2]; + } + } +} + // TODO test code static long long int gmax = 0; @@ -222,6 +314,7 @@ void SC_VcvPrototypeClient::evaluateProcessBlock(ProcessBlock* block) noexcept { auto start = std::chrono::high_resolution_clock::now(); auto&& string = buildScProcessBlockString(block); interpret(string.c_str()); + readScProcessBlockResult(block); auto end = std::chrono::high_resolution_clock::now(); auto ticks = (end - start).count(); if (gmax < ticks)