Browse Source

Some work for LS per-channel preset and 16outs, incomplete

tags/1.9.4
falkTX 11 years ago
parent
commit
d9d9bd78cc
4 changed files with 386 additions and 193 deletions
  1. +57
    -59
      source/backend/plugin/FluidSynthPlugin.cpp
  2. +2
    -5
      source/backend/plugin/LadspaPlugin.cpp
  3. +325
    -128
      source/backend/plugin/LinuxSamplerPlugin.cpp
  4. +2
    -1
      source/bridges/Makefile

+ 57
- 59
source/backend/plugin/FluidSynthPlugin.cpp View File

@@ -21,6 +21,8 @@

#include <fluidsynth.h>

#include <QtCore/QStringList>

#if (FLUIDSYNTH_VERSION_MAJOR >= 1 && FLUIDSYNTH_VERSION_MINOR >= 1 && FLUIDSYNTH_VERSION_MICRO >= 4)
# define FLUIDSYNTH_VERSION_NEW_API
#endif
@@ -38,7 +40,7 @@ class FluidSynthPlugin : public CarlaPlugin
public:
FluidSynthPlugin(CarlaEngine* const engine, const unsigned int id, const bool use16Outs)
: CarlaPlugin(engine, id),
kUses16Outs(use16Outs),
fUses16Outs(use16Outs),
fSettings(nullptr),
fSynth(nullptr),
fSynthId(-1),
@@ -434,45 +436,48 @@ public:
void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
{
CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
CARLA_SAFE_ASSERT_RETURN(type != nullptr,);
CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
carla_debug("DssiPlugin::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',);
carla_debug("FluidSynthPlugin::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
return carla_stderr2("FluidSynthPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));

if (std::strcmp(key, "midiPrograms") != 0)
return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));

// QStringList midiProgramList(QString(value).split(":", QString::SkipEmptyParts));
//
// if (midiProgramList.count() == MAX_MIDI_CHANNELS)
// {
// uint i = 0;
// foreach (const QString& midiProg, midiProgramList)
// {
// bool ok;
// uint index = midiProg.toUInt(&ok);
//
// if (ok && index < pData->midiprog.count)
// {
// const uint32_t bank = pData->midiprog.data[index].bank;
// const uint32_t program = pData->midiprog.data[index].program;
//
// fluid_synth_program_select(fSynth, i, fSynthId, bank, program);
// fCurMidiProgs[i] = index;
//
// if (pData->ctrlChannel == static_cast<int32_t>(i))
// {
// pData->midiprog.current = index;
// pData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
// }
// }
//
// ++i;
// }
// }
return carla_stderr2("FluidSynthPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));

if (! fUses16Outs)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

QStringList midiProgramList(QString(value).split(":", QString::SkipEmptyParts));

if (midiProgramList.count() == MAX_MIDI_CHANNELS)
{
uint i = 0;
foreach (const QString& midiProg, midiProgramList)
{
bool ok;
uint index = midiProg.toUInt(&ok);

if (ok && index < pData->midiprog.count)
{
const uint32_t bank = pData->midiprog.data[index].bank;
const uint32_t program = pData->midiprog.data[index].program;

fluid_synth_program_select(fSynth, i, fSynthId, bank, program);
fCurMidiProgs[i] = index;

if (pData->ctrlChannel == static_cast<int32_t>(i))
{
pData->midiprog.current = index;
pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
}
}

++i;
}
}

CarlaPlugin::setCustomData(type, key, value, sendGui);
}
@@ -496,6 +501,7 @@ public:
const uint32_t program = pData->midiprog.data[index].program;

//const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));

fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program);
fCurMidiProgs[pData->ctrlChannel] = index;
}
@@ -528,7 +534,7 @@ public:
clearBuffers();

uint32_t aOuts, params, j;
aOuts = kUses16Outs ? 32 : 2;
aOuts = fUses16Outs ? 32 : 2;
params = FluidSynthParametersMax;

pData->audioOut.createNew(aOuts);
@@ -540,7 +546,7 @@ public:
// ---------------------------------------
// Audio Outputs

if (kUses16Outs)
if (fUses16Outs)
{
for (j=0; j < 32; ++j)
{
@@ -879,7 +885,9 @@ public:
// extra plugin hints
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

if (! fUses16Outs)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);
@@ -1385,15 +1393,10 @@ public:
// --------------------------------------------------------------------------------------------------------
// Fill plugin buffers and Run plugin

if (kUses16Outs)
if (fUses16Outs)
{
for (i=0; i < pData->audioOut.count; ++i)
{
#ifdef HAVE_JUCE
FloatVectorOperations::clear(fAudio16Buffers[i], frames);
#else
#endif
}
FLOAT_CLEAR(fAudio16Buffers[i], frames);

fluid_synth_process(fSynth, frames, 0, nullptr, pData->audioOut.count, fAudio16Buffers);
}
@@ -1405,7 +1408,7 @@ public:
// Post-processing (volume and balance)

{
// note - balance not possible with kUses16Outs, so we can safely skip fAudioOutBuffers
// note - balance not possible with fUses16Outs, so we can safely skip fAudioOutBuffers
const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) > 0 && pData->postProc.volume != 1.0f;
const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) > 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);

@@ -1417,12 +1420,7 @@ public:
if (doBalance)
{
if (i % 2 == 0)
{
#ifdef HAVE_JUCE
FloatVectorOperations::copy(oldBufLeft, outBuffer[i]+timeOffset, frames);
#else
#endif
}
FLOAT_COPY(oldBufLeft, outBuffer[i]+timeOffset, frames);

float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
@@ -1445,7 +1443,7 @@ public:
}

// Volume
if (kUses16Outs)
if (fUses16Outs)
{
for (k=0; k < frames; ++k)
outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k] * pData->postProc.volume;
@@ -1459,7 +1457,7 @@ public:

} // End of Post-processing
#else
if (kUses16Outs)
if (fUses16Outs)
{
for (i=0; i < pData->audioOut.count; ++i)
{
@@ -1477,7 +1475,7 @@ public:

void bufferSizeChanged(const uint32_t newBufferSize) override
{
if (! kUses16Outs)
if (! fUses16Outs)
return;

for (uint32_t i=0; i < pData->audioOut.count; ++i)
@@ -1519,7 +1517,7 @@ public:

const void* getExtraStuff() const noexcept override
{
return kUses16Outs ? (const void*)0x1 : nullptr;
return fUses16Outs ? (const void*)0x1 : nullptr;
}

bool init(const char* const filename, const char* const name, const char* const label)
@@ -1576,7 +1574,7 @@ public:

CarlaString label2(label);

if (kUses16Outs && ! label2.endsWith(" (16 outs)"))
if (fUses16Outs && ! label2.endsWith(" (16 outs)"))
label2 += " (16 outs)";

pData->filename = carla_strdup(filename);
@@ -1647,7 +1645,7 @@ private:
FluidSynthParametersMax = 14
};

const bool kUses16Outs;
const bool fUses16Outs;

fluid_settings_t* fSettings;
fluid_synth_t* fSynth;


+ 2
- 5
source/backend/plugin/LadspaPlugin.cpp View File

@@ -1334,14 +1334,11 @@ public:

bool init(const char* const filename, const char* const name, const char* const label, const LADSPA_RDF_Descriptor* const rdfDescriptor)
{
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);

// ---------------------------------------------------------------
// first checks

if (pData->engine == nullptr)
{
return false;
}

if (pData->client != nullptr)
{
pData->engine->setLastError("Plugin client is already registered");


+ 325
- 128
source/backend/plugin/LinuxSamplerPlugin.cpp View File

@@ -15,6 +15,12 @@
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/

/* TODO
* - implement buffer size changes
* - implement sample rate changes
* - call outDev->ReconnectAll() after changing buffer size or sample rate
* - use CARLA_SAFE_ASSERT_RETURN with err
*/
#include "CarlaPluginInternal.hpp"

#ifdef WANT_LINUXSAMPLER
@@ -22,6 +28,9 @@
#include "linuxsampler/EngineFactory.h"
#include <linuxsampler/Sampler.h>

#include <QtCore/QFileInfo>
#include <QtCore/QStringList>

namespace LinuxSampler {

using CarlaBackend::CarlaEngine;
@@ -30,8 +39,8 @@ using CarlaBackend::CarlaPlugin;
// -----------------------------------------------------------------------
// LinuxSampler static values

static const float VOLUME_MAX = 3.16227766f; // +10 dB
static const float VOLUME_MIN = 0.0f; // -inf dB
static const float kVolumeMax = 3.16227766f; // +10 dB
static const float kVolumeMin = 0.0f; // -inf dB

// -----------------------------------------------------------------------
// LinuxSampler AudioOutputDevice Plugin
@@ -39,7 +48,7 @@ static const float VOLUME_MIN = 0.0f; // -inf dB
class AudioOutputDevicePlugin : public AudioOutputDevice
{
public:
AudioOutputDevicePlugin(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin)
AudioOutputDevicePlugin(const CarlaEngine* const engine, const CarlaPlugin* const plugin)
: AudioOutputDevice(std::map<String, DeviceCreationParameter*>()),
fEngine(engine),
fPlugin(plugin)
@@ -48,6 +57,8 @@ public:
CARLA_ASSERT(plugin != nullptr);
}

~AudioOutputDevicePlugin() override {}

// -------------------------------------------------------------------
// LinuxSampler virtual methods

@@ -71,7 +82,7 @@ public:

uint SampleRate() override
{
return (uint)fEngine->getSampleRate();
return uint(fEngine->getSampleRate());
}

String Driver() override
@@ -92,9 +103,25 @@ public:
return RenderAudio(samples);
}

// -------------------------------------------------------------------

private:
CarlaEngine* const fEngine;
CarlaPlugin* const fPlugin;
const CarlaEngine* const fEngine;
const CarlaPlugin* const fPlugin;
};

// -----------------------------------------------------------------------
// LinuxSampler MidiInputPort Plugin

class MidiInputPortPlugin : public MidiInputPort
{
public:
MidiInputPortPlugin(MidiInputDevice* const device, const int portNumber)
: MidiInputPort(device, portNumber)
{
}

~MidiInputPortPlugin() override {}
};

// -----------------------------------------------------------------------
@@ -126,28 +153,13 @@ public:

MidiInputPort* CreateMidiPort() override
{
return new MidiInputPortPlugin(this, (int)Ports.size());
return new MidiInputPortPlugin(this, int(Ports.size()));
}

// -------------------------------------------------------------------
// Properly delete port (destructor is protected)

void DeleteMidiPort(MidiInputPort* const port)
MidiInputPortPlugin* CreateMidiPortPlugin()
{
delete (MidiInputPortPlugin*)port;
return new MidiInputPortPlugin(this, int(Ports.size()));
}

// -------------------------------------------------------------------
// MIDI Port implementation for this plugin MIDI input driver
// (Constructor and destructor are protected)

class MidiInputPortPlugin : public MidiInputPort
{
protected:
MidiInputPortPlugin(MidiInputDevicePlugin* const device, const int portNumber)
: MidiInputPort(device, portNumber) {}
friend class MidiInputDevicePlugin;
};
};

} // namespace LinuxSampler
@@ -167,16 +179,20 @@ public:
: CarlaPlugin(engine, id),
fFormat(carla_strdup(format)),
fUses16Outs(use16Outs),
fSampler(new LinuxSampler::Sampler()),
fSamplerChannel(nullptr),
fEngine(nullptr),
fEngineChannel(nullptr),
fAudioOutputDevice(new LinuxSampler::AudioOutputDevicePlugin(engine, this)),
fMidiInputDevice(new LinuxSampler::MidiInputDevicePlugin(fSampler)),
fMidiInputPort(fMidiInputDevice->CreateMidiPort()),
fMidiInputDevice(nullptr),
fMidiInputPort(nullptr),
fInstrument(nullptr)
{
carla_debug("LinuxSamplerPlugin::LinuxSamplerPlugin(%p, %i, %s)", engine, id, bool2str(isGIG));
carla_debug("LinuxSamplerPlugin::LinuxSamplerPlugin(%p, %i, %s, %s)", engine, id, format, bool2str(use16Outs));

for (int i=0; i < 16; ++i)
{
fCurMidiProgs[0] = 0;
fSamplerChannels[i] = nullptr;
fEngineChannels[i] = nullptr;
fAudioOutputDevices[i] = nullptr;
}
}

~LinuxSamplerPlugin() override
@@ -197,23 +213,46 @@ public:

if (fEngine != nullptr)
{
if (fSamplerChannel != nullptr)
if (fMidiInputDevice != nullptr)
{
fMidiInputPort->Disconnect(fSamplerChannel->GetEngineChannel());
fEngineChannel->DisconnectAudioOutputDevice();
fSampler->RemoveSamplerChannel(fSamplerChannel);
if (fMidiInputPort != nullptr)
{
for (int i=0; i < 16; ++i)
{
if (fSamplerChannels[i] != nullptr)
{
if (fEngineChannels[i] != nullptr)
{
fMidiInputPort->Disconnect(fEngineChannels[i]);
fEngineChannels[i]->DisconnectAudioOutputDevice();
fEngineChannels[i] = nullptr;
}

fSampler.RemoveSamplerChannel(fSamplerChannels[i]);
fSamplerChannels[i] = nullptr;

if (fAudioOutputDevices[i] != nullptr)
{
delete fAudioOutputDevices[i];
fAudioOutputDevices[i] = nullptr;
}
}
}

delete fMidiInputPort;
fMidiInputPort = nullptr;
}

delete fMidiInputDevice;
fMidiInputDevice = nullptr;
}

fInstrument = nullptr;

LinuxSampler::EngineFactory::Destroy(fEngine);
fEngine = nullptr;
}

// destructor is private
fMidiInputDevice->DeleteMidiPort(fMidiInputPort);

delete fMidiInputDevice;
delete fAudioOutputDevice;
delete fSampler;

fInstrumentIds.clear();

if (fFormat != nullptr)
@@ -286,16 +325,89 @@ public:
// -------------------------------------------------------------------
// Set data (state)

// nothing
void prepareForSave() override
{
char strBuf[STR_MAX+1];
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i", fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3],
fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7],
fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11],
fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]);

CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING, "midiPrograms", strBuf, false);
}

// -------------------------------------------------------------------
// Set data (internal stuff)

// nothing
void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) override
{
if (channel < MAX_MIDI_CHANNELS)
pData->midiprog.current = fCurMidiProgs[channel];

CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
}

// -------------------------------------------------------------------
// Set data (plugin-specific stuff)

void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
{
CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',);
carla_debug("DssiPlugin::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));

if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
return carla_stderr2("LinuxSamplerPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));

if (std::strcmp(key, "midiPrograms") != 0)
return carla_stderr2("LinuxSamplerPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));

if (! fUses16Outs)
return CarlaPlugin::setCustomData(type, key, value, sendGui);

QStringList midiProgramList(QString(value).split(":", QString::SkipEmptyParts));

if (midiProgramList.count() == MAX_MIDI_CHANNELS)
{
uint i = 0;
foreach (const QString& midiProg, midiProgramList)
{
bool ok;
uint index = midiProg.toUInt(&ok);

if (ok && index < pData->midiprog.count)
{
const uint32_t bank = pData->midiprog.data[index].bank;
const uint32_t program = pData->midiprog.data[index].program;
const uint32_t rIndex = bank*128 + program;

if (pData->engine->isOffline())
{
fEngineChannels[i]->PrepareLoadInstrument(pData->filename, rIndex);
fEngineChannels[i]->LoadInstrument();
}
else
{
fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], fEngineChannels[i]);
}

fCurMidiProgs[i] = index;

if (pData->ctrlChannel == static_cast<int32_t>(i))
{
pData->midiprog.current = index;
pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
}
}

++i;
}
}

CarlaPlugin::setCustomData(type, key, value, sendGui);
}

void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) override
{
CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count));
@@ -305,7 +417,7 @@ public:
else if (index > static_cast<int32_t>(pData->midiprog.count))
return;

if (pData->ctrlChannel < 0 || pData->ctrlChannel >= 16)
if (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)
return;

if (index >= 0)
@@ -314,17 +426,21 @@ public:
const uint32_t program = pData->midiprog.data[index].program;
const uint32_t rIndex = bank*128 + program;

LinuxSampler::EngineChannel* const engineChannel(fUses16Outs ? fEngineChannels[pData->ctrlChannel] : fEngineChannels[0]);

const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));

if (pData->engine->isOffline())
{
fEngineChannel->PrepareLoadInstrument(pData->filename, rIndex);
fEngineChannel->LoadInstrument();
engineChannel->PrepareLoadInstrument(pData->filename, rIndex);
engineChannel->LoadInstrument();
}
else
{
fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], fEngineChannel);
fInstrument->LoadInstrumentInBackground(fInstrumentIds[rIndex], engineChannel);
}

fCurMidiProgs[pData->ctrlChannel] = index;
}

CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
@@ -350,7 +466,7 @@ public:
clearBuffers();

uint32_t aOuts;
aOuts = 2;
aOuts = fUses16Outs ? 16 : 2;

pData->audioOut.createNew(aOuts);

@@ -360,6 +476,37 @@ public:
// ---------------------------------------
// Audio Outputs

if (fUses16Outs)
{
for (uint32_t i=0; i < 32; ++i)
{
portName.clear();

if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
{
portName = pData->name;
portName += ":";
}

portName += "out-";

if ((i+2)/2 < 9)
portName += "0";

portName += CarlaString((i+2)/2);

if (i % 2 == 0)
portName += "L";
else
portName += "R";

portName.truncate(portNameSize);

pData->audioOut.ports[i].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
pData->audioOut.ports[i].rindex = i;
}
}
else
{
// out-left
portName.clear();
@@ -414,14 +561,16 @@ public:

// plugin hints
pData->hints = 0x0;
//pData->hints |= PLUGIN_IS_SYNTH;
pData->hints |= PLUGIN_IS_SYNTH;
pData->hints |= PLUGIN_CAN_VOLUME;
pData->hints |= PLUGIN_CAN_BALANCE;

// extra plugin hints
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

if (! fUses16Outs)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);
@@ -478,7 +627,16 @@ public:

if (init)
{
setMidiProgram(0, false, false, false);
for (int i=0; i < 16; ++i)
{
CARLA_SAFE_ASSERT_CONTINUE(fEngineChannels[i] != nullptr);

fEngineChannels[i]->PrepareLoadInstrument(pData->filename, 0);
fEngineChannels[i]->LoadInstrument();
fCurMidiProgs[i] = 0;
}

pData->midiprog.current = 0;
}
else
{
@@ -491,16 +649,20 @@ public:

void activate() override
{
CARLA_ASSERT(fAudioOutputDevice != nullptr);

fAudioOutputDevice->Play();
for (int i=0; i < 16; ++i)
{
if (fAudioOutputDevices[i] != nullptr)
fAudioOutputDevices[i]->Play();
}
}

void deactivate() override
{
CARLA_ASSERT(fAudioOutputDevice != nullptr);

fAudioOutputDevice->Stop();
for (int i=0; i < 16; ++i)
{
if (fAudioOutputDevices[i] != nullptr)
fAudioOutputDevices[i]->Stop();
}
}

void process(float** const, float** const outBuffer, const uint32_t frames) override
@@ -514,13 +676,7 @@ public:
{
// disable any output sound
for (i=0; i < pData->audioOut.count; ++i)
{
#ifdef HAVE_JUCE
FloatVectorOperations::clear(outBuffer[i], frames);
#else
#endif
}

FLOAT_CLEAR(outBuffer[i], frames);
return;
}

@@ -866,10 +1022,24 @@ public:
// --------------------------------------------------------------------------------------------------------
// Run plugin

fAudioOutputDevice->Channel(0)->SetBuffer(outBuffer[0] + timeOffset);
fAudioOutputDevice->Channel(1)->SetBuffer(outBuffer[1] + timeOffset);
// QUESTION: Need to clear it before?
fAudioOutputDevice->Render(frames);
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
{
fAudioOutputDevices[0]->Channel(0)->SetBuffer(outBuffer[0] + timeOffset);
fAudioOutputDevices[0]->Channel(1)->SetBuffer(outBuffer[1] + timeOffset);
fAudioOutputDevices[0]->Render(frames);
}

#ifndef BUILD_BRIDGE
// --------------------------------------------------------------------------------------------------------
@@ -887,12 +1057,7 @@ public:
if (doBalance)
{
if (i % 2 == 0)
{
#ifdef HAVE_JUCE
FloatVectorOperations::copy(oldBufLeft, outBuffer[i], frames);
#else
#endif
}
FLOAT_COPY(oldBufLeft, outBuffer[i], frames);

float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
@@ -945,19 +1110,11 @@ public:

bool init(const char* filename, const char* const name, const char* label)
{
CARLA_ASSERT(pData->engine != nullptr);
CARLA_ASSERT(pData->client == nullptr);
CARLA_ASSERT(filename != nullptr);
CARLA_ASSERT(label != nullptr);
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);

// ---------------------------------------------------------------
// first checks

if (pData->engine == nullptr)
{
return false;
}

if (pData->client != nullptr)
{
pData->engine->setLastError("Plugin client is already registered");
@@ -977,25 +1134,17 @@ public:
}

// ---------------------------------------------------------------
// Check if file exists
{
// QFileInfo file(filename);
//
// if (! (file.exists() && file.isFile() && file.isReadable()))
// {
// pData->engine->setLastError("Requested file is not valid or does not exist");
// return false;
// }
}
// Store format

CarlaString cstype(fFormat);
cstype.toLower();
const char* const ctype(cstype.getBuffer());

// ---------------------------------------------------------------
// Create the LinuxSampler Engine

CarlaString stype(fFormat);
stype.toLower();

try {
fEngine = LinuxSampler::EngineFactory::Create((const char*)stype);
fEngine = LinuxSampler::EngineFactory::Create(ctype);
}
catch (LinuxSampler::Exception& e)
{
@@ -1003,6 +1152,44 @@ public:
return false;
}

// ---------------------------------------------------------------
// Init LinuxSampler stuff

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)
{
fSamplerChannels[i] = fSampler.AddSamplerChannel();
CARLA_SAFE_ASSERT_CONTINUE(fSamplerChannels[i] != nullptr);

fEngineChannels[i] = fSamplerChannels[i]->GetEngineChannel();
CARLA_SAFE_ASSERT_CONTINUE(fEngineChannels[i] != nullptr);

LinuxSampler::AudioOutputDevicePlugin* outputDevice;

if (fUses16Outs)
{
fAudioOutputDevices[i] = new LinuxSampler::AudioOutputDevicePlugin(pData->engine, this);
outputDevice = fAudioOutputDevices[i];
}
else
{
outputDevice = fAudioOutputDevices[0];
}

fSamplerChannels[i]->SetEngineType(ctype);
fSamplerChannels[i]->SetAudioOutputDevice(outputDevice);

fEngineChannels[i]->Connect(outputDevice);
fEngineChannels[i]->Volume(LinuxSampler::kVolumeMax);

fMidiInputPort->Connect(fEngineChannels[i], static_cast<LinuxSampler::midi_chan_t>(i));
}

// ---------------------------------------------------------------
// Get the Engine's Instrument Manager

@@ -1011,8 +1198,6 @@ public:
if (fInstrument == nullptr)
{
pData->engine->setLastError("Failed to get LinuxSampler instrument manager");
LinuxSampler::EngineFactory::Destroy(fEngine);
fEngine = nullptr;
return false;
}

@@ -1025,8 +1210,6 @@ public:
catch (const LinuxSampler::InstrumentManagerException& e)
{
pData->engine->setLastError(e.what());
LinuxSampler::EngineFactory::Destroy(fEngine);
fEngine = nullptr;
return false;
}

@@ -1036,8 +1219,6 @@ public:
if (fInstrumentIds.size() == 0)
{
pData->engine->setLastError("Failed to find any instruments");
LinuxSampler::EngineFactory::Destroy(fEngine);
fEngine = nullptr;
return false;
}

@@ -1049,14 +1230,13 @@ public:
catch (const LinuxSampler::InstrumentManagerException& e)
{
pData->engine->setLastError(e.what());
LinuxSampler::EngineFactory::Destroy(fEngine);
fEngine = nullptr;
return false;
}

fRealName = info.InstrumentName.c_str();
fLabel = info.Product.c_str();
fMaker = info.Artists.c_str();

pData->filename = carla_strdup(filename);

if (fUses16Outs && ! fLabel.endsWith(" (16 outs)"))
@@ -1076,23 +1256,11 @@ public:
{
pData->engine->setLastError("Failed to register plugin client");
LinuxSampler::EngineFactory::Destroy(fEngine);
fInstrument = nullptr;
fEngine = nullptr;
return false;
}

// ---------------------------------------------------------------
// Init LinuxSampler stuff

fSamplerChannel = fSampler->AddSamplerChannel();
fSamplerChannel->SetEngineType((const char*)stype);
fSamplerChannel->SetAudioOutputDevice(fAudioOutputDevice);

fEngineChannel = fSamplerChannel->GetEngineChannel();
fEngineChannel->Connect(fAudioOutputDevice);
fEngineChannel->Volume(LinuxSampler::VOLUME_MAX);

fMidiInputPort->Connect(fSamplerChannel->GetEngineChannel(), LinuxSampler::midi_chan_all);

// ---------------------------------------------------------------
// load plugin settings

@@ -1128,19 +1296,21 @@ private:
const char* fFormat;
const bool fUses16Outs;

int32_t fCurMidiProgs[16];

CarlaString fRealName;
CarlaString fLabel;
CarlaString fMaker;

LinuxSampler::Sampler* fSampler;
LinuxSampler::SamplerChannel* fSamplerChannel;
LinuxSampler::Sampler fSampler;
LinuxSampler::Engine* fEngine;

LinuxSampler::Engine* fEngine;
LinuxSampler::EngineChannel* fEngineChannel;
LinuxSampler::SamplerChannel* fSamplerChannels[16];
LinuxSampler::EngineChannel* fEngineChannels[16];

LinuxSampler::AudioOutputDevicePlugin* fAudioOutputDevice;
LinuxSampler::MidiInputDevicePlugin* fMidiInputDevice;
LinuxSampler::MidiInputPort* fMidiInputPort;
LinuxSampler::AudioOutputDevicePlugin* fAudioOutputDevices[16];
LinuxSampler::MidiInputDevicePlugin* fMidiInputDevice;
LinuxSampler::MidiInputPortPlugin* fMidiInputPort;

LinuxSampler::InstrumentManager* fInstrument;
std::vector<LinuxSampler::InstrumentManager::instrument_id_t> fInstrumentIds;
@@ -1154,17 +1324,44 @@ CARLA_BACKEND_END_NAMESPACE

CARLA_BACKEND_START_NAMESPACE

CarlaPlugin* CarlaPlugin::newLinuxSampler(const Initializer& init, const char* const format, const bool use16Outs)
CarlaPlugin* CarlaPlugin::newLinuxSampler(const Initializer& init, const char* const format, const bool /*use16Outs*/)
{
// TESTING
const bool use16Outs = true;

carla_debug("LinuxSamplerPlugin::newLinuxSampler({%p, \"%s\", \"%s\", \"%s\"}, %s, %s)", init.engine, init.filename, init.name, init.label, format, bool2str(use16Outs));

#ifdef WANT_FLUIDSYNTH
#ifdef WANT_LINUXSAMPLER
if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && use16Outs)
{
init.engine->setLastError("Carla's rack mode can only work with Stereo modules, please choose the 2-channel only sample-library version");
return nullptr;
}

// -------------------------------------------------------------------
// Check if file exists
{
QFileInfo file(init.filename);

if (! file.exists())
{
init.engine->setLastError("Requested file does not exist");
return false;
}

if (! file.isFile())
{
init.engine->setLastError("Requested file is not valid");
return false;
}

if (! file.isReadable())
{
init.engine->setLastError("Requested file is not readable");
return false;
}
}

LinuxSamplerPlugin* const plugin(new LinuxSamplerPlugin(init.engine, init.id, format, use16Outs));

if (! plugin->init(init.filename, init.name, init.label))


+ 2
- 1
source/bridges/Makefile View File

@@ -382,7 +382,8 @@ OBJS_NATIVE += \
../backend/plugin/DssiPlugin__native.o \
../backend/plugin/Lv2Plugin__native.o \
../backend/plugin/VstPlugin__native.o \
../backend/plugin/Vst3Plugin__native.o \
../backend/plugin/AuPlugin__native.o \
../backend/plugin/JucePlugin__native.o \
../backend/plugin/FluidSynthPlugin__native.o \
../backend/plugin/LinuxSamplerPlugin__native.o



Loading…
Cancel
Save