diff --git a/Audio/Visualization/VisualizationController.swift b/Audio/Visualization/VisualizationController.swift index 18d46064f..b5133ddf7 100644 --- a/Audio/Visualization/VisualizationController.swift +++ b/Audio/Visualization/VisualizationController.swift @@ -12,7 +12,7 @@ class VisualizationController : NSObject { var serialQueue = DispatchQueue(label: "Visualization Queue") var sampleRate = 0.0 var latency = 0.0 - var visAudio: [Float] = Array(repeating: 0.0, count: 44100 * 45) + var visAudio: [Float] = Array(repeating: 0.0, count: 44100 * 45) var visAudioCursor = 0 var visAudioSize = 0 var visSamplesPosted: UInt64 = 0 @@ -30,10 +30,12 @@ class VisualizationController : NSObject { @objc func reset() { serialQueue.sync { - self.latency = 0 - self.visAudioSize = 44100 * 45 - self.visAudio = Array(repeating: 0.0, count: visAudioSize) - self.visSamplesPosted = 0 + self.latency = 0; + let amount = self.visAudioSize + for i in 0..(repeating: 0.0, count: visAudioSize) - self.visAudioCursor = 0 + visAudioSize = (Int)(sampleRate * 45.0) + visAudio = Array(repeating: 0.0, count: visAudioSize) + visAudioCursor = 0 } } } @@ -62,23 +64,17 @@ class VisualizationController : NSObject { @objc func postVisPCM(_ inPCM: UnsafePointer?, amount: Int) { serialQueue.sync { - if(self.visAudioSize == 0) { - return - } - let bufferPointer = UnsafeRawPointer(inPCM) - if let bptr = bufferPointer { - let dataArray = bptr.assumingMemoryBound(to: Float.self) - var j = self.visAudioCursor - let k = self.visAudioSize - for i in 0..= k { j = 0 } - } - self.visAudioCursor = j - self.latency += Double(amount) / self.sampleRate - self.visSamplesPosted += UInt64(amount) + let bufferPointer = UnsafeBufferPointer(start: inPCM, count: amount) + var j = self.visAudioCursor + let k = self.visAudioSize + for i in 0..= k { j = 0 } } + self.visAudioCursor = j + self.latency += Double(amount) / self.sampleRate + self.visSamplesPosted += UInt64(amount); } } @@ -91,10 +87,19 @@ class VisualizationController : NSObject { @objc func copyVisPCM(_ outPCM: UnsafeMutablePointer?, visFFT: UnsafeMutablePointer?, latencyOffset: Double) { - outPCM?.update(repeating: 0.0, count: 4096) - visFFT?.update(repeating: 0.0, count: 2048) - if(self.visAudioSize == 0) { + if(outPCM != nil) { + let pcmPointer = UnsafeMutableBufferPointer(start: outPCM, count: 4096) + for i in 0...4095 { + pcmPointer[i] = 0.0 + } + } + if(visFFT != nil) { + let fftPointer = UnsafeMutableBufferPointer(start: visFFT, count: 2048) + for i in 0...2047 { + fftPointer[i] = 0.0 + } + } return } @@ -103,16 +108,13 @@ class VisualizationController : NSObject { serialQueue.sync { // Offset latency so the target sample is in the center of the window let latencySamples = (Int)((self.latency + latencyOffset) * self.sampleRate) + 2048 - var samplesToDo = 4096 + var samplesToDo = 4096; if(latencySamples < 0) { - return - } - if(latencySamples + 4096 > visAudioSize) { - return + return; } if(latencySamples < 4096) { // Latency can sometimes dip below this threshold - samplesToDo = latencySamples + samplesToDo = latencySamples; } var j = self.visAudioCursor - latencySamples let k = self.visAudioSize @@ -129,7 +131,13 @@ class VisualizationController : NSObject { } } - outPCM?.update(from: outPCMCopy, count: 4096) + if(outPCM != nil) { + let pcmPointer = UnsafeMutableBufferPointer(start: outPCM, count: 4096) + for i in 0...4095 { + let x = outPCMCopy[i] + pcmPointer[i] = x + } + } if(visFFT != nil) { serialQueue.sync { diff --git a/Visualization/SpectrumViewCG.m b/Visualization/SpectrumViewCG.m index 58b41e759..dc633ff0a 100644 --- a/Visualization/SpectrumViewCG.m +++ b/Visualization/SpectrumViewCG.m @@ -41,8 +41,6 @@ extern NSString *CogPlaybackDidStopNotificiation; NSColor *borderColor; ddb_analyzer_t _analyzer; ddb_analyzer_draw_data_t _draw_data; - BOOL invalidateSpectrum; - float analyzerLastWidth; float visAudio[4096], visFFT[2048]; @@ -98,12 +96,6 @@ extern NSString *CogPlaybackDidStopNotificiation; paused = NO; isListening = NO; - visSamplesLastPosted = [self->visController samplesPosted]; - - invalidateSpectrum = YES; - - analyzerLastWidth = -1.0f; - saLowerBound = LOWER_BOUND; [self colorsDidChange:nil]; @@ -130,7 +122,6 @@ extern NSString *CogPlaybackDidStopNotificiation; - (void)enableFullView { isFullView = YES; _analyzer.freq_is_log = 1; - invalidateSpectrum = YES; [self repaint]; } @@ -248,10 +239,8 @@ extern NSString *CogPlaybackDidStopNotificiation; } - (void)timerRun:(NSTimer *)timer { - invalidateSpectrum = YES; [self repaint]; - if(visSamplesLastPosted) - visLatencyOffset -= 1.0f / 60.0f; + visLatencyOffset -= 1.0 / 60.0; } - (void)colorsDidChange:(NSNotification *)notification { @@ -424,28 +413,16 @@ extern NSString *CogPlaybackDidStopNotificiation; } UInt64 samplesPosted = [self->visController samplesPosted]; - if(!samplesPosted) return; - - if(samplesPosted != visSamplesLastPosted) { - float latencyOffset = (float)(((double)((SInt64)samplesPosted - (SInt64)visSamplesLastPosted)) / [self->visController readSampleRate]); - if (latencyOffset < 0) - latencyOffset = -visLatencyOffset; + if (samplesPosted != visSamplesLastPosted) { visSamplesLastPosted = samplesPosted; - visLatencyOffset += latencyOffset; + visLatencyOffset = 0.0; } - BOOL invalidateWidth = isFullView && (fabs(analyzerLastWidth - self.bounds.size.width) > 1e-5); - if(invalidateWidth) - analyzerLastWidth = self.bounds.size.width; + [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:visLatencyOffset]; - if(invalidateWidth || invalidateSpectrum) { - [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:visLatencyOffset]; - - ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); - ddb_analyzer_tick(&_analyzer); - ddb_analyzer_get_draw_data(&_analyzer, self.bounds.size.width, self.bounds.size.height, &_draw_data); - invalidateSpectrum = NO; - } + ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); + ddb_analyzer_tick(&_analyzer); + ddb_analyzer_get_draw_data(&_analyzer, self.bounds.size.width, self.bounds.size.height, &_draw_data); if(isFullView) { [self drawSaGrid]; @@ -461,7 +438,6 @@ extern NSString *CogPlaybackDidStopNotificiation; _analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS; _analyzer.mode_did_change = 1; - invalidateSpectrum = YES; [self repaint]; } diff --git a/Visualization/SpectrumViewSK.m b/Visualization/SpectrumViewSK.m index 1d8ae0be3..6eae05045 100644 --- a/Visualization/SpectrumViewSK.m +++ b/Visualization/SpectrumViewSK.m @@ -39,7 +39,6 @@ extern NSString *CogPlaybackDidStopNotificiation; NSColor *backgroundColor; ddb_analyzer_t _analyzer; ddb_analyzer_draw_data_t _draw_data; - BOOL invalidateSpectrum; SCNVector3 cameraPosition2d; SCNVector3 cameraEulerAngles2d; @@ -85,7 +84,7 @@ extern NSString *CogPlaybackDidStopNotificiation; NSDictionary *sceneOptions = @{ SCNPreferredRenderingAPIKey: @(SCNRenderingAPIMetal), SCNPreferredDeviceKey: device, - SCNPreferLowPowerDeviceKey: @(YES) + SCNPreferLowPowerDeviceKey: @(NO) }; self = [super initWithFrame:frame options:sceneOptions]; @@ -192,10 +191,6 @@ extern NSString *CogPlaybackDidStopNotificiation; isListening = NO; cameraControlEnabled = NO; - invalidateSpectrum = YES; - - visSamplesLastPosted = [self->visController samplesPosted]; - [self setBackgroundColor:[NSColor clearColor]]; SCNScene *theScene = [SCNScene sceneNamed:@"Scenes.scnassets/Spectrum.scn"]; @@ -316,38 +311,21 @@ extern NSString *CogPlaybackDidStopNotificiation; [self updateVisListening]; if(stopped) { - if(invalidateSpectrum) { - [self drawBaseBands]; - invalidateSpectrum = NO; - } + [self drawBaseBands]; return; } UInt64 samplesPosted = [self->visController samplesPosted]; - if(!samplesPosted) { - if(invalidateSpectrum) { - [self drawBaseBands]; - invalidateSpectrum = NO; - } - return; - } - - if(samplesPosted != visSamplesLastPosted) { - float latencyOffset = (float)(((double)((SInt64)samplesPosted - (SInt64)visSamplesLastPosted)) / [self->visController readSampleRate]); - if (latencyOffset < 0) - latencyOffset = -visLatencyOffset; + if (samplesPosted != visSamplesLastPosted) { visSamplesLastPosted = samplesPosted; - visLatencyOffset += latencyOffset; + visLatencyOffset = 0.0; } - if(invalidateSpectrum) { - [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:visLatencyOffset]; + [self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:visLatencyOffset]; - ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); - ddb_analyzer_tick(&_analyzer); - ddb_analyzer_get_draw_data(&_analyzer, 11.0, 1.0, &_draw_data); - invalidateSpectrum = NO; - } + ddb_analyzer_process(&_analyzer, [self->visController readSampleRate] / 2.0, 1, visFFT, 2048); + ddb_analyzer_tick(&_analyzer); + ddb_analyzer_get_draw_data(&_analyzer, 11.0, 1.0, &_draw_data); [self drawAnalyzer]; } @@ -368,10 +346,8 @@ extern NSString *CogPlaybackDidStopNotificiation; } - (void)timerRun:(NSTimer *)timer { - invalidateSpectrum = YES; [self repaint]; - if(visSamplesLastPosted) - visLatencyOffset -= 1.0f / 60.0f; + visLatencyOffset -= 1.0 / 60.0; } - (void)startPlayback { @@ -400,7 +376,6 @@ extern NSString *CogPlaybackDidStopNotificiation; stopped = YES; paused = NO; bandsReset = NO; - invalidateSpectrum = YES; [self updateVisListening]; [self repaint]; } @@ -445,13 +420,11 @@ extern NSString *CogPlaybackDidStopNotificiation; const int barBase = i * barStep; const int barIndex = barBase + j; if(barIndex < _draw_data.bar_count) { - const float bar_height = bar[barIndex].bar_height; - const float peak_ypos = bar[barIndex].peak_ypos; - if(bar_height > maxValue) { - maxValue = bar_height; + if(bar[barIndex].bar_height > maxValue) { + maxValue = bar[barIndex].bar_height; } - if(peak_ypos > maxMax) { - maxMax = peak_ypos; + if(bar[barIndex].peak_ypos > maxMax) { + maxMax = bar[barIndex].peak_ypos; } } } @@ -482,7 +455,6 @@ extern NSString *CogPlaybackDidStopNotificiation; _analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS; _analyzer.mode_did_change = 1; - invalidateSpectrum = YES; [self repaint]; }