/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ AudioSourcePlayer::AudioSourcePlayer() : source (nullptr), sampleRate (0), bufferSize (0), lastGain (1.0f), gain (1.0f) { } AudioSourcePlayer::~AudioSourcePlayer() { setSource (nullptr); } void AudioSourcePlayer::setSource (AudioSource* newSource) { if (source != newSource) { AudioSource* const oldSource = source; if (newSource != nullptr && bufferSize > 0 && sampleRate > 0) newSource->prepareToPlay (bufferSize, sampleRate); { const ScopedLock sl (readLock); source = newSource; } if (oldSource != nullptr) oldSource->releaseResources(); } } void AudioSourcePlayer::setGain (const float newGain) noexcept { gain = newGain; } void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData, int totalNumInputChannels, float** outputChannelData, int totalNumOutputChannels, int numSamples) { // these should have been prepared by audioDeviceAboutToStart()... jassert (sampleRate > 0 && bufferSize > 0); const ScopedLock sl (readLock); if (source != nullptr) { int numActiveChans = 0, numInputs = 0, numOutputs = 0; // messy stuff needed to compact the channels down into an array // of non-zero pointers.. for (int i = 0; i < totalNumInputChannels; ++i) { if (inputChannelData[i] != nullptr) { inputChans [numInputs++] = inputChannelData[i]; if (numInputs >= numElementsInArray (inputChans)) break; } } for (int i = 0; i < totalNumOutputChannels; ++i) { if (outputChannelData[i] != nullptr) { outputChans [numOutputs++] = outputChannelData[i]; if (numOutputs >= numElementsInArray (outputChans)) break; } } if (numInputs > numOutputs) { // 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 (numInputs - numOutputs, numSamples, false, false, true); for (int i = 0; i < numOutputs; ++i) { channels[numActiveChans] = outputChans[i]; memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples); ++numActiveChans; } for (int i = numOutputs; i < numInputs; ++i) { channels[numActiveChans] = tempBuffer.getWritePointer (i - numOutputs); memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples); ++numActiveChans; } } else { for (int i = 0; i < numInputs; ++i) { channels[numActiveChans] = outputChans[i]; memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples); ++numActiveChans; } for (int i = numInputs; i < numOutputs; ++i) { channels[numActiveChans] = outputChans[i]; zeromem (channels[numActiveChans], sizeof (float) * (size_t) numSamples); ++numActiveChans; } } AudioSampleBuffer buffer (channels, numActiveChans, numSamples); AudioSourceChannelInfo info (&buffer, 0, numSamples); source->getNextAudioBlock (info); for (int i = info.buffer->getNumChannels(); --i >= 0;) buffer.applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain); lastGain = gain; } else { for (int i = 0; i < totalNumOutputChannels; ++i) if (outputChannelData[i] != nullptr) zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples); } } void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device) { prepareToPlay (device->getCurrentSampleRate(), device->getCurrentBufferSizeSamples()); } void AudioSourcePlayer::prepareToPlay (double newSampleRate, int newBufferSize) { sampleRate = newSampleRate; bufferSize = newBufferSize; zeromem (channels, sizeof (channels)); if (source != nullptr) source->prepareToPlay (bufferSize, sampleRate); } void AudioSourcePlayer::audioDeviceStopped() { if (source != nullptr) source->releaseResources(); sampleRate = 0.0; bufferSize = 0; tempBuffer.setSize (2, 8); }