| @@ -597,7 +597,7 @@ public: | |||
| * \param sendCallback Send message change to registered callback | |||
| * \param block Block the audio callback | |||
| */ | |||
| virtual void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block); | |||
| virtual void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback); | |||
| /*! | |||
| * Change the current MIDI plugin program to \a index. | |||
| @@ -611,13 +611,13 @@ public: | |||
| * \param sendCallback Send message change to registered callback | |||
| * \param block Block the audio callback | |||
| */ | |||
| virtual void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block); | |||
| virtual void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback); | |||
| /*! | |||
| * This is an overloaded call to setMidiProgram().\n | |||
| * It changes the current MIDI program using \a bank and \a program values instead of index. | |||
| */ | |||
| void setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block); | |||
| void setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback); | |||
| // ------------------------------------------------------------------- | |||
| // Set gui stuff | |||
| @@ -847,6 +847,7 @@ protected: | |||
| private: | |||
| CarlaPlugin* const kPlugin; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedDisabler) | |||
| }; | |||
| @@ -856,12 +857,14 @@ protected: | |||
| class ScopedProcessLocker | |||
| { | |||
| public: | |||
| ScopedProcessLocker(CarlaPlugin* const plugin); | |||
| ScopedProcessLocker(CarlaPlugin* const plugin, const bool block); | |||
| ~ScopedProcessLocker(); | |||
| private: | |||
| CarlaPlugin* const kPlugin; | |||
| const bool kBlock; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedProcessLocker) | |||
| }; | |||
| @@ -1456,9 +1456,10 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t | |||
| // if no plugins in the rack, copy inputs over outputs | |||
| if (! processed) | |||
| { | |||
| carla_copyFloat(outBuf[0], inBuf[0], frames); | |||
| carla_copyFloat(outBuf[1], inBuf[1], frames); | |||
| std::memcpy(kData->rack.out, kData->rack.in, sizeof(EngineEvent)*RACK_EVENT_COUNT); | |||
| // FIXME | |||
| //carla_copyFloat(outBuf[0], inBuf[0], frames); | |||
| //carla_copyFloat(outBuf[1], inBuf[1], frames); | |||
| //std::memcpy(kData->rack.out, kData->rack.in, sizeof(EngineEvent)*RACK_EVENT_COUNT); | |||
| } | |||
| } | |||
| @@ -499,7 +499,7 @@ int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||
| if (program < 0) | |||
| return 1; | |||
| plugin->setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true, true); | |||
| plugin->setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true); | |||
| return 0; | |||
| } | |||
| @@ -516,7 +516,7 @@ int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||
| if (program < static_cast<int32_t>(plugin->programCount())) | |||
| { | |||
| plugin->setProgram(program, false, true, true, true); | |||
| plugin->setProgram(program, false, true, true); | |||
| return 0; | |||
| } | |||
| @@ -728,7 +728,7 @@ int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||
| const int32_t index = argv[0]->i; | |||
| plugin->setProgram(index, true, false, true, true); | |||
| plugin->setProgram(index, true, false, true); | |||
| return 0; | |||
| } | |||
| @@ -740,7 +740,7 @@ int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||
| const int32_t index = argv[0]->i; | |||
| plugin->setMidiProgram(index, true, false, true, true); | |||
| plugin->setMidiProgram(index, true, false, true); | |||
| return 0; | |||
| } | |||
| @@ -762,7 +762,7 @@ void CarlaPlugin::setChunkData(const char* const stringData) | |||
| (void)stringData; | |||
| } | |||
| void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) | |||
| void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->prog.count)); | |||
| @@ -804,7 +804,7 @@ void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool | |||
| kData->engine->callback(CALLBACK_PROGRAM_CHANGED, fId, fixedIndex, 0, 0.0f, nullptr); | |||
| } | |||
| void CarlaPlugin::setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) | |||
| void CarlaPlugin::setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->midiprog.count)); | |||
| @@ -851,12 +851,12 @@ void CarlaPlugin::setMidiProgram(int32_t index, const bool sendGui, const bool s | |||
| kData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fId, fixedIndex, 0, 0.0f, nullptr); | |||
| } | |||
| void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block) | |||
| void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| for (uint32_t i=0; i < kData->midiprog.count; i++) | |||
| { | |||
| if (kData->midiprog.data[i].bank == bank && kData->midiprog.data[i].program == program) | |||
| return setMidiProgram(i, sendGui, sendOsc, sendCallback, block); | |||
| return setMidiProgram(i, sendGui, sendOsc, sendCallback); | |||
| } | |||
| } | |||
| @@ -1464,6 +1464,9 @@ const char* CarlaPlugin::libError(const char* const filename) | |||
| CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) | |||
| : kPlugin(plugin) | |||
| { | |||
| carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin); | |||
| CARLA_ASSERT(plugin != nullptr); | |||
| if (plugin->fEnabled) | |||
| { | |||
| plugin->fEnabled = false; | |||
| @@ -1476,6 +1479,8 @@ CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) | |||
| CarlaPlugin::ScopedDisabler::~ScopedDisabler() | |||
| { | |||
| carla_debug("CarlaPlugin::~ScopedDisabler()"); | |||
| kPlugin->fEnabled = true; | |||
| kPlugin->kData->client->activate(); | |||
| } | |||
| @@ -1483,16 +1488,26 @@ CarlaPlugin::ScopedDisabler::~ScopedDisabler() | |||
| // ------------------------------------------------------------------- | |||
| // Scoped Process Locker | |||
| CarlaPlugin::ScopedProcessLocker::ScopedProcessLocker(CarlaPlugin* const plugin) | |||
| : kPlugin(plugin) | |||
| CarlaPlugin::ScopedProcessLocker::ScopedProcessLocker(CarlaPlugin* const plugin, const bool block) | |||
| : kPlugin(plugin), | |||
| kBlock(block) | |||
| { | |||
| plugin->kData->mutex.lock(); | |||
| carla_debug("CarlaPlugin::ScopedProcessLocker(%p, %s)", plugin, bool2str(block)); | |||
| CARLA_ASSERT(plugin != nullptr); | |||
| if (block) | |||
| plugin->kData->mutex.lock(); | |||
| } | |||
| CarlaPlugin::ScopedProcessLocker::~ScopedProcessLocker() | |||
| { | |||
| kPlugin->kData->needsReset = true; | |||
| kPlugin->kData->mutex.unlock(); | |||
| carla_debug("CarlaPlugin::~ScopedProcessLocker()"); | |||
| if (kBlock) | |||
| { | |||
| kPlugin->kData->needsReset = true; | |||
| kPlugin->kData->mutex.unlock(); | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -233,7 +233,7 @@ public: | |||
| if (fDssiDescriptor->configure != nullptr) | |||
| { | |||
| const ScopedProcessLocker spl(this); | |||
| const ScopedProcessLocker spl(this, true); | |||
| fDssiDescriptor->configure(fHandle, key, value); | |||
| @@ -269,11 +269,11 @@ public: | |||
| fChunk = QByteArray::fromBase64(QByteArray(stringData)); | |||
| //fChunk.toBase64(); | |||
| const ScopedProcessLocker spl(this); | |||
| const ScopedProcessLocker spl(this, true); | |||
| fDssiDescriptor->set_custom_data(fHandle, fChunk.data(), (unsigned long)fChunk.size()); | |||
| } | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block) | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(fDssiDescriptor != nullptr); | |||
| CARLA_ASSERT(fHandle != nullptr); | |||
| @@ -289,7 +289,7 @@ public: | |||
| const uint32_t bank = kData->midiprog.data[index].bank; | |||
| const uint32_t program = kData->midiprog.data[index].program; | |||
| const ScopedProcessLocker spl(this); | |||
| const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| fDssiDescriptor->select_program(fHandle, bank, program); | |||
| @@ -297,7 +297,7 @@ public: | |||
| fDssiDescriptor->select_program(fHandle2, bank, program); | |||
| } | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block); | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -818,7 +818,7 @@ public: | |||
| if (init) | |||
| { | |||
| if (kData->midiprog.count > 0) | |||
| setMidiProgram(0, false, false, false, true); | |||
| setMidiProgram(0, false, false, false); | |||
| } | |||
| else | |||
| { | |||
| @@ -853,7 +853,7 @@ public: | |||
| } | |||
| if (programChanged) | |||
| setMidiProgram(kData->midiprog.current, true, true, true, true); | |||
| setMidiProgram(kData->midiprog.current, true, true, true); | |||
| } | |||
| } | |||
| @@ -1096,7 +1096,7 @@ public: | |||
| if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
| { | |||
| value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| } | |||
| else | |||
| { | |||
| @@ -1127,7 +1127,7 @@ public: | |||
| { | |||
| if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId) | |||
| { | |||
| setMidiProgram(k, false, false, false, false); | |||
| setMidiProgram(k, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0); | |||
| break; | |||
| } | |||
| @@ -297,67 +297,54 @@ public: | |||
| const float fixedValue = kData->param.fixValue(parameterId, value); | |||
| fParamBuffers[parameterId] = fixedValue; | |||
| switch (parameterId) | |||
| { | |||
| case FluidSynthReverbOnOff: | |||
| fluid_synth_set_reverb_on(fSynth, (fixedValue > 0.5f) ? 1 : 0); | |||
| break; | |||
| case FluidSynthReverbRoomSize: | |||
| case FluidSynthReverbDamp: | |||
| case FluidSynthReverbLevel: | |||
| case FluidSynthReverbWidth: | |||
| fluid_synth_set_reverb(fSynth, fParamBuffers[FluidSynthReverbRoomSize], fParamBuffers[FluidSynthReverbDamp], fParamBuffers[FluidSynthReverbWidth], fParamBuffers[FluidSynthReverbLevel]); | |||
| break; | |||
| case FluidSynthChorusOnOff: | |||
| { | |||
| // FIXME | |||
| //const ScopedDisabler m(this, ! kData->engine->isOffline()); | |||
| fluid_synth_set_chorus_on(fSynth, (value > 0.5f) ? 1 : 0); | |||
| break; | |||
| } | |||
| case FluidSynthChorusNr: | |||
| case FluidSynthChorusLevel: | |||
| case FluidSynthChorusSpeedHz: | |||
| case FluidSynthChorusDepthMs: | |||
| case FluidSynthChorusType: | |||
| { | |||
| //FIXME | |||
| //const ScopedDisabler m(this, ! kData->engine->isOffline()); | |||
| fluid_synth_set_chorus(fSynth, fParamBuffers[FluidSynthChorusNr], fParamBuffers[FluidSynthChorusLevel], fParamBuffers[FluidSynthChorusSpeedHz], fParamBuffers[FluidSynthChorusDepthMs], fParamBuffers[FluidSynthChorusType]); | |||
| break; | |||
| } | |||
| case FluidSynthPolyphony: | |||
| { | |||
| //FIXME | |||
| //const ScopedDisabler m(this, ! kData->engine->isOffline()); | |||
| fluid_synth_set_polyphony(fSynth, value); | |||
| break; | |||
| } | |||
| case FluidSynthInterpolation: | |||
| { | |||
| //FIXME | |||
| //const ScopedDisabler m(this, ! kData->engine->isOffline()); | |||
| for (int i=0; i < 16; i++) | |||
| fluid_synth_set_interp_method(fSynth, i, value); | |||
| const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| break; | |||
| } | |||
| switch (parameterId) | |||
| { | |||
| case FluidSynthReverbOnOff: | |||
| fluid_synth_set_reverb_on(fSynth, (fixedValue > 0.5f) ? 1 : 0); | |||
| break; | |||
| case FluidSynthReverbRoomSize: | |||
| case FluidSynthReverbDamp: | |||
| case FluidSynthReverbLevel: | |||
| case FluidSynthReverbWidth: | |||
| fluid_synth_set_reverb(fSynth, fParamBuffers[FluidSynthReverbRoomSize], fParamBuffers[FluidSynthReverbDamp], fParamBuffers[FluidSynthReverbWidth], fParamBuffers[FluidSynthReverbLevel]); | |||
| break; | |||
| case FluidSynthChorusOnOff: | |||
| fluid_synth_set_chorus_on(fSynth, (value > 0.5f) ? 1 : 0); | |||
| break; | |||
| case FluidSynthChorusNr: | |||
| case FluidSynthChorusLevel: | |||
| case FluidSynthChorusSpeedHz: | |||
| case FluidSynthChorusDepthMs: | |||
| case FluidSynthChorusType: | |||
| fluid_synth_set_chorus(fSynth, fParamBuffers[FluidSynthChorusNr], fParamBuffers[FluidSynthChorusLevel], fParamBuffers[FluidSynthChorusSpeedHz], fParamBuffers[FluidSynthChorusDepthMs], fParamBuffers[FluidSynthChorusType]); | |||
| break; | |||
| case FluidSynthPolyphony: | |||
| fluid_synth_set_polyphony(fSynth, value); | |||
| break; | |||
| case FluidSynthInterpolation: | |||
| for (int i=0; i < 16; i++) | |||
| fluid_synth_set_interp_method(fSynth, i, value); | |||
| break; | |||
| default: | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback); | |||
| } | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block) | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(fSynth != nullptr); | |||
| CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->midiprog.count)); | |||
| if (index < -1) | |||
| @@ -368,25 +355,16 @@ public: | |||
| if (kData->ctrlChannel < 0 || kData->ctrlChannel >= 16) | |||
| return; | |||
| // FIXME | |||
| if (index >= 0) | |||
| { | |||
| const uint32_t bank = kData->midiprog.data[index].bank; | |||
| const uint32_t program = kData->midiprog.data[index].program; | |||
| if (kData->engine->isOffline()) | |||
| { | |||
| //const CarlaEngine::ScopedLocker m(x_engine, block); | |||
| fluid_synth_program_select(fSynth, kData->ctrlChannel, fSynthId, bank, program); | |||
| } | |||
| else | |||
| { | |||
| //const ScopedDisabler m(this, block); | |||
| fluid_synth_program_select(fSynth, kData->ctrlChannel, fSynthId, bank, program); | |||
| } | |||
| const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| fluid_synth_program_select(fSynth, kData->ctrlChannel, fSynthId, bank, program); | |||
| } | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block); | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -403,9 +381,6 @@ public: | |||
| // Safely disable plugin for reload | |||
| const ScopedDisabler sd(this); | |||
| if (kData->client->isActive()) | |||
| kData->client->deactivate(); | |||
| deleteBuffers(); | |||
| uint32_t aOuts, params, j; | |||
| @@ -771,8 +746,6 @@ public: | |||
| bufferSizeChanged(kData->engine->getBufferSize()); | |||
| reloadPrograms(true); | |||
| kData->client->activate(); | |||
| carla_debug("FluidSynthPlugin::reload() - end"); | |||
| } | |||
| @@ -862,7 +835,7 @@ public: | |||
| #endif | |||
| } | |||
| setMidiProgram(0, false, false, false, true); | |||
| setMidiProgram(0, false, false, false); | |||
| } | |||
| else | |||
| { | |||
| @@ -891,7 +864,7 @@ public: | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Check if active before | |||
| // Check if not active before | |||
| if (kData->needsReset || ! kData->activeBefore) | |||
| { | |||
| @@ -941,6 +914,7 @@ public: | |||
| bool allNotesOffSent = false; | |||
| uint32_t time, nEvents = kData->event.portIn->getEventCount(); | |||
| uint32_t startTime = 0; | |||
| uint32_t timeOffset = 0; | |||
| uint32_t nextBankIds[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 }; | |||
| @@ -961,12 +935,15 @@ public: | |||
| if (time > timeOffset) | |||
| { | |||
| if (kUses16Outs) | |||
| processSingle(outBuffer, time - timeOffset, timeOffset); | |||
| else | |||
| fluid_synth_write_float(fSynth, time - timeOffset, outBuffer[0] + timeOffset, 0, 1, outBuffer[1] + timeOffset, 0, 1); | |||
| if (processSingle(outBuffer, time - timeOffset, timeOffset)) | |||
| { | |||
| timeOffset = time; | |||
| timeOffset = time; | |||
| if (kData->midiprog.current >= 0 && kData->midiprog.count > 0 && kData->ctrlChannel >= 0 && kData->ctrlChannel < 16) | |||
| nextBankIds[kData->ctrlChannel] = kData->midiprog.data[kData->midiprog.current].bank; | |||
| } | |||
| else | |||
| startTime += timeOffset; | |||
| } | |||
| // Control change | |||
| @@ -989,7 +966,7 @@ public: | |||
| // Control backend stuff | |||
| if (event.channel == kData->ctrlChannel) | |||
| { | |||
| double value; | |||
| float value; | |||
| if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0) | |||
| { | |||
| @@ -1001,7 +978,7 @@ public: | |||
| if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0) | |||
| { | |||
| value = ctrlEvent.value*127/100; | |||
| value = ctrlEvent.value*127.0f/100.0f; | |||
| setVolume(value, false, false); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value); | |||
| continue; | |||
| @@ -1009,23 +986,23 @@ public: | |||
| if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0) | |||
| { | |||
| double left, right; | |||
| value = ctrlEvent.value/0.5 - 1.0; | |||
| float left, right; | |||
| value = ctrlEvent.value/0.5f - 1.0f; | |||
| if (value < 0.0) | |||
| if (value < 0.0f) | |||
| { | |||
| left = -1.0; | |||
| right = (value*2)+1.0; | |||
| left = -1.0f; | |||
| right = (value*2.0f)+1.0f; | |||
| } | |||
| else if (value > 0.0) | |||
| else if (value > 0.0f) | |||
| { | |||
| left = (value*2)-1.0; | |||
| right = 1.0; | |||
| left = (value*2.0f)-1.0f; | |||
| right = 1.0f; | |||
| } | |||
| else | |||
| { | |||
| left = -1.0; | |||
| right = 1.0; | |||
| left = -1.0f; | |||
| right = 1.0f; | |||
| } | |||
| setBalanceLeft(left, false, false); | |||
| @@ -1048,23 +1025,22 @@ public: | |||
| if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) | |||
| continue; | |||
| double value; | |||
| float value; | |||
| if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
| { | |||
| value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| } | |||
| else | |||
| { | |||
| // FIXME - ranges call for this | |||
| value = ctrlEvent.value * (kData->param.ranges[k].max - kData->param.ranges[k].min) + kData->param.ranges[k].min; | |||
| value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value); | |||
| if (kData->param.data[k].hints & PARAMETER_IS_INTEGER) | |||
| value = std::rint(value); | |||
| } | |||
| setParameterValue(k, value, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, k, 0, value); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value); | |||
| } | |||
| break; | |||
| @@ -1087,7 +1063,7 @@ public: | |||
| { | |||
| if (event.channel == kData->ctrlChannel) | |||
| { | |||
| setMidiProgram(k, false, false, false, false); | |||
| setMidiProgram(k, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0); | |||
| } | |||
| else | |||
| @@ -1109,6 +1085,12 @@ public: | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0); | |||
| allNotesOffSent = true; | |||
| #ifdef FLUIDSYNTH_VERSION_NEW_API | |||
| fluid_synth_all_sounds_off(fSynth, event.channel); | |||
| #else | |||
| fluid_synth_cc(f_synth, event.channel, MIDI_CONTROL_ALL_SOUND_OFF, 0); | |||
| #endif | |||
| } | |||
| break; | |||
| @@ -1119,6 +1101,12 @@ public: | |||
| sendMidiAllNotesOff(); | |||
| allNotesOffSent = true; | |||
| #ifdef FLUIDSYNTH_VERSION_NEW_API | |||
| fluid_synth_all_notes_off(fSynth, event.channel); | |||
| #else | |||
| fluid_synth_cc(f_synth, event.channel, MIDI_CONTROL_ALL_NOTES_OFF, 0); | |||
| #endif | |||
| } | |||
| break; | |||
| } | |||
| @@ -1156,15 +1144,10 @@ public: | |||
| } | |||
| else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status)) | |||
| { | |||
| const uint8_t note = midiEvent.data[1]; | |||
| const uint8_t pressure = midiEvent.data[2]; | |||
| //const uint8_t note = midiEvent.data[1]; | |||
| //const uint8_t pressure = midiEvent.data[2]; | |||
| // TODO, not in fluidsynth API? | |||
| continue; | |||
| // unused | |||
| (void)note; | |||
| (void)pressure; | |||
| // TODO, not in fluidsynth API | |||
| } | |||
| else if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fHints & PLUGIN_OPTION_SELF_AUTOMATION) != 0) | |||
| { | |||
| @@ -1186,8 +1169,6 @@ public: | |||
| fluid_synth_pitch_bend(fSynth, channel, (msb << 7) | lsb); | |||
| } | |||
| else | |||
| continue; | |||
| break; | |||
| } | |||
| @@ -1197,21 +1178,73 @@ public: | |||
| kData->postRtEvents.trySplice(); | |||
| if (frames > timeOffset) | |||
| { | |||
| if (kUses16Outs) | |||
| processSingle(outBuffer, frames - timeOffset, timeOffset); | |||
| else | |||
| fluid_synth_write_float(fSynth, frames - timeOffset, outBuffer[0] + timeOffset, 0, 1, outBuffer[1] + timeOffset, 0, 1); | |||
| } | |||
| processSingle(outBuffer, frames - timeOffset, timeOffset); | |||
| } // End of Event Input and Processing | |||
| CARLA_PROCESS_CONTINUE_CHECK; | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Control Output | |||
| { | |||
| k = FluidSynthVoiceCount; | |||
| fParamBuffers[k] = fluid_synth_get_active_voice_count(fSynth); | |||
| kData->param.ranges[k].fixValue(fParamBuffers[k]); | |||
| if (kData->param.data[k].midiCC > 0) | |||
| { | |||
| double value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
| kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
| } | |||
| } // End of Control Output | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| kData->activeBefore = kData->active; | |||
| } | |||
| bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) | |||
| { | |||
| uint32_t i, k; | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Try lock, silence otherwise | |||
| if (kData->engine->isOffline()) | |||
| { | |||
| kData->mutex.lock(); | |||
| } | |||
| else if (! kData->mutex.tryLock()) | |||
| { | |||
| for (i=0; i < kData->audioOut.count; i++) | |||
| { | |||
| for (k=0; k < frames; k++) | |||
| outBuffer[i][k+timeOffset] = 0.0f; | |||
| } | |||
| return false; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Fill plugin buffers and Run plugin | |||
| if (kUses16Outs) | |||
| { | |||
| for (i=0; i < kData->audioOut.count; i++) | |||
| carla_zeroFloat(fAudio16Buffers[i], frames); | |||
| fluid_synth_process(fSynth, frames, 0, nullptr, kData->audioOut.count, fAudio16Buffers); | |||
| } | |||
| else | |||
| fluid_synth_write_float(fSynth, frames, outBuffer[0] + timeOffset, 0, 1, outBuffer[1] + timeOffset, 0, 1); | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Post-processing (volume and balance) | |||
| { | |||
| // note - balance not possible with kUses16Outs, so we can safely skip fAudioOutBuffers | |||
| const bool doVolume = (fHints & PLUGIN_CAN_VOLUME) > 0 && kData->postProc.volume != 1.0f; | |||
| const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f); | |||
| @@ -1246,7 +1279,12 @@ public: | |||
| } | |||
| // Volume | |||
| if (doVolume) | |||
| if (kUses16Outs) | |||
| { | |||
| for (k=0; k < frames; k++) | |||
| outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k] * kData->postProc.volume; | |||
| } | |||
| else if (doVolume) | |||
| { | |||
| for (k=0; k < frames; k++) | |||
| outBuffer[i][k] *= kData->postProc.volume; | |||
| @@ -1255,41 +1293,10 @@ public: | |||
| } // End of Post-processing | |||
| CARLA_PROCESS_CONTINUE_CHECK; | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Control Output | |||
| { | |||
| k = FluidSynthVoiceCount; | |||
| fParamBuffers[k] = fluid_synth_get_active_voice_count(fSynth); | |||
| kData->param.ranges[k].fixValue(fParamBuffers[k]); | |||
| if (kData->param.data[k].midiCC > 0) | |||
| { | |||
| double value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
| kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
| } | |||
| } // End of Control Output | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| kData->activeBefore = kData->active; | |||
| } | |||
| void processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) | |||
| { | |||
| for (uint32_t i=0; i < kData->audioOut.count; i++) | |||
| carla_zeroFloat(fAudio16Buffers[i], frames); | |||
| fluid_synth_process(fSynth, frames, 0, nullptr, kData->audioOut.count, fAudio16Buffers); | |||
| for (uint32_t i=0, k; i < kData->audioOut.count; i++) | |||
| { | |||
| for (k=0; k < frames; k++) | |||
| outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k]; | |||
| } | |||
| kData->mutex.unlock(); | |||
| return true; | |||
| } | |||
| void bufferSizeChanged(const uint32_t newBufferSize) | |||
| @@ -1407,8 +1414,6 @@ private: | |||
| double fParamBuffers[FluidSynthParametersMax]; | |||
| }; | |||
| /**@}*/ | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_FLUIDSYNTH | |||
| @@ -926,7 +926,7 @@ public: | |||
| if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
| { | |||
| value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| } | |||
| else | |||
| { | |||
| @@ -248,6 +248,34 @@ public: | |||
| std::strncpy(strBuf, (const char*)fRealName, STR_MAX); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Set data (plugin-specific stuff) | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->midiprog.count)); | |||
| if (index < -1) | |||
| index = -1; | |||
| else if (index > static_cast<int32_t>(kData->midiprog.count)) | |||
| return; | |||
| if (kData->ctrlChannel < 0 || kData->ctrlChannel >= 16) | |||
| return; | |||
| if (index >= 0) | |||
| { | |||
| // TODO | |||
| //const uint32_t bank = kData->midiprog.data[index].bank; | |||
| //const uint32_t program = kData->midiprog.data[index].program; | |||
| //const ScopedProcessLocker spl(this); | |||
| //fluid_synth_program_select(fSynth, kData->ctrlChannel, fSynthId, bank, program); | |||
| } | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state | |||
| @@ -262,9 +290,6 @@ public: | |||
| // Safely disable plugin for reload | |||
| const ScopedDisabler sd(this); | |||
| if (kData->client->isActive()) | |||
| kData->client->deactivate(); | |||
| deleteBuffers(); | |||
| uint32_t aOuts; | |||
| @@ -350,8 +375,6 @@ public: | |||
| bufferSizeChanged(kData->engine->getBufferSize()); | |||
| reloadPrograms(true); | |||
| kData->client->activate(); | |||
| carla_debug("LinuxSamplerPlugin::reload() - end"); | |||
| } | |||
| @@ -396,7 +419,7 @@ public: | |||
| if (init) | |||
| { | |||
| setMidiProgram(0, false, false, false, true); | |||
| setMidiProgram(0, false, false, false); | |||
| } | |||
| else | |||
| { | |||
| @@ -598,19 +621,18 @@ public: | |||
| if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
| { | |||
| value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| } | |||
| else | |||
| { | |||
| // FIXME - ranges call for this | |||
| value = ctrlEvent.value * (kData->param.ranges[k].max - kData->param.ranges[k].min) + kData->param.ranges[k].min; | |||
| value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value); | |||
| if (kData->param.data[k].hints & PARAMETER_IS_INTEGER) | |||
| value = std::rint(value); | |||
| } | |||
| setParameterValue(k, value, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, k, 0, value); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value); | |||
| } | |||
| break; | |||
| @@ -630,7 +652,7 @@ public: | |||
| { | |||
| if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId) | |||
| { | |||
| setMidiProgram(k, false, false, false, false); | |||
| setMidiProgram(k, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0); | |||
| break; | |||
| } | |||
| @@ -1128,9 +1128,6 @@ public: | |||
| // Safely disable plugin for reload | |||
| const ScopedDisabler m(this); | |||
| if (x_client->isActive()) | |||
| x_client->deactivate(); | |||
| // Remove client ports | |||
| removeClientPorts(); | |||
| @@ -1822,8 +1819,6 @@ public: | |||
| reloadPrograms(true); | |||
| x_client->activate(); | |||
| carla_debug("Lv2Plugin::reload() - end"); | |||
| } | |||
| @@ -414,7 +414,7 @@ public: | |||
| CarlaPlugin::setCustomData(type, key, value, sendGui); | |||
| } | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool block) | |||
| void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) | |||
| { | |||
| CARLA_ASSERT(fDescriptor != nullptr); | |||
| CARLA_ASSERT(fHandle != nullptr); | |||
| @@ -425,31 +425,20 @@ public: | |||
| else if (index > static_cast<int32_t>(kData->midiprog.count)) | |||
| return; | |||
| // FIXME | |||
| if (fDescriptor != nullptr && fHandle != nullptr && index >= 0) | |||
| { | |||
| const uint32_t bank = kData->midiprog.data[index].bank; | |||
| const uint32_t program = kData->midiprog.data[index].program; | |||
| if (kData->engine->isOffline()) | |||
| { | |||
| //const CarlaEngine::ScopedLocker m(x_engine, block); | |||
| fDescriptor->set_midi_program(fHandle, bank, program); | |||
| const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| if (fHandle2 != nullptr) | |||
| fDescriptor->set_midi_program(fHandle2, bank, program); | |||
| } | |||
| else | |||
| { | |||
| //const ScopedDisabler m(this, block); | |||
| fDescriptor->set_midi_program(fHandle, bank, program); | |||
| fDescriptor->set_midi_program(fHandle, bank, program); | |||
| if (fHandle2 != nullptr) | |||
| fDescriptor->set_midi_program(fHandle2, bank, program); | |||
| } | |||
| if (fHandle2 != nullptr) | |||
| fDescriptor->set_midi_program(fHandle2, bank, program); | |||
| } | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block); | |||
| CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -500,9 +489,6 @@ public: | |||
| // Safely disable plugin for reload | |||
| const ScopedDisabler sd(this); | |||
| if (kData->client->isActive()) | |||
| kData->client->deactivate(); | |||
| deleteBuffers(); | |||
| const double sampleRate = kData->engine->getSampleRate(); | |||
| @@ -865,8 +851,6 @@ public: | |||
| bufferSizeChanged(kData->engine->getBufferSize()); | |||
| reloadPrograms(true); | |||
| kData->client->activate(); | |||
| carla_debug("NativePlugin::reload() - end"); | |||
| } | |||
| @@ -912,7 +896,7 @@ public: | |||
| if (init) | |||
| { | |||
| if (kData->midiprog.count > 0) | |||
| setMidiProgram(0, false, false, false, true); | |||
| setMidiProgram(0, false, false, false); | |||
| } | |||
| else | |||
| { | |||
| @@ -947,7 +931,7 @@ public: | |||
| } | |||
| if (programChanged) | |||
| setMidiProgram(kData->midiprog.current, true, true, true, true); | |||
| setMidiProgram(kData->midiprog.current, true, true, true); | |||
| } | |||
| } | |||
| @@ -1195,19 +1179,18 @@ public: | |||
| if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) | |||
| { | |||
| value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max; | |||
| } | |||
| else | |||
| { | |||
| // FIXME - ranges call for this | |||
| value = ctrlEvent.value * (kData->param.ranges[k].max - kData->param.ranges[k].min) + kData->param.ranges[k].min; | |||
| value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value); | |||
| if (kData->param.data[k].hints & PARAMETER_IS_INTEGER) | |||
| value = std::rint(value); | |||
| } | |||
| setParameterValue(k, value, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, k, 0, value); | |||
| postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value); | |||
| } | |||
| break; | |||
| @@ -1227,7 +1210,7 @@ public: | |||
| { | |||
| if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId) | |||
| { | |||
| setMidiProgram(k, false, false, false, false); | |||
| setMidiProgram(k, false, false, false); | |||
| postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0); | |||
| break; | |||
| } | |||
| @@ -480,9 +480,6 @@ public: | |||
| // Safely disable plugin for reload | |||
| const ScopedDisabler m(this); | |||
| if (x_client->isActive()) | |||
| x_client->deactivate(); | |||
| // Remove client ports | |||
| removeClientPorts(); | |||
| @@ -788,8 +785,6 @@ public: | |||
| reloadPrograms(true); | |||
| x_client->activate(); | |||
| carla_debug("VstPlugin::reload() - end"); | |||
| } | |||
| @@ -1429,7 +1429,7 @@ void carla_set_program(unsigned int pluginId, uint32_t programId) | |||
| if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId)) | |||
| { | |||
| if (programId < plugin->programCount()) | |||
| return plugin->setProgram(static_cast<int32_t>(programId), true, true, false, true); | |||
| return plugin->setProgram(static_cast<int32_t>(programId), true, true, false); | |||
| carla_stderr2("carla_set_program(%i, %i) - programId out of bounds", pluginId, programId); | |||
| return; | |||
| @@ -1449,7 +1449,7 @@ void carla_set_midi_program(unsigned int pluginId, uint32_t midiProgramId) | |||
| if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId)) | |||
| { | |||
| if (midiProgramId < plugin->midiProgramCount()) | |||
| return plugin->setMidiProgram(static_cast<int32_t>(midiProgramId), true, true, false, true); | |||
| return plugin->setMidiProgram(static_cast<int32_t>(midiProgramId), true, true, false); | |||
| carla_stderr2("carla_set_midi_program(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId); | |||
| return; | |||
| @@ -320,7 +320,7 @@ public: | |||
| CARLA_ASSERT(fPlugin != nullptr); | |||
| if (fPlugin != nullptr) | |||
| fPlugin->setProgram(index, true, true, false, true); | |||
| fPlugin->setProgram(index, true, true, false); | |||
| } | |||
| void setMidiProgram(const uint32_t index) | |||
| @@ -329,7 +329,7 @@ public: | |||
| CARLA_ASSERT(fPlugin != nullptr); | |||
| if (fPlugin != nullptr) | |||
| fPlugin->setMidiProgram(index, true, true, false, true); | |||
| fPlugin->setMidiProgram(index, true, true, false); | |||
| } | |||
| void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) | |||