From 3a9db65b5387fbc14d3a055665d511a983ef394f Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 24 Jun 2022 03:43:50 -0700 Subject: [PATCH] [Visualization] Resample all visualizer audio Visualizer audio is now resampled to 44100 Hz, for consistency across the system. Signed-off-by: Christopher Snowhill --- Audio/Output/OutputAVFoundation.h | 6 ++- Audio/Output/OutputAVFoundation.m | 74 +++++++++++++++++++++++++++---- Audio/ThirdParty/r8bstate.hpp | 7 +-- 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/Audio/Output/OutputAVFoundation.h b/Audio/Output/OutputAVFoundation.h index afd4c9669..fc042da4c 100644 --- a/Audio/Output/OutputAVFoundation.h +++ b/Audio/Output/OutputAVFoundation.h @@ -36,9 +36,12 @@ using std::atomic_long; @interface OutputAVFoundation : NSObject { OutputNode *outputController; - BOOL r8bFlushing, r8bFlushed, r8bDone; + BOOL r8bDone; void *r8bstate, *r8bold; + void *r8bvis; + double lastVisRate; + BOOL stopInvoked; BOOL running; BOOL stopping; @@ -46,6 +49,7 @@ using std::atomic_long; BOOL started; BOOL paused; BOOL restarted; + BOOL stopFlush; BOOL eqEnabled; BOOL eqInitialized; diff --git a/Audio/Output/OutputAVFoundation.m b/Audio/Output/OutputAVFoundation.m index 1ee1be8aa..bd27fb726 100644 --- a/Audio/Output/OutputAVFoundation.m +++ b/Audio/Output/OutputAVFoundation.m @@ -63,7 +63,6 @@ static OSStatus eqRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioA amountToRead = 1024; - int visTabulated = 0; float visAudio[amountToRead]; // Chunk size if(stopping == YES || [outputController shouldContinue] == NO) { @@ -145,8 +144,65 @@ static OSStatus eqRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioA [downmixerForVis process:outputPtr frameCount:frameCount - output:visAudio]; - visTabulated += frameCount; + output:&visAudio[0]]; + + [visController postSampleRate:44100.0]; + + float visTemp[8192]; + if(newFormat.mSampleRate != 44100.0) { + if(newFormat.mSampleRate != lastVisRate) { + if(r8bvis) { + for(;;) { + int samplesFlushed; + [currentPtsLock lock]; + samplesFlushed = (int)r8bstate_flush(r8bvis, &visTemp[0], 8192); + [currentPtsLock unlock]; + if(samplesFlushed) { + [visController postVisPCM:visTemp amount:samplesFlushed]; + } else { + break; + } + } + [currentPtsLock lock]; + r8bstate_delete(r8bvis); + r8bvis = NULL; + [currentPtsLock unlock]; + } + lastVisRate = newFormat.mSampleRate; + [currentPtsLock lock]; + r8bvis = r8bstate_new(1, 1024, lastVisRate, 44100.0); + [currentPtsLock unlock]; + } + if(r8bvis) { + size_t inDone = 0; + int samplesProcessed; + [currentPtsLock lock]; + samplesProcessed = (int)r8bstate_resample(r8bvis, &visAudio[0], frameCount, &inDone, &visTemp[0], 8192); + [currentPtsLock unlock]; + if(samplesProcessed) { + [visController postVisPCM:&visTemp[0] amount:samplesProcessed]; + } + } + } else if(r8bvis) { + for(;;) { + int samplesFlushed; + [currentPtsLock lock]; + samplesFlushed = (int)r8bstate_flush(r8bvis, &visTemp[0], 8192); + [currentPtsLock unlock]; + if(samplesFlushed) { + [visController postVisPCM:visTemp amount:samplesFlushed]; + } else { + break; + } + } + [currentPtsLock lock]; + r8bstate_delete(r8bvis); + r8bvis = NULL; + [currentPtsLock unlock]; + [visController postVisPCM:&visAudio[0] amount:frameCount]; + } else { + [visController postVisPCM:&visAudio[0] amount:frameCount]; + } cblas_scopy((int)(frameCount * newFormat.mChannelsPerFrame), outputPtr, 1, &inputBuffer[0], 1); amountRead = frameCount; @@ -178,9 +234,6 @@ static OSStatus eqRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioA scale_by_volume(&inputBuffer[0], amountRead * newFormat.mChannelsPerFrame, volumeScale); - [visController postSampleRate:newFormat.mSampleRate]; - [visController postVisPCM:visAudio amount:visTabulated]; - return amountRead; } @@ -750,12 +803,13 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons downmixerForVis = nil; - r8bFlushing = NO; - r8bFlushed = NO; r8bDone = NO; r8bstate = NULL; r8bold = NULL; + r8bvis = NULL; + lastVisRate = 44100.0; + AudioComponentDescription desc; NSError *err; @@ -999,6 +1053,10 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons r8bstate_delete(r8bold); r8bold = NULL; } + if(r8bvis) { + r8bstate_delete(r8bvis); + r8bvis = NULL; + } } } diff --git a/Audio/ThirdParty/r8bstate.hpp b/Audio/ThirdParty/r8bstate.hpp index b39f43e99..a425698f7 100644 --- a/Audio/ThirdParty/r8bstate.hpp +++ b/Audio/ThirdParty/r8bstate.hpp @@ -21,11 +21,12 @@ struct r8bstate { uint64_t inProcessed; uint64_t outProcessed; double sampleRatio; + double dstRate; r8b::CFixedBuffer InBuf; r8b::CFixedBuffer *OutBufs; r8b::CDSPResampler24 **Resamps; - r8bstate(int _channelCount, int _bufferCapacity, double srcRate, double dstRate) - : channelCount(_channelCount), bufferCapacity(_bufferCapacity), inProcessed(0), outProcessed(0), remainder(0) { + r8bstate(int _channelCount, int _bufferCapacity, double srcRate, double _dstRate) + : channelCount(_channelCount), bufferCapacity(_bufferCapacity), inProcessed(0), outProcessed(0), remainder(0), dstRate(_dstRate) { InBuf.alloc(bufferCapacity); OutBufs = new r8b::CFixedBuffer[channelCount]; Resamps = new r8b::CDSPResampler24 *[channelCount]; @@ -44,7 +45,7 @@ struct r8bstate { } double latency() { - return ((double)inProcessed * sampleRatio) - (double)outProcessed; + return (((double)inProcessed * sampleRatio) - (double)outProcessed) / dstRate; } int resample(const float *input, size_t inCount, size_t *inDone, float *output, size_t outMax) {