Browse Source

SC: rearrange functions in cpp

tags/v1.3.0
Brian Heim 5 years ago
parent
commit
fbba8c2306
1 changed files with 112 additions and 106 deletions
  1. +112
    -106
      src/SuperColliderEngine.cpp

+ 112
- 106
src/SuperColliderEngine.cpp View File

@@ -43,8 +43,8 @@ public:
std::string&& command = "VcvPrototypeProcessBlock.numRows = " + std::to_string(NUM_ROWS); std::string&& command = "VcvPrototypeProcessBlock.numRows = " + std::to_string(NUM_ROWS);
interpret(command.c_str()); interpret(command.c_str());
} }
int getFrameDivider() noexcept { return getResultAsInt("^~vcv_frameDivider"); }
int getBufferSize() noexcept { return getResultAsInt("^~vcv_bufferSize"); }
int getFrameDivider() noexcept { return getInterpretResultAsInt("^~vcv_frameDivider"); }
int getBufferSize() noexcept { return getInterpretResultAsInt("^~vcv_bufferSize"); }


bool isOk() const noexcept { return _ok; } bool isOk() const noexcept { return _ok; }


@@ -56,19 +56,21 @@ public:
void flush() override {} void flush() override {}


private: private:
// Called on unrecoverable error, will stop the plugin
void fail(const std::string& msg) noexcept;

const char* buildScProcessBlockString(const ProcessBlock* block) const noexcept; const char* buildScProcessBlockString(const ProcessBlock* block) const noexcept;
int getResultAsInt(const char* text) noexcept;
bool isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept;


void fail(const std::string& msg) noexcept;
int getInterpretResultAsInt(const char* text) noexcept;


// converts top of stack back to ProcessBlock data // converts top of stack back to ProcessBlock data
void readScProcessBlockResult(ProcessBlock* block) noexcept; void readScProcessBlockResult(ProcessBlock* block) noexcept;


// helpers for copying SC info back into process block's arrays // helpers for copying SC info back into process block's arrays
bool isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept;
bool copyFloatArray(const PyrSlot& inSlot, const char* context, float* outArray, int size) noexcept;
template <typename Array> template <typename Array>
bool copyArrayOfFloatArrays(const PyrSlot& inSlot, const char* context, Array& array, int size) noexcept; bool copyArrayOfFloatArrays(const PyrSlot& inSlot, const char* context, Array& array, int size) noexcept;
bool copyFloatArray(const PyrSlot& inSlot, const char* context, float* outArray, int size) noexcept;


SuperColliderEngine* _engine; SuperColliderEngine* _engine;
PyrSymbol* _vcvPrototypeProcessBlockSym; PyrSymbol* _vcvPrototypeProcessBlockSym;
@@ -157,27 +159,68 @@ void SC_VcvPrototypeClient::interpret(const char* text) noexcept {
interpretCmdLine(); interpretCmdLine();
} }


#ifdef SC_VCV_ENGINE_TIMING
static long long int gmax = 0;
static constexpr unsigned int nTimes = 1024;
static long long int times[nTimes] = {};
static unsigned int timesIndex = 0;
#endif

void SC_VcvPrototypeClient::evaluateProcessBlock(ProcessBlock* block) noexcept {
#ifdef SC_VCV_ENGINE_TIMING
auto start = std::chrono::high_resolution_clock::now();
#endif
auto* buf = buildScProcessBlockString(block);
interpret(buf);
readScProcessBlockResult(block);
#ifdef SC_VCV_ENGINE_TIMING
auto end = std::chrono::high_resolution_clock::now();
auto ticks = (end - start).count();

times[timesIndex] = ticks;
timesIndex++;
timesIndex %= nTimes;
if (gmax < ticks)
{
gmax = ticks;
std::printf("MAX TIME %lld\n", ticks);
}
if (timesIndex == 0)
{
std::printf("AVG TIME %lld\n", std::accumulate(std::begin(times), std::end(times), 0ull) / nTimes);
}
#endif
}

void SC_VcvPrototypeClient::postText(const char* str, size_t len) { void SC_VcvPrototypeClient::postText(const char* str, size_t len) {
// Ensure the last message logged (presumably an error) stays onscreen. // Ensure the last message logged (presumably an error) stays onscreen.
if (_ok) if (_ok)
_engine->display(std::string(str, len)); _engine->display(std::string(str, len));
} }


void SC_VcvPrototypeClient::fail(const std::string& msg) noexcept {
// Ensure the last messaged logged in a previous failure stays onscreen.
if (_ok)
_engine->display(msg);
_ok = false;
}

// This should be well above what we ever need to represent a process block. // This should be well above what we ever need to represent a process block.
constexpr unsigned overhead = 512;
constexpr unsigned floatSize = 10;
constexpr unsigned insOutsSize = MAX_BUFFER_SIZE * NUM_ROWS * 2 * floatSize;
constexpr unsigned otherArraysSize = floatSize * NUM_ROWS * 8;
constexpr unsigned bufferSize = overhead + insOutsSize + otherArraysSize;
// Currently comes out to around 500 KB.
constexpr unsigned buildPbOverhead = 1024;
constexpr unsigned buildPbFloatSize = 10;
constexpr unsigned buildPbInsOutsSize = MAX_BUFFER_SIZE * NUM_ROWS * 2 * buildPbFloatSize;
constexpr unsigned buildPbOtherArraysSize = buildPbFloatSize * NUM_ROWS * 8;
constexpr unsigned buildPbBufferSize = buildPbOverhead + buildPbInsOutsSize + buildPbOtherArraysSize;


// Don't write initial string every time // Don't write initial string every time
#define PROCESS_BEGIN_STRING "^~vcv_process.(VcvPrototypeProcessBlock.new("
static char processBlockStringScratchBuf[bufferSize] = PROCESS_BEGIN_STRING;
constexpr unsigned processBeginStringOffset = sizeof(PROCESS_BEGIN_STRING);
#undef PROCESS_BEGIN_STRING
#define BUILD_PB_BEGIN_STRING "^~vcv_process.(VcvPrototypeProcessBlock.new("
static char buildPbStringScratchBuf[buildPbBufferSize] = BUILD_PB_BEGIN_STRING;
constexpr unsigned buildPbBeginStringOffset = sizeof(BUILD_PB_BEGIN_STRING);
#undef BUILD_PB_BEGIN_STRING


const char* SC_VcvPrototypeClient::buildScProcessBlockString(const ProcessBlock* block) const noexcept { const char* SC_VcvPrototypeClient::buildScProcessBlockString(const ProcessBlock* block) const noexcept {
auto* buf = processBlockStringScratchBuf + processBeginStringOffset - 1;
auto* buf = buildPbStringScratchBuf + buildPbBeginStringOffset - 1;


// Perhaps imprudently assuming snprintf never returns a negative code // Perhaps imprudently assuming snprintf never returns a negative code
buf += std::sprintf(buf, "%.6f,%.6f,%d,", block->sampleRate, block->sampleTime, block->bufferSize); buf += std::sprintf(buf, "%.6f,%.6f,%d,", block->sampleRate, block->sampleTime, block->bufferSize);
@@ -223,58 +266,27 @@ const char* SC_VcvPrototypeClient::buildScProcessBlockString(const ProcessBlock*


buf += std::sprintf(buf, "));"); buf += std::sprintf(buf, "));");


return processBlockStringScratchBuf;
}

bool SC_VcvPrototypeClient::isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept {
if (NotObj(slot))
return false;

auto* klass = slotRawObject(slot)->classptr;
auto* klassNameSymbol = slotRawSymbol(&klass->name);
return klassNameSymbol == _vcvPrototypeProcessBlockSym;
return buildPbStringScratchBuf;
} }


template <typename Array>
bool SC_VcvPrototypeClient::copyArrayOfFloatArrays(const PyrSlot& inSlot, const char* context, Array& outArray, int size) noexcept
{
// OUTPUTS
if (!isKindOfSlot(const_cast<PyrSlot*>(&inSlot), class_array)) {
fail(std::string(context) + " must be a Array");
return false;
}
auto* inObj = slotRawObject(&inSlot);
if (inObj->size != NUM_ROWS) {
fail(std::string(context) + " must be of size " + std::to_string(NUM_ROWS));
return false;
}
int SC_VcvPrototypeClient::getInterpretResultAsInt(const char* text) noexcept {
interpret(text);


for (int i = 0; i < NUM_ROWS; ++i) {
if (!copyFloatArray(inObj->slots[i], "subarray", outArray[i], size)) {
return false;
auto* resultSlot = &scGlobals()->result;
if (IsInt(resultSlot)) {
auto intResult = slotRawInt(resultSlot);
if (intResult > 0) {
return intResult;
} else {
fail(std::string("Result of '") + text + "' should be > 0");
return -1;
} }
} else {
fail(std::string("Result of '") + text + "' should be Integer");
return -1;
} }

return true;
} }


bool SC_VcvPrototypeClient::copyFloatArray(const PyrSlot& inSlot, const char* context, float* outArray, int size) noexcept
{
if (!isKindOfSlot(const_cast<PyrSlot*>(&inSlot), class_floatarray)) {
fail(std::string(context) + " must be a FloatArray");
return false;
}
auto* floatArrayObj = slotRawObject(&inSlot);
if (floatArrayObj->size != size) {
fail(std::string(context) + " must be of size " + std::to_string(size));
return false;
}

auto* floatArray = reinterpret_cast<const PyrFloatArray*>(floatArrayObj);
auto* rawArray = static_cast<const float*>(floatArray->f);
std::memcpy(outArray, rawArray, size * sizeof(float));
return true;
}


void SC_VcvPrototypeClient::readScProcessBlockResult(ProcessBlock* block) noexcept { void SC_VcvPrototypeClient::readScProcessBlockResult(ProcessBlock* block) noexcept {
auto* resultSlot = &scGlobals()->result; auto* resultSlot = &scGlobals()->result;
@@ -302,60 +314,54 @@ void SC_VcvPrototypeClient::readScProcessBlockResult(ProcessBlock* block) noexce
return; return;
} }


void SC_VcvPrototypeClient::fail(const std::string& msg) noexcept {
_engine->display(msg);
_ok = false;
}

#ifdef SC_VCV_ENGINE_TIMING
static long long int gmax = 0;
static constexpr unsigned int nTimes = 1024;
static long long int times[nTimes] = {};
static unsigned int timesIndex = 0;
#endif
bool SC_VcvPrototypeClient::isVcvPrototypeProcessBlock(const PyrSlot* slot) const noexcept {
if (NotObj(slot))
return false;


void SC_VcvPrototypeClient::evaluateProcessBlock(ProcessBlock* block) noexcept {
#ifdef SC_VCV_ENGINE_TIMING
auto start = std::chrono::high_resolution_clock::now();
#endif
auto* buf = buildScProcessBlockString(block);
interpret(buf);
readScProcessBlockResult(block);
#ifdef SC_VCV_ENGINE_TIMING
auto end = std::chrono::high_resolution_clock::now();
auto ticks = (end - start).count();
auto* klass = slotRawObject(slot)->classptr;
auto* klassNameSymbol = slotRawSymbol(&klass->name);
return klassNameSymbol == _vcvPrototypeProcessBlockSym;
}


times[timesIndex] = ticks;
timesIndex++;
timesIndex %= nTimes;
if (gmax < ticks)
{
gmax = ticks;
std::printf("MAX TIME %lld\n", ticks);
bool SC_VcvPrototypeClient::copyFloatArray(const PyrSlot& inSlot, const char* context, float* outArray, int size) noexcept
{
if (!isKindOfSlot(const_cast<PyrSlot*>(&inSlot), class_floatarray)) {
fail(std::string(context) + " must be a FloatArray");
return false;
} }
if (timesIndex == 0)
{
std::printf("AVG TIME %lld\n", std::accumulate(std::begin(times), std::end(times), 0ull) / nTimes);
auto* floatArrayObj = slotRawObject(&inSlot);
if (floatArrayObj->size != size) {
fail(std::string(context) + " must be of size " + std::to_string(size));
return false;
} }
#endif

auto* floatArray = reinterpret_cast<const PyrFloatArray*>(floatArrayObj);
auto* rawArray = static_cast<const float*>(floatArray->f);
std::memcpy(outArray, rawArray, size * sizeof(float));
return true;
} }


int SC_VcvPrototypeClient::getResultAsInt(const char* text) noexcept {
interpret(text);
template <typename Array>
bool SC_VcvPrototypeClient::copyArrayOfFloatArrays(const PyrSlot& inSlot, const char* context, Array& outArray, int size) noexcept
{
// OUTPUTS
if (!isKindOfSlot(const_cast<PyrSlot*>(&inSlot), class_array)) {
fail(std::string(context) + " must be a Array");
return false;
}
auto* inObj = slotRawObject(&inSlot);
if (inObj->size != NUM_ROWS) {
fail(std::string(context) + " must be of size " + std::to_string(NUM_ROWS));
return false;
}


auto* resultSlot = &scGlobals()->result;
if (IsInt(resultSlot)) {
auto intResult = slotRawInt(resultSlot);
if (intResult > 0) {
return intResult;
} else {
fail(std::string("Result of '") + text + "' should be > 0");
return -1;
for (int i = 0; i < NUM_ROWS; ++i) {
if (!copyFloatArray(inObj->slots[i], "subarray", outArray[i], size)) {
return false;
} }
} else {
fail(std::string("Result of '") + text + "' should be Integer");
return -1;
} }

return true;
} }


__attribute__((constructor(1000))) __attribute__((constructor(1000)))


Loading…
Cancel
Save