//Yes, this uses goto. Yes, goto is evil. We need a single point of exit. void Simulation::getBlock(float* out, unsigned int channels, bool mayApplyMixingMatrix) { if(out == nullptr || channels == 0) goto end; //nothing to do. if(block_callback) block_callback(outgoingObject(this->shared_from_this()), block_callback_time, block_callback_userdata); //configure our connection to the number of channels requested. final_output_connection->reconfigure(0, channels); //append buffers to the final_outputs vector until it's big enough. //in a sane application, we'll never go above 8 channels so keeping them around is no big deal. while(final_outputs.size() < channels) final_outputs.push_back(allocArray<float>(block_size)); //zero the outputs we need. for(unsigned int i= 0; i < channels; i++) memset(final_outputs[i], 0, sizeof(float)*block_size); //Inform nodes that we are going to tick. for(auto &i: nodes) { auto n = i.lock(); if(n) n->willTick(); } //Use the planner. planner->execute(std::dynamic_pointer_cast<Job>(shared_from_this()), threads); //write, applying mixing matrices as needed. final_output_connection->addNodeless(&final_outputs[0], true); //interleave the samples. interleaveSamples(channels, block_size, channels, &final_outputs[0], out); block_callback_time +=block_size/sr; end: int maintenance_count=maintenance_start; for(auto &i: nodes) { auto i_s=i.lock(); if(i_s == nullptr) continue; if(maintenance_count % maintenance_rate== 0) i_s->doMaintenance(); maintenance_count++; } maintenance_start++; //and ourselves. if(maintenance_start%maintenance_rate == 0) doMaintenance(); tick_count ++; }
Lav_PUBLIC_FUNCTION LavError Lav_createBuffer(LavHandle simulationHandle, LavHandle* destination) { PUB_BEGIN auto simulation = incomingObject<Simulation>(simulationHandle); LOCK(*simulation); *destination = outgoingObject(createBuffer(simulation)); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_createSimulation(unsigned int sr, unsigned int blockSize, LavHandle* destination) { PUB_BEGIN auto shared = std::make_shared<Simulation>(sr, blockSize, 0); shared->completeInitialization(); *destination = outgoingObject(shared); PUB_END }
//begin public api Lav_PUBLIC_FUNCTION LavError Lav_createDoppleringDelayNode(LavHandle simulationHandle, float maxDelay, unsigned int lineCount, LavHandle* destination) { PUB_BEGIN auto simulation =incomingObject<Simulation>(simulationHandle); LOCK(*simulation); auto d = createDoppleringDelayNode(simulation, maxDelay, lineCount); *destination = outgoingObject(d); PUB_END }
//begin public api Lav_PUBLIC_FUNCTION LavError Lav_createFilteredDelayNode(LavHandle simulationHandle, float maxDelay, unsigned int channels, LavHandle* destination) { PUB_BEGIN auto simulation =incomingObject<Simulation>(simulationHandle); LOCK(*simulation); auto d = createFilteredDelayNode(simulation, maxDelay, channels); *destination = outgoingObject(d); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_createChannelMergerNode(LavHandle simulationHandle, int channels, LavHandle* destination) { PUB_BEGIN auto simulation = incomingObject<Simulation>(simulationHandle); LOCK(*simulation); auto retval = createChannelMergerNode(simulation, channels); *destination = outgoingObject(retval); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_createBufferTimelineNode(LavHandle simulationHandle, int channels, LavHandle* destination) { PUB_BEGIN auto sim = incomingObject<Simulation>(simulationHandle); LOCK(*sim); if(channels == 0) ERROR(Lav_ERROR_RANGE); auto n =createBufferTimelineNode(sim, channels); *destination = outgoingObject(n); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_bufferGetSimulation(LavHandle handle, LavHandle* destination) { PUB_BEGIN auto b= incomingObject<Buffer>(handle); *destination = outgoingObject(b->getSimulation()); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_nodeGetBufferProperty(LavHandle nodeHandle, int slot, LavHandle* destination) { PUB_BEGIN PROP_PREAMBLE(nodeHandle, slot, Lav_PROPERTYTYPE_BUFFER); *destination = outgoingObject(prop.getBufferValue()); PUB_END }
Lav_PUBLIC_FUNCTION LavError Lav_nodeGetSimulation(LavHandle handle, LavHandle* destination) { PUB_BEGIN auto n = incomingObject<Node>(handle); *destination = outgoingObject(n->getSimulation()); PUB_END }