|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2017 - ROLI Ltd.
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 5 End-User License
- Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
- 27th April 2017).
-
- End User License Agreement: www.juce.com/juce-5-licence
- Privacy Policy: www.juce.com/juce-5-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- AudioProcessorPlayer::AudioProcessorPlayer (bool doDoublePrecisionProcessing)
- : isDoublePrecision (doDoublePrecisionProcessing)
- {
- }
-
- AudioProcessorPlayer::~AudioProcessorPlayer()
- {
- setProcessor (nullptr);
- }
-
- //==============================================================================
- void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
- {
- if (processor != processorToPlay)
- {
- if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
- {
- processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, sampleRate, blockSize);
-
- bool supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision;
-
- processorToPlay->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision
- : AudioProcessor::singlePrecision);
- processorToPlay->prepareToPlay (sampleRate, blockSize);
- }
-
- AudioProcessor* oldOne;
-
- {
- const ScopedLock sl (lock);
- oldOne = isPrepared ? processor : nullptr;
- processor = processorToPlay;
- isPrepared = true;
- }
-
- if (oldOne != nullptr)
- oldOne->releaseResources();
- }
- }
-
- void AudioProcessorPlayer::setDoublePrecisionProcessing (bool doublePrecision)
- {
- if (doublePrecision != isDoublePrecision)
- {
- const ScopedLock sl (lock);
-
- if (processor != nullptr)
- {
- processor->releaseResources();
-
- bool supportsDouble = processor->supportsDoublePrecisionProcessing() && doublePrecision;
-
- processor->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision
- : AudioProcessor::singlePrecision);
- processor->prepareToPlay (sampleRate, blockSize);
- }
-
- isDoublePrecision = doublePrecision;
- }
- }
-
- void AudioProcessorPlayer::setMidiOutput (MidiOutput* midiOutputToUse)
- {
- if (midiOutput != midiOutputToUse)
- {
- const ScopedLock sl (lock);
- midiOutput = midiOutputToUse;
- }
- }
-
- //==============================================================================
- void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChannelData,
- const int numInputChannels,
- float** const outputChannelData,
- const int numOutputChannels,
- const int numSamples)
- {
- // these should have been prepared by audioDeviceAboutToStart()...
- jassert (sampleRate > 0 && blockSize > 0);
-
- incomingMidi.clear();
- messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples);
- int totalNumChans = 0;
-
- if (numInputChannels > numOutputChannels)
- {
- // if there aren't enough output channels for the number of
- // inputs, we need to create some temporary extra ones (can't
- // use the input data in case it gets written to)
- tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples,
- false, false, true);
-
- for (int i = 0; i < numOutputChannels; ++i)
- {
- channels[totalNumChans] = outputChannelData[i];
- memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
- ++totalNumChans;
- }
-
- for (int i = numOutputChannels; i < numInputChannels; ++i)
- {
- channels[totalNumChans] = tempBuffer.getWritePointer (i - numOutputChannels);
- memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
- ++totalNumChans;
- }
- }
- else
- {
- for (int i = 0; i < numInputChannels; ++i)
- {
- channels[totalNumChans] = outputChannelData[i];
- memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * (size_t) numSamples);
- ++totalNumChans;
- }
-
- for (int i = numInputChannels; i < numOutputChannels; ++i)
- {
- channels[totalNumChans] = outputChannelData[i];
- zeromem (channels[totalNumChans], sizeof (float) * (size_t) numSamples);
- ++totalNumChans;
- }
- }
-
- AudioBuffer<float> buffer (channels, totalNumChans, numSamples);
-
- {
- const ScopedLock sl (lock);
-
- if (processor != nullptr)
- {
- const ScopedLock sl2 (processor->getCallbackLock());
-
- if (! processor->isSuspended())
- {
- if (processor->isUsingDoublePrecision())
- {
- conversionBuffer.makeCopyOf (buffer, true);
- processor->processBlock (conversionBuffer, incomingMidi);
- buffer.makeCopyOf (conversionBuffer, true);
- }
- else
- {
- processor->processBlock (buffer, incomingMidi);
- }
-
- if (midiOutput != nullptr)
- midiOutput->sendBlockOfMessagesNow (incomingMidi);
-
- return;
- }
- }
- }
-
- for (int i = 0; i < numOutputChannels; ++i)
- FloatVectorOperations::clear (outputChannelData[i], numSamples);
- }
-
- void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device)
- {
- auto newSampleRate = device->getCurrentSampleRate();
- auto newBlockSize = device->getCurrentBufferSizeSamples();
- auto numChansIn = device->getActiveInputChannels().countNumberOfSetBits();
- auto numChansOut = device->getActiveOutputChannels().countNumberOfSetBits();
-
- const ScopedLock sl (lock);
-
- sampleRate = newSampleRate;
- blockSize = newBlockSize;
- numInputChans = numChansIn;
- numOutputChans = numChansOut;
-
- messageCollector.reset (sampleRate);
- channels.calloc (jmax (numChansIn, numChansOut) + 2);
-
- if (processor != nullptr)
- {
- if (isPrepared)
- processor->releaseResources();
-
- auto* oldProcessor = processor;
- setProcessor (nullptr);
- setProcessor (oldProcessor);
- }
- }
-
- void AudioProcessorPlayer::audioDeviceStopped()
- {
- const ScopedLock sl (lock);
-
- if (processor != nullptr && isPrepared)
- processor->releaseResources();
-
- sampleRate = 0.0;
- blockSize = 0;
- isPrepared = false;
- tempBuffer.setSize (1, 1);
- }
-
- void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
- {
- messageCollector.addMessageToQueue (message);
- }
-
- } // namespace juce
|