From 85f6279d215b5c2acba828f1d6f5ddbad8f4d82b Mon Sep 17 00:00:00 2001 From: "lllucius@gmail.com" Date: Sun, 11 Jan 2015 22:52:08 +0000 Subject: [PATCH] This fixes a couple of issues with AudioUnits and 1 with latency If latency was introduced by an effect, the input position could get offset by the amount of latency, such that the same input would be processed twice for the number of sample of latency. There was an issue in AUs where a "latency done" flags wasn't being reset and so the second and subsequent uses of an effect could not latency correct. And in research that, I found that you need to set the sample rate on all 3 scopes (global, input, and output) instead of just the global scope. --- src/effects/Effect.cpp | 28 ++++--- src/effects/audiounits/AudioUnitEffect.cpp | 93 ++++++++++++---------- src/effects/audiounits/AudioUnitEffect.h | 2 - 3 files changed, 68 insertions(+), 55 deletions(-) diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index f77446d0f..e16502623 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -1003,6 +1003,8 @@ bool Effect::ProcessTrack(int count, sampleCount outputBufferCnt = 0; bool cleared = false; + int chans = wxMin(mNumAudioOut, mNumChannels); + WaveTrack *genLeft = NULL; WaveTrack *genRight = NULL; sampleCount genLength = 0; @@ -1134,6 +1136,13 @@ bool Effect::ProcessTrack(int count, inputBufferCnt -= curBlockSize; } + // "ls" and "rs" serve as the input sample index for the left and + // right channels when processing the input samples. If we flip + // over to processing delayed samples, they simply become counters + // for the progress display. + inLeftPos += curBlockSize; + inRightPos += curBlockSize; + // Get the current number of delayed samples and accumulate if (isProcessor) { @@ -1154,22 +1163,22 @@ bool Effect::ProcessTrack(int count, else if (curDelay > 0) { curBlockSize -= curDelay; - for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++) + for (int i = 0; i < chans; i++) { - memmove(mOutBufPos[i], mOutBufPos[i] + curDelay, SAMPLE_SIZE(floatSample) * curBlockSize); + memmove(mOutBufPos[i], mOutBufPos[i] + curDelay, sizeof(float) * curBlockSize); } curDelay = 0; } } - // + // Adjust the number of samples in the output buffers outputBufferCnt += curBlockSize; - // + // Still have room in the output buffers if (outputBufferCnt < mBufferSize) { // Bump to next output buffer position - for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++) + for (int i = 0; i < chans; i++) { mOutBufPos[i] += curBlockSize; } @@ -1196,7 +1205,7 @@ bool Effect::ProcessTrack(int count, } // Reset the output buffer positions - for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++) + for (int i = 0; i < chans; i++) { mOutBufPos[i] = mOutBuffer[i]; } @@ -1207,13 +1216,6 @@ bool Effect::ProcessTrack(int count, outputBufferCnt = 0; } - // "ls" and "rs" serve as the input sample index for the left and - // right channels when processing the input samples. If we flip - // over to processing delayed samples, they simply become counters - // for the progress display. - inLeftPos += curBlockSize; - inRightPos += curBlockSize; - if (mNumChannels > 1) { if (TrackGroupProgress(count, (inLeftPos - leftStart) / (double) len)) diff --git a/src/effects/audiounits/AudioUnitEffect.cpp b/src/effects/audiounits/AudioUnitEffect.cpp index 306e6d21e..52ca0515b 100644 --- a/src/effects/audiounits/AudioUnitEffect.cpp +++ b/src/effects/audiounits/AudioUnitEffect.cpp @@ -931,8 +931,6 @@ AudioUnitEffect::AudioUnitEffect(const wxString & path, mUnit = NULL; - mLatency = 0.0; - mTailTime = 0.0; mBlockSize = 0.0; mUIHost = NULL; @@ -1140,37 +1138,15 @@ bool AudioUnitEffect::SetHost(EffectHostInterface *host) SetRateAndChannels(); - UInt32 dataSize; - - // Retrieve the latency (can be updated via an event) - dataSize = sizeof(mLatency); - mLatency = 0.0; - AudioUnitGetProperty(mUnit, - kAudioUnitProperty_Latency, - kAudioUnitScope_Global, - 0, - &mLatency, - &dataSize); - - // Retrieve the tail time - dataSize = sizeof(mTailTime); - mTailTime = 0.0; - AudioUnitGetProperty(mUnit, - kAudioUnitProperty_TailTime, - kAudioUnitScope_Global, - 0, - &mTailTime, - &dataSize); - // Retrieve the desired number of frames per slice - dataSize = sizeof(mBlockSize); + UInt32 dataSize = sizeof(mBlockSize); mBlockSize = 512; AudioUnitGetProperty(mUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &mBlockSize, - &dataSize); + &dataSize); // mHost will be null during registration if (mHost) @@ -1307,10 +1283,21 @@ sampleCount AudioUnitEffect::GetBlockSize(sampleCount maxBlockSize) sampleCount AudioUnitEffect::GetLatency() { + // Retrieve the latency (can be updated via an event) if (mUseLatency && !mLatencyDone) { mLatencyDone = true; - return mLatency * mSampleRate; + + Float64 latency = 0.0; + UInt32 dataSize = sizeof(latency); + AudioUnitGetProperty(mUnit, + kAudioUnitProperty_Latency, + kAudioUnitScope_Global, + 0, + &latency, + &dataSize); + + return (sampleCount) (latency * mSampleRate); } return 0; @@ -1318,7 +1305,17 @@ sampleCount AudioUnitEffect::GetLatency() sampleCount AudioUnitEffect::GetTailSize() { - return mTailTime * mSampleRate; + // Retrieve the tail time + Float64 tailTime = 0.0; + UInt32 dataSize = sizeof(tailTime); + AudioUnitGetProperty(mUnit, + kAudioUnitProperty_TailTime, + kAudioUnitScope_Global, + 0, + &tailTime, + &dataSize); + + return (sampleCount) (tailTime * mSampleRate); } bool AudioUnitEffect::IsReady() @@ -1374,6 +1371,8 @@ bool AudioUnitEffect::ProcessInitialize() return false; } + mLatencyDone = false; + mReady = true; return true; @@ -2320,6 +2319,30 @@ bool AudioUnitEffect::SetRateAndChannels() return false; } + auResult = AudioUnitSetProperty(mUnit, + kAudioUnitProperty_SampleRate, + kAudioUnitScope_Input, + 0, + &mSampleRate, + sizeof(Float64)); + if (auResult != 0) + { + printf("Didn't accept sample rate\n"); + return false; + } + + auResult = AudioUnitSetProperty(mUnit, + kAudioUnitProperty_SampleRate, + kAudioUnitScope_Output, + 0, + &mSampleRate, + sizeof(Float64)); + if (auResult != 0) + { + printf("Didn't accept sample rate\n"); + return false; + } + AudioStreamBasicDescription streamFormat = {0}; streamFormat.mSampleRate = mSampleRate; @@ -2481,18 +2504,8 @@ void AudioUnitEffect::EventListener(const AudioUnitEvent *inEvent, // We're only registered for Latency changes if (inEvent->mArgument.mProperty.mPropertyID == kAudioUnitProperty_Latency) { - // Retrieve the latency - UInt32 dataSize = sizeof(mLatency); - mLatency = 0.0; - AudioUnitGetProperty(mUnit, - kAudioUnitProperty_Latency, - kAudioUnitScope_Global, - 0, - &mLatency, - &dataSize); - - // And allow change to be used - mLatencyDone = false; + // Allow change to be used + //mLatencyDone = false; } return; diff --git a/src/effects/audiounits/AudioUnitEffect.h b/src/effects/audiounits/AudioUnitEffect.h index 23db95948..752ec5503 100644 --- a/src/effects/audiounits/AudioUnitEffect.h +++ b/src/effects/audiounits/AudioUnitEffect.h @@ -194,8 +194,6 @@ private: int mAudioOuts; bool mInteractive; bool mLatencyDone; - Float64 mLatency; // in seconds...multiply by samplerate - Float64 mTailTime; // in seconds...multiply by samplerate UInt32 mBlockSize; double mSampleRate;