| @@ -983,6 +983,10 @@ namespace | |||||
| template <typename FloatType> struct AudioBusPointerHelper {}; | template <typename FloatType> struct AudioBusPointerHelper {}; | ||||
| template <> struct AudioBusPointerHelper<float> { static inline float** impl (Vst::AudioBusBuffers& data) noexcept { return data.channelBuffers32; } }; | template <> struct AudioBusPointerHelper<float> { static inline float** impl (Vst::AudioBusBuffers& data) noexcept { return data.channelBuffers32; } }; | ||||
| template <> struct AudioBusPointerHelper<double> { static inline double** impl (Vst::AudioBusBuffers& data) noexcept { return data.channelBuffers64; } }; | template <> struct AudioBusPointerHelper<double> { static inline double** impl (Vst::AudioBusBuffers& data) noexcept { return data.channelBuffers64; } }; | ||||
| template <typename FloatType> struct ChooseBufferHelper {}; | |||||
| template <> struct ChooseBufferHelper<float> { static inline AudioBuffer<float>& impl (AudioBuffer<float>& f, AudioBuffer<double>& ) noexcept { return f; } }; | |||||
| template <> struct ChooseBufferHelper<double> { static inline AudioBuffer<double>& impl (AudioBuffer<float>& , AudioBuffer<double>& d) noexcept { return d; } }; | |||||
| } | } | ||||
| @@ -1142,6 +1146,9 @@ public: | |||||
| if (! state) | if (! state) | ||||
| { | { | ||||
| getPluginInstance().releaseResources(); | getPluginInstance().releaseResources(); | ||||
| deallocateChannelListAndBuffers (channelListFloat, emptyBufferFloat); | |||||
| deallocateChannelListAndBuffers (channelListDouble, emptyBufferDouble); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1156,8 +1163,8 @@ public: | |||||
| ? (int) processSetup.maxSamplesPerBlock | ? (int) processSetup.maxSamplesPerBlock | ||||
| : bufferSize; | : bufferSize; | ||||
| allocateChannelLists (channelListFloat); | |||||
| allocateChannelLists (channelListDouble); | |||||
| allocateChannelListAndBuffers (channelListFloat, emptyBufferFloat); | |||||
| allocateChannelListAndBuffers (channelListDouble, emptyBufferDouble); | |||||
| preparePlugin (sampleRate, bufferSize); | preparePlugin (sampleRate, bufferSize); | ||||
| } | } | ||||
| @@ -1947,6 +1954,9 @@ private: | |||||
| Array<float*> channelListFloat; | Array<float*> channelListFloat; | ||||
| Array<double*> channelListDouble; | Array<double*> channelListDouble; | ||||
| AudioBuffer<float> emptyBufferFloat; | |||||
| AudioBuffer<double> emptyBufferDouble; | |||||
| bool isMidiInputBusEnabled, isMidiOutputBusEnabled; | bool isMidiInputBusEnabled, isMidiOutputBusEnabled; | ||||
| ScopedJuceInitialiser_GUI libraryInitialiser; | ScopedJuceInitialiser_GUI libraryInitialiser; | ||||
| @@ -1965,52 +1975,110 @@ private: | |||||
| void processAudio (Vst::ProcessData& data, Array<FloatType*>& channelList) | void processAudio (Vst::ProcessData& data, Array<FloatType*>& channelList) | ||||
| { | { | ||||
| int totalInputChans = 0; | int totalInputChans = 0; | ||||
| bool tmpBufferNeedsClearing = false; | |||||
| const int plugInInputChannels = pluginInstance->getTotalNumInputChannels(); | const int plugInInputChannels = pluginInstance->getTotalNumInputChannels(); | ||||
| const int plugInOutputChannels = pluginInstance->getTotalNumOutputChannels(); | const int plugInOutputChannels = pluginInstance->getTotalNumOutputChannels(); | ||||
| if (data.inputs != nullptr) | |||||
| // Wavelab workaround: wave-lab lies on the number of inputs/outputs so re-count here | |||||
| int vstInputs; | |||||
| for (vstInputs = 0; vstInputs < data.numInputs; ++vstInputs) | |||||
| if (getPointerForAudioBus<FloatType> (data.inputs[vstInputs]) == nullptr) | |||||
| break; | |||||
| int vstOutputs; | |||||
| for (vstOutputs = 0; vstOutputs < data.numOutputs; ++vstOutputs) | |||||
| if (getPointerForAudioBus<FloatType> (data.outputs[vstOutputs]) == nullptr) | |||||
| break; | |||||
| { | { | ||||
| for (int bus = 0; bus < data.numInputs && totalInputChans < plugInInputChannels; ++bus) | |||||
| const int n = jmax (vstInputs, getNumAudioBuses (true)); | |||||
| for (int bus = 0; bus < n && totalInputChans < plugInInputChannels; ++bus) | |||||
| { | { | ||||
| if (FloatType** const busChannels = getPointerForAudioBus<FloatType> (data.inputs[bus])) | |||||
| if (bus < vstInputs) | |||||
| { | { | ||||
| const int numChans = jmin ((int) data.inputs[bus].numChannels, plugInInputChannels - totalInputChans); | |||||
| if (FloatType** const busChannels = getPointerForAudioBus<FloatType> (data.inputs[bus])) | |||||
| { | |||||
| const int numChans = jmin ((int) data.inputs[bus].numChannels, plugInInputChannels - totalInputChans); | |||||
| for (int i = 0; i < numChans; ++i) | |||||
| if (busChannels[i] != nullptr) | |||||
| channelList.set (totalInputChans++, busChannels[i]); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| const int numChans = jmin (pluginInstance->getChannelCountOfBus (true, bus), plugInInputChannels - totalInputChans); | |||||
| for (int i = 0; i < numChans; ++i) | for (int i = 0; i < numChans; ++i) | ||||
| if (busChannels[i] != nullptr) | |||||
| channelList.set (totalInputChans++, busChannels[i]); | |||||
| { | |||||
| if (FloatType* tmpBuffer = getTmpBufferForChannel<FloatType> (totalInputChans, data.numSamples)) | |||||
| { | |||||
| tmpBufferNeedsClearing = true; | |||||
| channelList.set (totalInputChans++, tmpBuffer); | |||||
| } | |||||
| else | |||||
| return; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| int totalOutputChans = 0; | int totalOutputChans = 0; | ||||
| if (data.outputs != nullptr) | |||||
| { | { | ||||
| for (int bus = 0; bus < data.numOutputs && totalOutputChans < plugInOutputChannels; ++bus) | |||||
| const int n = jmax (vstOutputs, getNumAudioBuses (false)); | |||||
| for (int bus = 0; bus < n && totalOutputChans < plugInOutputChannels; ++bus) | |||||
| { | { | ||||
| if (FloatType** const busChannels = getPointerForAudioBus<FloatType> (data.outputs[bus])) | |||||
| if (bus < vstOutputs) | |||||
| { | { | ||||
| const int numChans = jmin ((int) data.outputs[bus].numChannels, plugInOutputChannels - totalOutputChans); | |||||
| if (FloatType** const busChannels = getPointerForAudioBus<FloatType> (data.outputs[bus])) | |||||
| { | |||||
| const int numChans = jmin ((int) data.outputs[bus].numChannels, plugInOutputChannels - totalOutputChans); | |||||
| for (int i = 0; i < numChans; ++i) | |||||
| { | |||||
| if (busChannels[i] != nullptr) | |||||
| { | |||||
| if (totalOutputChans >= totalInputChans) | |||||
| { | |||||
| FloatVectorOperations::clear (busChannels[i], data.numSamples); | |||||
| channelList.set (totalOutputChans, busChannels[i]); | |||||
| } | |||||
| ++totalOutputChans; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| const int numChans = jmin (pluginInstance->getChannelCountOfBus (false, bus), plugInOutputChannels - totalOutputChans); | |||||
| for (int i = 0; i < numChans; ++i) | for (int i = 0; i < numChans; ++i) | ||||
| { | { | ||||
| if (busChannels[i] != nullptr) | |||||
| if (FloatType* tmpBuffer = getTmpBufferForChannel<FloatType> (totalOutputChans, data.numSamples)) | |||||
| { | { | ||||
| if (totalOutputChans >= totalInputChans) | if (totalOutputChans >= totalInputChans) | ||||
| { | { | ||||
| FloatVectorOperations::clear (busChannels[i], data.numSamples); | |||||
| channelList.set (totalOutputChans, busChannels[i]); | |||||
| tmpBufferNeedsClearing = true; | |||||
| channelList.set (totalOutputChans, tmpBuffer); | |||||
| } | } | ||||
| ++totalOutputChans; | ++totalOutputChans; | ||||
| } | } | ||||
| else | |||||
| return; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (tmpBufferNeedsClearing) | |||||
| ChooseBufferHelper<FloatType>::impl (emptyBufferFloat, emptyBufferDouble).clear(); | |||||
| AudioBuffer<FloatType> buffer; | AudioBuffer<FloatType> buffer; | ||||
| if (int totalChans = jmax (totalOutputChans, totalInputChans)) | if (int totalChans = jmax (totalOutputChans, totalInputChans)) | ||||
| @@ -2089,10 +2157,22 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| template <typename FloatType> | template <typename FloatType> | ||||
| void allocateChannelLists (Array<FloatType*>& channelList) | |||||
| void allocateChannelListAndBuffers (Array<FloatType*>& channelList, AudioBuffer<FloatType>& buffer) | |||||
| { | { | ||||
| channelList.clearQuick(); | channelList.clearQuick(); | ||||
| channelList.insertMultiple (0, nullptr, 128); | channelList.insertMultiple (0, nullptr, 128); | ||||
| const AudioProcessor& p = getPluginInstance(); | |||||
| buffer.setSize (jmax (p.getTotalNumInputChannels(), p.getTotalNumOutputChannels()), p.getBlockSize() * 4); | |||||
| buffer.clear(); | |||||
| } | |||||
| template <typename FloatType> | |||||
| void deallocateChannelListAndBuffers (Array<FloatType*>& channelList, AudioBuffer<FloatType>& buffer) | |||||
| { | |||||
| channelList.clearQuick(); | |||||
| channelList.resize (0); | |||||
| buffer.setSize (0, 0); | |||||
| } | } | ||||
| template <typename FloatType> | template <typename FloatType> | ||||
| @@ -2101,6 +2181,19 @@ private: | |||||
| return AudioBusPointerHelper<FloatType>::impl (data); | return AudioBusPointerHelper<FloatType>::impl (data); | ||||
| } | } | ||||
| template <typename FloatType> | |||||
| FloatType* getTmpBufferForChannel (int channel, int numSamples) noexcept | |||||
| { | |||||
| AudioBuffer<FloatType>& buffer = ChooseBufferHelper<FloatType>::impl (emptyBufferFloat, emptyBufferDouble); | |||||
| // we can't do anything if the host requests to render many more samples than the | |||||
| // block size, we need to bail out | |||||
| if (numSamples > buffer.getNumSamples() || channel >= buffer.getNumChannels()) | |||||
| return nullptr; | |||||
| return buffer.getWritePointer (channel); | |||||
| } | |||||
| void preparePlugin (double sampleRate, int bufferSize) | void preparePlugin (double sampleRate, int bufferSize) | ||||
| { | { | ||||
| AudioProcessor& p = getPluginInstance(); | AudioProcessor& p = getPluginInstance(); | ||||