diff --git a/source/backend/engine/jack.cpp b/source/backend/engine/jack.cpp index 0886fd916..a4c677ebe 100644 --- a/source/backend/engine/jack.cpp +++ b/source/backend/engine/jack.cpp @@ -83,6 +83,9 @@ public: return CarlaEngineAudioPort::initBuffer(engine); fBuffer = (float*)jackbridge_port_get_buffer(kPort, engine->getBufferSize()); + + //if (! kIsInput) + // carla_zeroFloat(fBuffer, engine->getBufferSize()); } private: diff --git a/source/backend/plugin/dssi.cpp b/source/backend/plugin/dssi.cpp index 25da2d425..0ad8bef50 100644 --- a/source/backend/plugin/dssi.cpp +++ b/source/backend/plugin/dssi.cpp @@ -37,7 +37,9 @@ public: fDescriptor = nullptr; fDssiDescriptor = nullptr; - fParamBuffers = nullptr; + fAudioInBuffers = nullptr; + fAudioOutBuffers = nullptr; + fParamBuffers = nullptr; carla_zeroMem(fMidiEvents, sizeof(snd_seq_event_t)*MAX_MIDI_EVENTS); } @@ -88,11 +90,7 @@ public: fDssiDescriptor = nullptr; } - if (fParamBuffers != nullptr) - { - delete[] fParamBuffers; - fParamBuffers = nullptr; - } + deleteBuffers(); } // ------------------------------------------------------------------- @@ -424,11 +422,19 @@ public: if (aIns > 0) { kData->audioIn.createNew(aIns); + fAudioInBuffers = new float*[aIns]; + + for (uint32_t i=0; i < aIns; i++) + fAudioInBuffers[i] = nullptr; } if (aOuts > 0) { kData->audioOut.createNew(aOuts); + fAudioOutBuffers = new float*[aOuts]; + + for (uint32_t i=0; i < aOuts; i++) + fAudioOutBuffers[i] = nullptr; } if (params > 0) @@ -754,6 +760,7 @@ public: } } + bufferSizeChanged(kData->engine->getBufferSize()); reloadPrograms(true); kData->client->activate(); @@ -928,7 +935,7 @@ public: { while (midiEventCount < MAX_MIDI_EVENTS && ! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note = kData->extNotes.data.getLast(true); // FIXME, should be first CARLA_ASSERT(note.channel >= 0); @@ -950,6 +957,7 @@ public: // Event Input (System) bool allNotesOffSent = false; + bool sampleAccurate = (fHints & PLUGIN_OPTION_FIXED_BUFFER) == 0; uint32_t time, nEvents = kData->event.portIn->getEventCount(); uint32_t timeOffset = 0; @@ -969,10 +977,12 @@ public: CARLA_ASSERT(time >= timeOffset); - if (time > timeOffset) + if (time > timeOffset && sampleAccurate) { - processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset, midiEventCount); + qWarning("Variable proccessing @ frame %04i/%04i for %04i frames, cur:%04i", timeOffset, frames, time - timeOffset, time); + processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset, midiEventCount); midiEventCount = 0; + nextBankId = 0; timeOffset = time; } @@ -1126,6 +1136,18 @@ public: allNotesOffSent = true; } + + carla_zeroStruct(fMidiEvents[midiEventCount]); + + if (! sampleAccurate) + fMidiEvents[midiEventCount].time.tick = time; + + fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER; + fMidiEvents[midiEventCount].data.control.channel = event.channel; + fMidiEvents[midiEventCount].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF; + + midiEventCount++; + break; case kEngineControlEventTypeAllNotesOff: @@ -1136,6 +1158,18 @@ public: allNotesOffSent = true; } + + carla_zeroStruct(fMidiEvents[midiEventCount]); + + if (! sampleAccurate) + fMidiEvents[midiEventCount].time.tick = time; + + fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER; + fMidiEvents[midiEventCount].data.control.channel = event.channel; + fMidiEvents[midiEventCount].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF; + + midiEventCount++; + break; } @@ -1158,7 +1192,8 @@ public: carla_zeroStruct(fMidiEvents[midiEventCount]); - fMidiEvents[midiEventCount].time.tick = time; + //if (! sampleAccurate) + fMidiEvents[midiEventCount].time.tick = time - timeOffset; if (MIDI_IS_STATUS_NOTE_OFF(status)) { @@ -1192,6 +1227,19 @@ public: fMidiEvents[midiEventCount].data.note.note = note; fMidiEvents[midiEventCount].data.note.velocity = pressure; } + else if (MIDI_IS_STATUS_CONTROL_CHANGE(status)) + { + if (fHints & PLUGIN_OPTION_SELF_AUTOMATION) + { + const uint8_t control = midiEvent.data[1]; + const uint8_t value = midiEvent.data[2]; + + fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER; + fMidiEvents[midiEventCount].data.control.channel = channel; + fMidiEvents[midiEventCount].data.control.param = control; + fMidiEvents[midiEventCount].data.control.value = value; + } + } else if (MIDI_IS_STATUS_AFTERTOUCH(status)) { const uint8_t pressure = midiEvent.data[1]; @@ -1222,7 +1270,12 @@ public: kData->postRtEvents.trySplice(); if (frames > timeOffset) + { + if (timeOffset != 0) + qWarning("FINAL proccessing @ frame %04i/%04i for %04i frames, cur:%04i", timeOffset, frames, frames - timeOffset, time); + processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset, midiEventCount); + } } // End of Event Input and Processing @@ -1372,54 +1425,93 @@ public: void processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const uint32_t midiEventCount) { + for (uint32_t i=0; i < kData->audioIn.count; i++) + std::memcpy(fAudioInBuffers[i], inBuffer[i]+timeOffset, sizeof(float)*frames); + for (uint32_t i=0; i < kData->audioOut.count; i++) + carla_zeroFloat(fAudioOutBuffers[i], frames); + + if (fDssiDescriptor->run_synth != nullptr) + { + fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount); + + if (fHandle2 != nullptr) + fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount); + } + else if (fDssiDescriptor->run_multiple_synths != nullptr) + { + unsigned long instances = (fHandle2 != nullptr) ? 2 : 1; + LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 }; + snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents }; + unsigned long midiEventCountPtr[2] = { midiEventCount, midiEventCount }; + fDssiDescriptor->run_multiple_synths(instances, handlePtr, frames, midiEventsPtr, midiEventCountPtr); + } + else + { + fDescriptor->run(fHandle, frames); + + if (fHandle2 != nullptr) + fDescriptor->run(fHandle2, frames); + } + + for (uint32_t i=0, k; i < kData->audioOut.count; i++) + { + for (k=0; k < frames; k++) + outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k]; + } + } + + void bufferSizeChanged(const uint32_t newBufferSize) + { + for (uint32_t i=0; i < kData->audioIn.count; i++) + { + if (fAudioInBuffers[i] != nullptr) + delete[] fAudioInBuffers[i]; + fAudioInBuffers[i] = new float[newBufferSize]; + } + + for (uint32_t i=0; i < kData->audioOut.count; i++) + { + if (fAudioOutBuffers[i] != nullptr) + delete[] fAudioOutBuffers[i]; + fAudioOutBuffers[i] = new float[newBufferSize]; + } + if (fHandle2 == nullptr) { for (uint32_t i=0; i < kData->audioIn.count; i++) - fDescriptor->connect_port(fHandle, kData->audioIn.ports[i].rindex, inBuffer[i]+timeOffset); + { + CARLA_ASSERT(fAudioInBuffers[i] != nullptr); + fDescriptor->connect_port(fHandle, kData->audioIn.ports[i].rindex, fAudioInBuffers[i]); + } for (uint32_t i=0; i < kData->audioOut.count; i++) - fDescriptor->connect_port(fHandle, kData->audioOut.ports[i].rindex, outBuffer[i]+timeOffset); + { + CARLA_ASSERT(fAudioOutBuffers[i] != nullptr); + fDescriptor->connect_port(fHandle, kData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); + } } else { if (kData->audioIn.count > 0) { CARLA_ASSERT(kData->audioIn.count == 2); + CARLA_ASSERT(fAudioInBuffers[0] != nullptr); + CARLA_ASSERT(fAudioInBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, kData->audioIn.ports[0].rindex, inBuffer[0]+timeOffset); - fDescriptor->connect_port(fHandle2, kData->audioIn.ports[1].rindex, inBuffer[1]+timeOffset); + fDescriptor->connect_port(fHandle, kData->audioIn.ports[0].rindex, fAudioInBuffers[0]); + fDescriptor->connect_port(fHandle2, kData->audioIn.ports[1].rindex, fAudioInBuffers[1]); } if (kData->audioOut.count > 0) { CARLA_ASSERT(kData->audioOut.count == 2); + CARLA_ASSERT(fAudioOutBuffers[0] != nullptr); + CARLA_ASSERT(fAudioOutBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, kData->audioOut.ports[0].rindex, outBuffer[0]+timeOffset); - fDescriptor->connect_port(fHandle2, kData->audioOut.ports[1].rindex, outBuffer[1]+timeOffset); + fDescriptor->connect_port(fHandle, kData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); + fDescriptor->connect_port(fHandle2, kData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); } } - - if (fDssiDescriptor->run_synth != nullptr) - { - fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount); - - if (fHandle2) - fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount); - } - else if (fDssiDescriptor->run_multiple_synths != nullptr) - { - LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 }; - snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents }; - unsigned long midiEventCountPtr[2] = { midiEventCount, midiEventCount }; - fDssiDescriptor->run_multiple_synths((fHandle2 != nullptr) ? 2 : 1, handlePtr, frames, midiEventsPtr, midiEventCountPtr); - } - else - { - fDescriptor->run(fHandle, frames); - - if (fHandle2) - fDescriptor->run(fHandle2, frames); - } } // ------------------------------------------------------------------- @@ -1498,6 +1590,36 @@ public: { qDebug("DssiPlugin::deleteBuffers() - start"); + if (fAudioInBuffers != nullptr) + { + for (uint32_t i=0; i < kData->audioIn.count; i++) + { + if (fAudioInBuffers[i] != nullptr) + { + delete[] fAudioInBuffers[i]; + fAudioInBuffers[i] = nullptr; + } + } + + delete[] fAudioInBuffers; + fAudioInBuffers = nullptr; + } + + if (fAudioOutBuffers != nullptr) + { + for (uint32_t i=0; i < kData->audioOut.count; i++) + { + if (fAudioOutBuffers[i] != nullptr) + { + delete[] fAudioOutBuffers[i]; + fAudioOutBuffers[i] = nullptr; + } + } + + delete[] fAudioOutBuffers; + fAudioOutBuffers = nullptr; + } + if (fParamBuffers != nullptr) { delete[] fParamBuffers; @@ -1609,8 +1731,10 @@ private: const LADSPA_Descriptor* fDescriptor; const DSSI_Descriptor* fDssiDescriptor; + float** fAudioInBuffers; + float** fAudioOutBuffers; + float* fParamBuffers; snd_seq_event_t fMidiEvents[MAX_MIDI_EVENTS]; - float* fParamBuffers; QByteArray fChunk; }; diff --git a/source/backend/plugin/ladspa.cpp b/source/backend/plugin/ladspa.cpp index f59599a23..4e9841304 100644 --- a/source/backend/plugin/ladspa.cpp +++ b/source/backend/plugin/ladspa.cpp @@ -36,7 +36,9 @@ public: fDescriptor = nullptr; fRdfDescriptor = nullptr; - fParamBuffers = nullptr; + fAudioInBuffers = nullptr; + fAudioOutBuffers = nullptr; + fParamBuffers = nullptr; } ~LadspaPlugin() @@ -72,11 +74,7 @@ public: fRdfDescriptor = nullptr; } - if (fParamBuffers != nullptr) - { - delete[] fParamBuffers; - fParamBuffers = nullptr; - } + deleteBuffers(); } // ------------------------------------------------------------------- @@ -408,11 +406,19 @@ public: if (aIns > 0) { kData->audioIn.createNew(aIns); + fAudioInBuffers = new float*[aIns]; + + for (uint32_t i=0; i < aIns; i++) + fAudioInBuffers[i] = nullptr; } if (aOuts > 0) { kData->audioOut.createNew(aOuts); + fAudioOutBuffers = new float*[aOuts]; + + for (uint32_t i=0; i < aOuts; i++) + fAudioOutBuffers[i] = nullptr; } if (params > 0) @@ -725,6 +731,8 @@ public: } } + bufferSizeChanged(kData->engine->getBufferSize()); + kData->client->activate(); qDebug("LadspaPlugin::reload() - end"); @@ -789,6 +797,8 @@ public: // ---------------------------------------------------------------------------------------------------- // Event Input (System) + bool sampleAccurate = (fHints & PLUGIN_OPTION_FIXED_BUFFER) == 0; + uint32_t time, nEvents = kData->event.portIn->getEventCount(); uint32_t timeOffset = 0; @@ -803,9 +813,9 @@ public: CARLA_ASSERT(time >= timeOffset); - if (time > timeOffset) + if (time > timeOffset && sampleAccurate) { - processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset); + processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset); timeOffset = time; } @@ -1094,37 +1104,75 @@ public: void processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) { + for (uint32_t i=0; i < kData->audioIn.count; i++) + std::memcpy(fAudioInBuffers[i], inBuffer[i]+timeOffset, sizeof(float)*frames); + for (uint32_t i=0; i < kData->audioOut.count; i++) + carla_zeroFloat(fAudioOutBuffers[i], frames); + + fDescriptor->run(fHandle, frames); + + if (fHandle2 != nullptr) + fDescriptor->run(fHandle2, frames); + + for (uint32_t i=0, k; i < kData->audioOut.count; i++) + { + for (k=0; k < frames; k++) + outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k]; + } + } + + void bufferSizeChanged(const uint32_t newBufferSize) + { + for (uint32_t i=0; i < kData->audioIn.count; i++) + { + if (fAudioInBuffers[i] != nullptr) + delete[] fAudioInBuffers[i]; + fAudioInBuffers[i] = new float[newBufferSize]; + } + + for (uint32_t i=0; i < kData->audioOut.count; i++) + { + if (fAudioOutBuffers[i] != nullptr) + delete[] fAudioOutBuffers[i]; + fAudioOutBuffers[i] = new float[newBufferSize]; + } + if (fHandle2 == nullptr) { for (uint32_t i=0; i < kData->audioIn.count; i++) - fDescriptor->connect_port(fHandle, kData->audioIn.ports[i].rindex, inBuffer[i]+timeOffset); + { + CARLA_ASSERT(fAudioInBuffers[i] != nullptr); + fDescriptor->connect_port(fHandle, kData->audioIn.ports[i].rindex, fAudioInBuffers[i]); + } for (uint32_t i=0; i < kData->audioOut.count; i++) - fDescriptor->connect_port(fHandle, kData->audioOut.ports[i].rindex, outBuffer[i]+timeOffset); + { + CARLA_ASSERT(fAudioOutBuffers[i] != nullptr); + fDescriptor->connect_port(fHandle, kData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); + } } else { if (kData->audioIn.count > 0) { CARLA_ASSERT(kData->audioIn.count == 2); + CARLA_ASSERT(fAudioInBuffers[0] != nullptr); + CARLA_ASSERT(fAudioInBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, kData->audioIn.ports[0].rindex, inBuffer[0]+timeOffset); - fDescriptor->connect_port(fHandle2, kData->audioIn.ports[1].rindex, inBuffer[1]+timeOffset); + fDescriptor->connect_port(fHandle, kData->audioIn.ports[0].rindex, fAudioInBuffers[0]); + fDescriptor->connect_port(fHandle2, kData->audioIn.ports[1].rindex, fAudioInBuffers[1]); } if (kData->audioOut.count > 0) { CARLA_ASSERT(kData->audioOut.count == 2); + CARLA_ASSERT(fAudioOutBuffers[0] != nullptr); + CARLA_ASSERT(fAudioOutBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, kData->audioOut.ports[0].rindex, outBuffer[0]+timeOffset); - fDescriptor->connect_port(fHandle2, kData->audioOut.ports[1].rindex, outBuffer[1]+timeOffset); + fDescriptor->connect_port(fHandle, kData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); + fDescriptor->connect_port(fHandle2, kData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); } } - - fDescriptor->run(fHandle, frames); - - if (fHandle2 != nullptr) - fDescriptor->run(fHandle2, frames); } // ------------------------------------------------------------------- @@ -1134,6 +1182,36 @@ public: { qDebug("LadspaPlugin::deleteBuffers() - start"); + if (fAudioInBuffers != nullptr) + { + for (uint32_t i=0; i < kData->audioIn.count; i++) + { + if (fAudioInBuffers[i] != nullptr) + { + delete[] fAudioInBuffers[i]; + fAudioInBuffers[i] = nullptr; + } + } + + delete[] fAudioInBuffers; + fAudioInBuffers = nullptr; + } + + if (fAudioOutBuffers != nullptr) + { + for (uint32_t i=0; i < kData->audioOut.count; i++) + { + if (fAudioOutBuffers[i] != nullptr) + { + delete[] fAudioOutBuffers[i]; + fAudioOutBuffers[i] = nullptr; + } + } + + delete[] fAudioOutBuffers; + fAudioOutBuffers = nullptr; + } + if (fParamBuffers != nullptr) { delete[] fParamBuffers; @@ -1238,7 +1316,9 @@ private: const LADSPA_Descriptor* fDescriptor; const LADSPA_RDF_Descriptor* fRdfDescriptor; - float* fParamBuffers; + float** fAudioInBuffers; + float** fAudioOutBuffers; + float* fParamBuffers; }; CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/standalone/carla_standalone.cpp b/source/backend/standalone/carla_standalone.cpp index 10041ddee..91ab4ba04 100644 --- a/source/backend/standalone/carla_standalone.cpp +++ b/source/backend/standalone/carla_standalone.cpp @@ -23,6 +23,12 @@ #include "carla_midi.h" #include "carla_native.h" +#if 0 +extern "C" { +#include "siginfo.c" +} +#endif + #include using CarlaBackend::CarlaEngine; @@ -187,6 +193,16 @@ bool carla_engine_init(const char* driverName, const char* clientName) CARLA_ASSERT(driverName != nullptr); CARLA_ASSERT(clientName != nullptr); +#if 0 + static bool sigInfoInitiated = false; + + if (! sigInfoInitiated) + { + setup_siginfo(); + sigInfoInitiated = true; + } +#endif + standalone.engine = CarlaEngine::newDriverByName(driverName); if (standalone.engine == nullptr)