mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioProcessor: Allow querying of the host timestamp in processBlock
This commit is contained in:
parent
5d096b46d7
commit
cfa289d943
31 changed files with 496 additions and 185 deletions
|
|
@ -69,9 +69,14 @@ public:
|
|||
CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
|
||||
|
||||
private:
|
||||
void audioDeviceIOCallback (const float** ins, int numIns, float** outs, int numOuts, int numSamples) override
|
||||
void audioDeviceIOCallbackWithContext (const float** ins,
|
||||
int numIns,
|
||||
float** outs,
|
||||
int numOuts,
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext& context) override
|
||||
{
|
||||
owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
|
||||
owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples, context);
|
||||
}
|
||||
|
||||
void audioDeviceAboutToStart (AudioIODevice* device) override
|
||||
|
|
@ -900,7 +905,8 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
|
|||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int numOutputChannels,
|
||||
int numSamples)
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext& context)
|
||||
{
|
||||
const ScopedLock sl (audioCallbackLock);
|
||||
|
||||
|
|
@ -912,15 +918,23 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
|
|||
|
||||
tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
|
||||
|
||||
callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
|
||||
outputChannelData, numOutputChannels, numSamples);
|
||||
callbacks.getUnchecked(0)->audioDeviceIOCallbackWithContext (inputChannelData,
|
||||
numInputChannels,
|
||||
outputChannelData,
|
||||
numOutputChannels,
|
||||
numSamples,
|
||||
context);
|
||||
|
||||
auto** tempChans = tempBuffer.getArrayOfWritePointers();
|
||||
|
||||
for (int i = callbacks.size(); --i > 0;)
|
||||
{
|
||||
callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
|
||||
tempChans, numOutputChannels, numSamples);
|
||||
callbacks.getUnchecked(i)->audioDeviceIOCallbackWithContext (inputChannelData,
|
||||
numInputChannels,
|
||||
tempChans,
|
||||
numOutputChannels,
|
||||
numSamples,
|
||||
context);
|
||||
|
||||
for (int chan = 0; chan < numOutputChannels; ++chan)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -526,8 +526,12 @@ private:
|
|||
class CallbackHandler;
|
||||
std::unique_ptr<CallbackHandler> callbackHandler;
|
||||
|
||||
void audioDeviceIOCallbackInt (const float** inputChannelData, int totalNumInputChannels,
|
||||
float** outputChannelData, int totalNumOutputChannels, int numSamples);
|
||||
void audioDeviceIOCallbackInt (const float** inputChannelData,
|
||||
int totalNumInputChannels,
|
||||
float** outputChannelData,
|
||||
int totalNumOutputChannels,
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext& context);
|
||||
void audioDeviceAboutToStartInt (AudioIODevice*);
|
||||
void audioDeviceStoppedInt();
|
||||
void audioDeviceErrorInt (const String&);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ namespace juce
|
|||
|
||||
class AudioIODevice;
|
||||
|
||||
/** Additional information that may be passed to the AudioIODeviceCallback. */
|
||||
struct AudioIODeviceCallbackContext
|
||||
{
|
||||
/** If the host provides this information, this field will be set to point to
|
||||
an integer holding the current value; otherwise, this will be nullptr.
|
||||
*/
|
||||
const uint64_t* hostTimeNs = nullptr;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
|
|
@ -87,7 +95,26 @@ public:
|
|||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int numOutputChannels,
|
||||
int numSamples) = 0;
|
||||
int numSamples)
|
||||
{
|
||||
ignoreUnused (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);
|
||||
}
|
||||
|
||||
/** The same as audioDeviceIOCallback(), but with an additional context argument.
|
||||
|
||||
The default implementation of this function will call audioDeviceIOCallback(),
|
||||
but you can override this function if you need to make use of the context information.
|
||||
*/
|
||||
virtual void audioDeviceIOCallbackWithContext (const float** inputChannelData,
|
||||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int numOutputChannels,
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext& context)
|
||||
{
|
||||
audioDeviceIOCallback (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);
|
||||
ignoreUnused (context);
|
||||
}
|
||||
|
||||
/** Called to indicate that the device is about to start calling back.
|
||||
|
||||
|
|
|
|||
|
|
@ -357,9 +357,11 @@ public:
|
|||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback->audioDeviceIOCallback (inputChannelBuffer.getArrayOfReadPointers(), numClientInputChannels,
|
||||
outputChannelBuffer.getArrayOfWritePointers(), numClientOutputChannels,
|
||||
actualBufferSize);
|
||||
callback->audioDeviceIOCallbackWithContext (inputChannelBuffer.getArrayOfReadPointers(),
|
||||
numClientInputChannels,
|
||||
outputChannelBuffer.getArrayOfWritePointers(),
|
||||
numClientOutputChannels,
|
||||
actualBufferSize, {});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -428,8 +428,12 @@ private:
|
|||
{
|
||||
if (auto* cb = callback.exchange (nullptr))
|
||||
{
|
||||
cb->audioDeviceIOCallback (inputChannelData, numInputChannels,
|
||||
outputChannelData, numOutputChannels, numFrames);
|
||||
cb->audioDeviceIOCallbackWithContext (inputChannelData,
|
||||
numInputChannels,
|
||||
outputChannelData,
|
||||
numOutputChannels,
|
||||
numFrames,
|
||||
{});
|
||||
callback.set (cb);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -605,7 +605,7 @@ public:
|
|||
{
|
||||
if (auto* cb = callback.exchange (nullptr))
|
||||
{
|
||||
cb->audioDeviceIOCallback (inputChannelData, inputChannels, outputChannelData, outputChannels, bufferSize);
|
||||
cb->audioDeviceIOCallbackWithContext (inputChannelData, inputChannels, outputChannelData, outputChannels, bufferSize, {});
|
||||
callback.set (cb);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
#include <juce_audio_basics/native/juce_mac_CoreAudioTimeConversions.h>
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
|
|
@ -900,9 +902,14 @@ struct iOSAudioIODevice::Pimpl : public AudioPlayHead,
|
|||
zeromem (inputData[c], channelDataSize);
|
||||
}
|
||||
|
||||
callback->audioDeviceIOCallback ((const float**) inputData, channelData.inputs ->numActiveChannels,
|
||||
outputData, channelData.outputs->numActiveChannels,
|
||||
(int) numFrames);
|
||||
const auto nanos = time != nullptr ? timeConversions.hostTimeToNanos (time->mHostTime) : 0;
|
||||
|
||||
callback->audioDeviceIOCallbackWithContext ((const float**) inputData,
|
||||
channelData.inputs ->numActiveChannels,
|
||||
outputData,
|
||||
channelData.outputs->numActiveChannels,
|
||||
(int) numFrames,
|
||||
{ (time != nullptr && (time->mFlags & kAudioTimeStampHostTimeValid) != 0) ? &nanos : nullptr });
|
||||
|
||||
for (int c = 0; c < channelData.outputs->numActiveChannels; ++c)
|
||||
{
|
||||
|
|
@ -1329,6 +1336,8 @@ struct iOSAudioIODevice::Pimpl : public AudioPlayHead,
|
|||
AudioBuffer<float> audioData { 0, 0 };
|
||||
};
|
||||
|
||||
CoreAudioTimeConversions timeConversions;
|
||||
|
||||
IOChannelData channelData;
|
||||
|
||||
BigInteger requestedInputChannels, requestedOutputChannels;
|
||||
|
|
|
|||
|
|
@ -711,11 +711,12 @@ public:
|
|||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback->audioDeviceIOCallback (inputChannelDataForCallback.getRawDataPointer(),
|
||||
inputChannelDataForCallback.size(),
|
||||
outputChannelDataForCallback.getRawDataPointer(),
|
||||
outputChannelDataForCallback.size(),
|
||||
bufferSize);
|
||||
callback->audioDeviceIOCallbackWithContext (inputChannelDataForCallback.getRawDataPointer(),
|
||||
inputChannelDataForCallback.size(),
|
||||
outputChannelDataForCallback.getRawDataPointer(),
|
||||
outputChannelDataForCallback.size(),
|
||||
bufferSize,
|
||||
{});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -433,9 +433,12 @@ private:
|
|||
channelOutBuffer[ch] = &context.analogOut[(Frames) (ch - analogChannelStart) * context.audioFrames];
|
||||
}
|
||||
|
||||
callback->audioDeviceIOCallback (channelInBuffer.getData(), actualNumberOfInputs,
|
||||
channelOutBuffer.getData(), actualNumberOfOutputs,
|
||||
(int) context.audioFrames);
|
||||
callback->audioDeviceIOCallbackWithContext (channelInBuffer.getData(),
|
||||
actualNumberOfInputs,
|
||||
channelOutBuffer.getData(),
|
||||
actualNumberOfOutputs,
|
||||
(int) context.audioFrames,
|
||||
{});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -462,8 +462,12 @@ private:
|
|||
if (callback != nullptr)
|
||||
{
|
||||
if ((numActiveInChans + numActiveOutChans) > 0)
|
||||
callback->audioDeviceIOCallback (const_cast<const float**> (inChans.getData()), numActiveInChans,
|
||||
outChans, numActiveOutChans, numSamples);
|
||||
callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inChans.getData()),
|
||||
numActiveInChans,
|
||||
outChans,
|
||||
numActiveOutChans,
|
||||
numSamples,
|
||||
{});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
#include <juce_audio_basics/native/juce_mac_CoreAudioTimeConversions.h>
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
|
|
@ -746,7 +748,8 @@ public:
|
|||
double getSampleRate() const { return sampleRate; }
|
||||
int getBufferSize() const { return bufferSize; }
|
||||
|
||||
void audioCallback (const AudioBufferList* inInputData,
|
||||
void audioCallback (const AudioTimeStamp* timeStamp,
|
||||
const AudioBufferList* inInputData,
|
||||
AudioBufferList* outOutputData)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
|
@ -778,11 +781,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
callback->audioDeviceIOCallback (const_cast<const float**> (tempInputBuffers.get()),
|
||||
numInputChans,
|
||||
tempOutputBuffers,
|
||||
numOutputChans,
|
||||
bufferSize);
|
||||
const auto nanos = timeStamp != nullptr ? timeConversions.hostTimeToNanos (timeStamp->mHostTime) : 0;
|
||||
|
||||
callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (tempInputBuffers.get()),
|
||||
numInputChans,
|
||||
tempOutputBuffers,
|
||||
numOutputChans,
|
||||
bufferSize,
|
||||
{ timeStamp != nullptr ? &nanos : nullptr });
|
||||
|
||||
for (int i = numOutputChans; --i >= 0;)
|
||||
{
|
||||
|
|
@ -838,6 +844,7 @@ public:
|
|||
AudioDeviceIOProcID audioProcID = {};
|
||||
|
||||
private:
|
||||
CoreAudioTimeConversions timeConversions;
|
||||
AudioIODeviceCallback* callback = nullptr;
|
||||
CriticalSection callbackLock;
|
||||
AudioDeviceID deviceID;
|
||||
|
|
@ -876,14 +883,14 @@ private:
|
|||
}
|
||||
|
||||
static OSStatus audioIOProc (AudioDeviceID /*inDevice*/,
|
||||
const AudioTimeStamp* /*inNow*/,
|
||||
const AudioTimeStamp* inNow,
|
||||
const AudioBufferList* inInputData,
|
||||
const AudioTimeStamp* /*inInputTime*/,
|
||||
AudioBufferList* outOutputData,
|
||||
const AudioTimeStamp* /*inOutputTime*/,
|
||||
void* device)
|
||||
{
|
||||
static_cast<CoreAudioInternal*> (device)->audioCallback (inInputData, outOutputData);
|
||||
static_cast<CoreAudioInternal*> (device)->audioCallback (inNow, inInputData, outOutputData);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
|
@ -1624,8 +1631,12 @@ private:
|
|||
const ScopedLock sl (callbackLock);
|
||||
|
||||
if (callback != nullptr)
|
||||
callback->audioDeviceIOCallback ((const float**) inputChans.getRawDataPointer(), numInputChans,
|
||||
outputChans.getRawDataPointer(), numOutputChans, numSamples);
|
||||
callback->audioDeviceIOCallbackWithContext ((const float**) inputChans.getRawDataPointer(),
|
||||
numInputChans,
|
||||
outputChans.getRawDataPointer(),
|
||||
numOutputChans,
|
||||
numSamples,
|
||||
{}); // Can't predict when the next output callback will happen
|
||||
else
|
||||
didCallback = false;
|
||||
}
|
||||
|
|
@ -1920,9 +1931,12 @@ private:
|
|||
outputFifo.finishedWrite (size1 + size2);
|
||||
}
|
||||
|
||||
void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,
|
||||
float** outputChannelData, int numOutputChannels,
|
||||
int numSamples) override
|
||||
void audioDeviceIOCallbackWithContext (const float** inputChannelData,
|
||||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int numOutputChannels,
|
||||
int numSamples,
|
||||
const AudioIODeviceCallbackContext&) override
|
||||
{
|
||||
if (numInputChannels > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1326,8 +1326,12 @@ private:
|
|||
inputFormat[i].convertToFloat (infos[i].buffers[bufferIndex], inBuffers[i], samps);
|
||||
}
|
||||
|
||||
currentCallback->audioDeviceIOCallback (const_cast<const float**> (inBuffers.getData()), numActiveInputChans,
|
||||
outBuffers, numActiveOutputChans, samps);
|
||||
currentCallback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inBuffers.getData()),
|
||||
numActiveInputChans,
|
||||
outBuffers,
|
||||
numActiveOutputChans,
|
||||
samps,
|
||||
{});
|
||||
|
||||
for (int i = 0; i < numActiveOutputChans; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1016,9 +1016,12 @@ public:
|
|||
|
||||
if (isStarted)
|
||||
{
|
||||
callback->audioDeviceIOCallback (inputBuffers.getArrayOfReadPointers(), inputBuffers.getNumChannels(),
|
||||
outputBuffers.getArrayOfWritePointers(), outputBuffers.getNumChannels(),
|
||||
bufferSizeSamples);
|
||||
callback->audioDeviceIOCallbackWithContext (inputBuffers.getArrayOfReadPointers(),
|
||||
inputBuffers.getNumChannels(),
|
||||
outputBuffers.getArrayOfWritePointers(),
|
||||
outputBuffers.getNumChannels(),
|
||||
bufferSizeSamples,
|
||||
{});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1515,8 +1515,12 @@ public:
|
|||
const ScopedTryLock sl (startStopLock);
|
||||
|
||||
if (sl.isLocked() && isStarted)
|
||||
callback->audioDeviceIOCallback (const_cast<const float**> (inputBuffers), numInputBuffers,
|
||||
outputBuffers, numOutputBuffers, bufferSize);
|
||||
callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inputBuffers),
|
||||
numInputBuffers,
|
||||
outputBuffers,
|
||||
numOutputBuffers,
|
||||
bufferSize,
|
||||
{});
|
||||
else
|
||||
outs.clear();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue