From 6f6b5d6986f3da79db5fa9884e8fe8f321d4fdae Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sun, 26 Jun 2022 05:36:20 -0700 Subject: [PATCH] [Visualization System] Change API a bit Now the API makes both PCM and FFT data optional, and will do nothing if neither are requested. Also, it now supports a latency offset in seconds with floating point precision. The two built-in visualizations currently request zero larency. Increasing the latency asks for even older samples while specifying a negative count requests samples from the "future" relative to what the listener is hearing. Signed-off-by: Christopher Snowhill --- Audio/Visualization/VisualizationController.h | 2 +- Audio/Visualization/VisualizationController.m | 22 ++++++++++++++----- SpectrumViewCG.m | 2 +- Visualization/SpectrumViewSK.m | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Audio/Visualization/VisualizationController.h b/Audio/Visualization/VisualizationController.h index 45e7050d3..68390ef27 100644 --- a/Audio/Visualization/VisualizationController.h +++ b/Audio/Visualization/VisualizationController.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)postSampleRate:(double)sampleRate; - (void)postVisPCM:(const float *)inPCM amount:(int)amount; - (double)readSampleRate; -- (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT; +- (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT latencyOffset:(double)latency; @end diff --git a/Audio/Visualization/VisualizationController.m b/Audio/Visualization/VisualizationController.m index fd6f8783a..30bcf6c4f 100644 --- a/Audio/Visualization/VisualizationController.m +++ b/Audio/Visualization/VisualizationController.m @@ -80,20 +80,28 @@ static VisualizationController *_sharedController = nil; } } -- (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT { +- (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT latencyOffset:(double)latency { + if(!outPCM && !outFFT) return; + + float tempPCM[4096]; + if(!outPCM) outPCM = &tempPCM[0]; + @synchronized(self) { if(!sampleRate) { bzero(outPCM, 4096 * sizeof(float)); - bzero(outFFT, 2048 * sizeof(float)); + if(outFFT) { + bzero(outFFT, 2048 * sizeof(float)); + } return; } - int latencySamples = (int)(sampleRate * latency); + int latencySamples = (int)(sampleRate * (self->latency + latency)); + if(latencySamples < 4096) latencySamples = 4096; int readCursor = visAudioCursor - latencySamples; int samples = 4096; int samplesRead = 0; - if(readCursor < 0) + while(readCursor < 0) readCursor += visAudioSize; - else if(readCursor >= visAudioSize) + while(readCursor >= visAudioSize) readCursor -= visAudioSize; while(samples > 0) { int samplesToRead = (int)(visAudioSize - readCursor); @@ -105,7 +113,9 @@ static VisualizationController *_sharedController = nil; if(readCursor >= visAudioSize) readCursor -= visAudioSize; } } - fft_calculate(outPCM, outFFT, 2048); + if(outFFT) { + fft_calculate(outPCM, outFFT, 2048); + } } @end diff --git a/SpectrumViewCG.m b/SpectrumViewCG.m index f4735803f..46fc1bd3f 100644 --- a/SpectrumViewCG.m +++ b/SpectrumViewCG.m @@ -370,7 +370,7 @@ extern NSString *CogPlaybackDidStopNotficiation; float visAudio[4096], visFFT[2048]; - [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0]]; + [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0]; ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); ddb_analyzer_tick(&_analyzer); diff --git a/Visualization/SpectrumViewSK.m b/Visualization/SpectrumViewSK.m index ee585d250..236fe2b43 100644 --- a/Visualization/SpectrumViewSK.m +++ b/Visualization/SpectrumViewSK.m @@ -273,7 +273,7 @@ extern NSString *CogPlaybackDidStopNotficiation; float visAudio[4096], visFFT[2048]; - [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0]]; + [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0]; ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); ddb_analyzer_tick(&_analyzer);