| @@ -48,13 +48,15 @@ static const float kVolumeMin = 0.0f; // -inf dB | |||
| class AudioOutputDevicePlugin : public AudioOutputDevice | |||
| { | |||
| public: | |||
| AudioOutputDevicePlugin(const CarlaEngine* const engine, const CarlaPlugin* const plugin) | |||
| AudioOutputDevicePlugin(const CarlaEngine* const engine, const CarlaPlugin* const plugin, const bool uses16Outs) | |||
| : AudioOutputDevice(std::map<String, DeviceCreationParameter*>()), | |||
| fEngine(engine), | |||
| fPlugin(plugin) | |||
| { | |||
| CARLA_ASSERT(engine != nullptr); | |||
| CARLA_ASSERT(plugin != nullptr); | |||
| AcquireChannels(uses16Outs ? 32 : 2); | |||
| } | |||
| ~AudioOutputDevicePlugin() override {} | |||
| @@ -183,18 +185,18 @@ public: | |||
| fMaker(nullptr), | |||
| fRealName(nullptr), | |||
| fEngine(nullptr), | |||
| fAudioOutputDevice(nullptr), | |||
| fMidiInputDevice(nullptr), | |||
| fMidiInputPort(nullptr), | |||
| fInstrument(nullptr) | |||
| { | |||
| carla_debug("LinuxSamplerPlugin::LinuxSamplerPlugin(%p, %i, %s, %s)", engine, id, format, bool2str(use16Outs)); | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| fCurMidiProgs[0] = 0; | |||
| fSamplerChannels[i] = nullptr; | |||
| fEngineChannels[i] = nullptr; | |||
| fAudioOutputDevices[i] = nullptr; | |||
| fCurMidiProgs[0] = 0; | |||
| fSamplerChannels[i] = nullptr; | |||
| fEngineChannels[i] = nullptr; | |||
| } | |||
| } | |||
| @@ -220,7 +222,7 @@ public: | |||
| { | |||
| if (fMidiInputPort != nullptr) | |||
| { | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| if (fSamplerChannels[i] != nullptr) | |||
| { | |||
| @@ -233,21 +235,9 @@ public: | |||
| fSampler.RemoveSamplerChannel(fSamplerChannels[i]); | |||
| fSamplerChannels[i] = nullptr; | |||
| if (fAudioOutputDevices[i] != nullptr && fUses16Outs) | |||
| { | |||
| delete fAudioOutputDevices[i]; | |||
| fAudioOutputDevices[i] = nullptr; | |||
| } | |||
| } | |||
| } | |||
| if (fAudioOutputDevices[0] != nullptr) | |||
| { | |||
| delete fAudioOutputDevices[0]; | |||
| fAudioOutputDevices[0] = nullptr; | |||
| } | |||
| delete fMidiInputPort; | |||
| fMidiInputPort = nullptr; | |||
| } | |||
| @@ -256,6 +246,12 @@ public: | |||
| fMidiInputDevice = nullptr; | |||
| } | |||
| if (fAudioOutputDevice != nullptr) | |||
| { | |||
| delete fAudioOutputDevice; | |||
| fAudioOutputDevice = nullptr; | |||
| } | |||
| fInstrument = nullptr; | |||
| LinuxSampler::EngineFactory::Destroy(fEngine); | |||
| @@ -420,12 +416,12 @@ public: | |||
| const uint32_t program = pData->midiprog.data[index].program; | |||
| const uint32_t rIndex = bank*128 + program; | |||
| if (pData->engine->isOffline()) | |||
| /*if (pData->engine->isOffline()) | |||
| { | |||
| fEngineChannels[i]->PrepareLoadInstrument(pData->filename, rIndex); | |||
| fEngineChannels[i]->LoadInstrument(); | |||
| } | |||
| else | |||
| else*/ | |||
| { | |||
| fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], fEngineChannels[i]); | |||
| } | |||
| @@ -463,12 +459,12 @@ public: | |||
| const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); | |||
| if (pData->engine->isOffline()) | |||
| /*if (pData->engine->isOffline()) | |||
| { | |||
| engineChannel->PrepareLoadInstrument(pData->filename, rIndex); | |||
| engineChannel->LoadInstrument(); | |||
| } | |||
| else | |||
| else*/ | |||
| { | |||
| fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], engineChannel); | |||
| } | |||
| @@ -668,12 +664,13 @@ public: | |||
| if (init) | |||
| { | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| CARLA_SAFE_ASSERT_CONTINUE(fEngineChannels[i] != nullptr); | |||
| fEngineChannels[i]->PrepareLoadInstrument(pData->filename, 0); | |||
| fEngineChannels[i]->LoadInstrument(); | |||
| /*fEngineChannels[i]->PrepareLoadInstrument(pData->filename, 0); | |||
| fEngineChannels[i]->LoadInstrument();*/ | |||
| fInstrument->LoadInstrumentInBackground(fInstrumentIds[0], fEngineChannels[i]); | |||
| fCurMidiProgs[i] = 0; | |||
| } | |||
| @@ -691,7 +688,7 @@ public: | |||
| #if 0 | |||
| void activate() override | |||
| { | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| if (fAudioOutputDevices[i] != nullptr) | |||
| fAudioOutputDevices[i]->Play(); | |||
| @@ -700,7 +697,7 @@ public: | |||
| void deactivate() override | |||
| { | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| if (fAudioOutputDevices[i] != nullptr) | |||
| fAudioOutputDevices[i]->Stop(); | |||
| @@ -928,12 +925,12 @@ public: | |||
| { | |||
| LinuxSampler::EngineChannel* const engineChannel(fEngineChannels[pData->ctrlChannel]); | |||
| if (pData->engine->isOffline()) | |||
| /*if (pData->engine->isOffline()) | |||
| { | |||
| engineChannel->PrepareLoadInstrument(pData->filename, rIndex); | |||
| engineChannel->LoadInstrument(); | |||
| } | |||
| else | |||
| else*/ | |||
| { | |||
| fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], engineChannel); | |||
| } | |||
| @@ -992,12 +989,19 @@ public: | |||
| if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0) | |||
| continue; | |||
| fMidiInputPort->DispatchRaw(const_cast<uint8_t*>(midiEvent.data), sampleAccurate ? startTime : time); | |||
| // put back channel in data | |||
| uint8_t data[EngineMidiEvent::kDataSize]; | |||
| std::memcpy(data, event.midi.data, EngineMidiEvent::kDataSize); | |||
| if (status < 0xF0 && channel < MAX_MIDI_CHANNELS) | |||
| data[0] = uint8_t(data[0] + channel); | |||
| fMidiInputPort->DispatchRaw(data, sampleAccurate ? startTime : time); | |||
| if (status == MIDI_STATUS_NOTE_ON) | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, data[1], data[2]); | |||
| else if (status == MIDI_STATUS_NOTE_OFF) | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f); | |||
| pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel,data[1], 0.0f); | |||
| break; | |||
| } | |||
| @@ -1038,25 +1042,14 @@ public: | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Run plugin | |||
| if (fUses16Outs) | |||
| { | |||
| for (int i=0; i < 16; ++i) | |||
| { | |||
| if (fAudioOutputDevices[i] != nullptr) | |||
| { | |||
| fAudioOutputDevices[i]->Channel(0)->SetBuffer(outBuffer[i*2 ] + timeOffset); | |||
| fAudioOutputDevices[i]->Channel(1)->SetBuffer(outBuffer[i*2+1] + timeOffset); | |||
| fAudioOutputDevices[i]->Render(frames); | |||
| } | |||
| } | |||
| } | |||
| else | |||
| for (uint32_t i=0; i < pData->audioOut.count; ++i) | |||
| { | |||
| fAudioOutputDevices[0]->Channel(0)->SetBuffer(outBuffer[0] + timeOffset); | |||
| fAudioOutputDevices[0]->Channel(1)->SetBuffer(outBuffer[1] + timeOffset); | |||
| fAudioOutputDevices[0]->Render(frames); | |||
| if (LinuxSampler::AudioChannel* const outDev = fAudioOutputDevice->Channel(i)) | |||
| outDev->SetBuffer(outBuffer[i] + timeOffset); | |||
| } | |||
| fAudioOutputDevice->Render(frames); | |||
| #ifndef BUILD_BRIDGE | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Post-processing (dry/wet, volume and balance) | |||
| @@ -1112,16 +1105,18 @@ public: | |||
| return true; | |||
| } | |||
| void bufferSizeChanged(const uint32_t newBufferSize) override | |||
| void bufferSizeChanged(const uint32_t) override | |||
| { | |||
| // TODO | |||
| (void)newBufferSize; | |||
| CARLA_SAFE_ASSERT_RETURN(fAudioOutputDevice != nullptr,); | |||
| fAudioOutputDevice->ReconnectAll(); | |||
| } | |||
| void sampleRateChanged(const double newSampleRate) override | |||
| void sampleRateChanged(const double) override | |||
| { | |||
| // TODO | |||
| (void)newSampleRate; | |||
| CARLA_SAFE_ASSERT_RETURN(fAudioOutputDevice != nullptr,); | |||
| fAudioOutputDevice->ReconnectAll(); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -1185,38 +1180,36 @@ public: | |||
| // --------------------------------------------------------------- | |||
| // Init LinuxSampler stuff | |||
| fAudioOutputDevice = new LinuxSampler::AudioOutputDevicePlugin(pData->engine, this, fUses16Outs); | |||
| fMidiInputDevice = new LinuxSampler::MidiInputDevicePlugin(&fSampler); | |||
| fMidiInputPort = fMidiInputDevice->CreateMidiPortPlugin(); | |||
| // always needs at least 1 output device | |||
| fAudioOutputDevices[0] = new LinuxSampler::AudioOutputDevicePlugin(pData->engine, this); | |||
| for (int i=0; i < 16; ++i) | |||
| for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
| { | |||
| LinuxSampler::AudioOutputDevicePlugin* outputDevice; | |||
| if (fUses16Outs) | |||
| { | |||
| fAudioOutputDevices[i] = new LinuxSampler::AudioOutputDevicePlugin(pData->engine, this); | |||
| outputDevice = fAudioOutputDevices[i]; | |||
| } | |||
| else | |||
| { | |||
| outputDevice = fAudioOutputDevices[0]; | |||
| } | |||
| fSamplerChannels[i] = fSampler.AddSamplerChannel(); | |||
| CARLA_SAFE_ASSERT_CONTINUE(fSamplerChannels[i] != nullptr); | |||
| fSamplerChannels[i]->SetEngineType(ctype); | |||
| fSamplerChannels[i]->SetAudioOutputDevice(outputDevice); | |||
| fSamplerChannels[i]->SetAudioOutputDevice(fAudioOutputDevice); | |||
| fEngineChannels[i] = fSamplerChannels[i]->GetEngineChannel(); | |||
| CARLA_SAFE_ASSERT_CONTINUE(fEngineChannels[i] != nullptr); | |||
| fEngineChannels[i]->Connect(outputDevice); | |||
| fEngineChannels[i]->Connect(fAudioOutputDevice); | |||
| fEngineChannels[i]->Volume(LinuxSampler::kVolumeMax); | |||
| if (fUses16Outs) | |||
| { | |||
| fEngineChannels[i]->SetOutputChannel(0, i*2); | |||
| fEngineChannels[i]->SetOutputChannel(1, i*2 +1); | |||
| } | |||
| else | |||
| { | |||
| fEngineChannels[i]->SetOutputChannel(0, 0); | |||
| fEngineChannels[i]->SetOutputChannel(1, 1); | |||
| } | |||
| fMidiInputPort->Connect(fEngineChannels[i], static_cast<LinuxSampler::midi_chan_t>(i)); | |||
| } | |||
| @@ -1331,15 +1324,15 @@ private: | |||
| const char* fMaker; | |||
| const char* fRealName; | |||
| int32_t fCurMidiProgs[16]; | |||
| int32_t fCurMidiProgs[MAX_MIDI_CHANNELS]; | |||
| LinuxSampler::Sampler fSampler; | |||
| LinuxSampler::Engine* fEngine; | |||
| LinuxSampler::SamplerChannel* fSamplerChannels[16]; | |||
| LinuxSampler::EngineChannel* fEngineChannels[16]; | |||
| LinuxSampler::SamplerChannel* fSamplerChannels[MAX_MIDI_CHANNELS]; | |||
| LinuxSampler::EngineChannel* fEngineChannels[MAX_MIDI_CHANNELS]; | |||
| LinuxSampler::AudioOutputDevicePlugin* fAudioOutputDevices[16]; | |||
| LinuxSampler::AudioOutputDevicePlugin* fAudioOutputDevice; | |||
| LinuxSampler::MidiInputDevicePlugin* fMidiInputDevice; | |||
| LinuxSampler::MidiInputPortPlugin* fMidiInputPort; | |||