|
- /*
- ==============================================================================
-
- This file was auto-generated!
-
- It contains the basic framework code for an ARA playback renderer implementation.
-
- ==============================================================================
- */
-
- %%araplaybackrenderer_headers%%
-
- //==============================================================================
- void %%araplaybackrenderer_class_name%%::prepareToPlay (double sampleRateIn, int maximumSamplesPerBlockIn, int numChannelsIn, juce::AudioProcessor::ProcessingPrecision, AlwaysNonRealtime alwaysNonRealtime)
- {
- numChannels = numChannelsIn;
- sampleRate = sampleRateIn;
- maximumSamplesPerBlock = maximumSamplesPerBlockIn;
- useBufferedAudioSourceReader = alwaysNonRealtime == AlwaysNonRealtime::no;
- }
-
- void %%araplaybackrenderer_class_name%%::releaseResources()
- {
- }
-
- //==============================================================================
- bool %%araplaybackrenderer_class_name%%::processBlock (juce::AudioBuffer<float>& buffer,
- juce::AudioProcessor::Realtime realtime,
- const juce::AudioPlayHead::PositionInfo& positionInfo) noexcept
- {
- const auto numSamples = buffer.getNumSamples();
- jassert (numSamples <= maximumSamplesPerBlock);
- jassert (numChannels == buffer.getNumChannels());
- jassert (realtime == juce::AudioProcessor::Realtime::no || useBufferedAudioSourceReader);
- const auto timeInSamples = positionInfo.getTimeInSamples().orFallback (0);
- const auto isPlaying = positionInfo.getIsPlaying();
-
- bool success = true;
- bool didRenderAnyRegion = false;
-
- if (isPlaying)
- {
- const auto blockRange = juce::Range<juce::int64>::withStartAndLength (timeInSamples, numSamples);
-
- for (const auto& playbackRegion : getPlaybackRegions())
- {
- // Evaluate region borders in song time, calculate sample range to render in song time.
- // Note that this example does not use head- or tailtime, so the includeHeadAndTail
- // parameter is set to false here - this might need to be adjusted in actual plug-ins.
- const auto playbackSampleRange = playbackRegion->getSampleRange (sampleRate,
- juce::ARAPlaybackRegion::IncludeHeadAndTail::no);
- auto renderRange = blockRange.getIntersectionWith (playbackSampleRange);
-
- if (renderRange.isEmpty())
- continue;
-
- // Evaluate region borders in modification/source time and calculate offset between
- // song and source samples, then clip song samples accordingly
- // (if an actual plug-in supports time stretching, this must be taken into account here).
- juce::Range<juce::int64> modificationSampleRange { playbackRegion->getStartInAudioModificationSamples(),
- playbackRegion->getEndInAudioModificationSamples() };
- const auto modificationSampleOffset = modificationSampleRange.getStart() - playbackSampleRange.getStart();
-
- renderRange = renderRange.getIntersectionWith (modificationSampleRange.movedToStartAt (playbackSampleRange.getStart()));
-
- if (renderRange.isEmpty())
- continue;
-
- // Now calculate the samples in renderRange for this PlaybackRegion based on the ARA model
- // graph. If didRenderAnyRegion is true, add the region's output samples in renderRange to
- // the buffer. Otherwise the buffer needs to be initialised so the sample value must be
- // overwritten.
- const int numSamplesToRead = (int) renderRange.getLength();
- const int startInBuffer = (int) (renderRange.getStart() - blockRange.getStart());
- const auto startInSource = renderRange.getStart() + modificationSampleOffset;
-
- for (int c = 0; c < numChannels; ++c)
- {
- auto* channelData = buffer.getWritePointer (c);
-
- for (int i = 0; i < numSamplesToRead; ++i)
- {
- // Calculate region output sample at index startInSource + i ...
- float sample = 0.0f;
-
- if (didRenderAnyRegion)
- channelData[startInBuffer + i] += sample;
- else
- channelData[startInBuffer + i] = sample;
- }
- }
-
- // If rendering first region, clear any excess at start or end of the region.
- if (! didRenderAnyRegion)
- {
- if (startInBuffer != 0)
- buffer.clear (0, startInBuffer);
-
- const int endInBuffer = startInBuffer + numSamples;
- const int remainingSamples = numSamples - endInBuffer;
-
- if (remainingSamples != 0)
- buffer.clear (endInBuffer, remainingSamples);
-
- didRenderAnyRegion = true;
- }
- }
- }
-
- if (! didRenderAnyRegion)
- buffer.clear();
-
- return success;
- }
|