|
|
|
@@ -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<snd_seq_event_t>(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<snd_seq_event_t>(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<snd_seq_event_t>(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; |
|
|
|
}; |
|
|
|
|
|
|
|
|