11namespace tracktion {
inline namespace engine
17 : c (clip), playHeadState (playHeadStateToUse), clipPtr (clip),
18 file (c.getAudioFile()),
19 fileInfo (file.getInfo()),
20 sampleRate (fileInfo.sampleRate),
21 fifo ((choc::buffer::ChannelCount)
std::
max (1, fileInfo.numChannels), 8192)
25 reader = c.edit.engine.getAudioFileManager().cache.createReader (file);
27 auto wi = clip.getWaveInfo();
28 auto& li = c.getLoopInfo();
30 if (li.getNumBeats() > 0)
32 if (c.getAutoTempo() && wi.hashCode != 0)
33 speedRatio = (
float) (li.getBpm (wi) / clip.edit.tempoSequence.getTempo (0)->getBpm());
35 speedRatio = (
float) c.getSpeedRatio();
38 const int rootNote = li.getRootNote();
42 if (c.getAutoPitch() && rootNote != -1)
43 pitchSemitones = (
float) c.getTransposeSemiTones (
true);
45 pitchSemitones = c.getPitchChange();
49 speedRatio =
std::max (speedRatio, 0.1f);
56 props.hasAudio =
true;
57 props.numberOfChannels = fileInfo.numChannels;
72 sampleRate = info.sampleRate;
76 if (TimeStretcher::canProcessFor (m))
78 fileSpeedRatio =
float (fileInfo.sampleRate / sampleRate);
79 const float resamplingPitchRatio = fileSpeedRatio > 0.0f ? (
float)
std::log2 (fileSpeedRatio) : 1.0f;
80 timestretcher.initialise (info.sampleRate, stretchBlockSize, fileInfo.numChannels, m, c.elastiqueProOptions.get(),
false);
81 timestetchSpeedRatio =
std::max (0.1f,
float (speedRatio / fileSpeedRatio));
82 timestetchSemitonesUp =
float ((pitchSemitones + (resamplingPitchRatio * 12.0f)));
83 timestretcher.setSpeedAndPitch (timestetchSpeedRatio, timestetchSemitonesUp);
86 fifo.setSize ((choc::buffer::ChannelCount) fileInfo.numChannels,
87 (choc::buffer::FrameCount) timestretcher.getMaxFramesNeeded());
90bool TimeStretchingWaveNode::isReadyToProcess()
92 if (file.getHash() == 0)
95 if (reader ==
nullptr)
96 reader = c.edit.engine.getAudioFileManager().cache.createReader (file);
98 return reader !=
nullptr && reader->getSampleRate() > 0.0;
105 const auto editRange = tracktion::graph::sampleToTime (timelineRange, sampleRate);
107 if (timelineRange.isEmpty())
110 auto destAudioView = pc.buffers.audio;
112 if (! playHeadState.isContiguousWithPreviousBlock() || editRange.getStart() != nextEditTime)
113 reset (editRange.getStart());
115 auto numSamples = destAudioView.getNumFrames();
116 choc::buffer::FrameCount start = 0;
118 while (numSamples > 0)
120 auto numReady =
std::min (numSamples, (choc::buffer::FrameCount) fifo.getNumReady());
124 const bool res = fifo.readAdding (destAudioView.getFrameRange ({ start, start + numReady }));
128 numSamples -= numReady;
132 if (! fillNextBlock())
137 nextEditTime = editRange.getEnd();
141int64_t TimeStretchingWaveNode::timeToFileSample (
double time)
const noexcept
143 const double fileStartTime =
time / speedRatio;
147void TimeStretchingWaveNode::reset (
double newStartTime)
149 const int64_t readPos = timeToFileSample (newStartTime);
151 if (reader !=
nullptr)
153 if (readPos == reader->getReadPosition())
156 reader->setReadPosition (readPos);
161 timestretcher.reset();
162 timestretcher.setSpeedAndPitch (timestetchSpeedRatio, timestetchSemitonesUp);
165bool TimeStretchingWaveNode::fillNextBlock()
168 const int needed = timestretcher.getFramesNeeded();
169 jassert (needed < fifo.getFreeSpace());
172 if (reader ==
nullptr)
175 AudioScratchBuffer fifoScratch (fileInfo.numChannels, stretchBlockSize);
179 fifoScratch.buffer.getWritePointer (0),
180 fileInfo.numChannels > 1 ? fifoScratch.buffer.getWritePointer (1) :
nullptr,
186 AudioScratchBuffer scratch (fileInfo.numChannels, needed);
192 bool b = reader->readSamples (needed, scratch.buffer, bufChannels, 0, channelsToUse, 3);
199 scratch.buffer.getReadPointer (0),
200 fileInfo.numChannels > 1 ? scratch.buffer.getReadPointer (1) :
nullptr,
204 if (TimeStretcher::canProcessFor (c.getTimeStretchMode()))
205 timestretcher.processData (ins, needed, outs);
207 for (
int channel = fileInfo.numChannels; --channel >= 0;)
208 juce::FloatVectorOperations::copy (outs[channel], ins[channel], needed);
213 timestretcher.flush (outs);
216 const bool res = fifo.write (choc::buffer::createChannelArrayView (fifoScratch.buffer.getArrayOfWritePointers(),
217 (choc::buffer::ChannelCount) fifoScratch.buffer.getNumChannels(),
218 (choc::buffer::FrameCount) stretchBlockSize));
static AudioChannelSet JUCE_CALLTYPE mono()
static AudioChannelSet JUCE_CALLTYPE stereo()
Mode
Holds the various algorithms to which can be used (if enabled).
Struct to describe a single iteration of a process call.
Determines how this block releates to other previous render blocks and if the play head has jumped in...
void ignoreUnused(Types &&...) noexcept
int roundToInt(const FloatType value) noexcept
SplitTimelineRange referenceSampleRangeToSplitTimelineRange(const PlayHead &playHead, juce::Range< int64_t > referenceSampleRange)
Converts a reference sample range to a TimelinePositionWindow which could have two time ranges if the...
Holds some really basic properties of a node.
Passed into Nodes when they are being initialised, to give them useful contextual information that th...
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.