[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 <kode54@gmail.com>
swiftingly
Christopher Snowhill 2022-06-26 05:36:20 -07:00
parent 038b0b8067
commit 6f6b5d6986
4 changed files with 19 additions and 9 deletions

View File

@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)postSampleRate:(double)sampleRate; - (void)postSampleRate:(double)sampleRate;
- (void)postVisPCM:(const float *)inPCM amount:(int)amount; - (void)postVisPCM:(const float *)inPCM amount:(int)amount;
- (double)readSampleRate; - (double)readSampleRate;
- (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT; - (void)copyVisPCM:(float *)outPCM visFFT:(float *)outFFT latencyOffset:(double)latency;
@end @end

View File

@ -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) { @synchronized(self) {
if(!sampleRate) { if(!sampleRate) {
bzero(outPCM, 4096 * sizeof(float)); bzero(outPCM, 4096 * sizeof(float));
bzero(outFFT, 2048 * sizeof(float)); if(outFFT) {
bzero(outFFT, 2048 * sizeof(float));
}
return; return;
} }
int latencySamples = (int)(sampleRate * latency); int latencySamples = (int)(sampleRate * (self->latency + latency));
if(latencySamples < 4096) latencySamples = 4096;
int readCursor = visAudioCursor - latencySamples; int readCursor = visAudioCursor - latencySamples;
int samples = 4096; int samples = 4096;
int samplesRead = 0; int samplesRead = 0;
if(readCursor < 0) while(readCursor < 0)
readCursor += visAudioSize; readCursor += visAudioSize;
else if(readCursor >= visAudioSize) while(readCursor >= visAudioSize)
readCursor -= visAudioSize; readCursor -= visAudioSize;
while(samples > 0) { while(samples > 0) {
int samplesToRead = (int)(visAudioSize - readCursor); int samplesToRead = (int)(visAudioSize - readCursor);
@ -105,7 +113,9 @@ static VisualizationController *_sharedController = nil;
if(readCursor >= visAudioSize) readCursor -= visAudioSize; if(readCursor >= visAudioSize) readCursor -= visAudioSize;
} }
} }
fft_calculate(outPCM, outFFT, 2048); if(outFFT) {
fft_calculate(outPCM, outFFT, 2048);
}
} }
@end @end

View File

@ -370,7 +370,7 @@ extern NSString *CogPlaybackDidStopNotficiation;
float visAudio[4096], visFFT[2048]; 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_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048);
ddb_analyzer_tick(&_analyzer); ddb_analyzer_tick(&_analyzer);

View File

@ -273,7 +273,7 @@ extern NSString *CogPlaybackDidStopNotficiation;
float visAudio[4096], visFFT[2048]; 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_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048);
ddb_analyzer_tick(&_analyzer); ddb_analyzer_tick(&_analyzer);