Visualization: Make latency animation smoother

Compensate for latency by incrementing an offset
according to animation frame rate.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2024-09-20 22:12:50 -07:00
parent 26bdd7fcc0
commit 42a7232fda
4 changed files with 36 additions and 2 deletions

View file

@ -15,12 +15,15 @@ NS_ASSUME_NONNULL_BEGIN
float *visAudio;
int visAudioCursor, visAudioSize;
float *visAudioTemp;
uint64_t visSamplesPosted;
}
+ (VisualizationController *)sharedController;
- (void)postLatency:(double)latency;
- (UInt64)samplesPosted;
- (void)postSampleRate:(double)sampleRate;
- (void)postVisPCM:(const float *)inPCM amount:(int)amount;
- (double)readSampleRate;

View file

@ -15,6 +15,7 @@ class VisualizationController : NSObject {
var visAudio: [Float] = Array(repeating: 0.0, count: 44100 * 45)
var visAudioCursor = 0
var visAudioSize = 0
var visSamplesPosted: UInt64 = 0
private static var sharedVisualizationController: VisualizationController = {
let visualizationController = VisualizationController()
@ -34,6 +35,7 @@ class VisualizationController : NSObject {
for i in 0..<amount {
self.visAudio[i] = 0
}
self.visSamplesPosted = 0;
}
}
@ -41,6 +43,11 @@ class VisualizationController : NSObject {
func postLatency(_ latency: Double) {
self.latency = latency
}
@objc
func samplesPosted() -> UInt64 {
return self.visSamplesPosted
}
@objc
func postSampleRate(_ sampleRate: Double) {
@ -67,6 +74,7 @@ class VisualizationController : NSObject {
}
self.visAudioCursor = j
self.latency += Double(amount) / self.sampleRate
self.visSamplesPosted += UInt64(amount);
}
}
@ -101,6 +109,9 @@ class VisualizationController : NSObject {
// 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;
if(latencySamples < 0) {
return;
}
if(latencySamples < 4096) {
// Latency can sometimes dip below this threshold
samplesToDo = latencySamples;

View file

@ -42,6 +42,9 @@ extern NSString *CogPlaybackDidStopNotificiation;
ddb_analyzer_draw_data_t _draw_data;
float visAudio[4096], visFFT[2048];
UInt64 visSamplesLastPosted;
double visLatencyOffset;
}
@end
@ -234,6 +237,7 @@ extern NSString *CogPlaybackDidStopNotificiation;
- (void)timerRun:(NSTimer *)timer {
[self repaint];
visLatencyOffset -= 1.0 / 60.0;
}
- (void)colorsDidChange:(NSNotification *)notification {
@ -403,7 +407,13 @@ extern NSString *CogPlaybackDidStopNotificiation;
_analyzer.view_width = self.bounds.size.width;
}
[self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0];
UInt64 samplesPosted = [self->visController samplesPosted];
if (samplesPosted != visSamplesLastPosted) {
visSamplesLastPosted = samplesPosted;
visLatencyOffset = 0.0;
}
[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);

View file

@ -45,6 +45,9 @@ extern NSString *CogPlaybackDidStopNotificiation;
SCNVector3 cameraEulerAngles3d;
float visAudio[4096], visFFT[2048];
UInt64 visSamplesLastPosted;
double visLatencyOffset;
}
@end
@ -307,7 +310,13 @@ extern NSString *CogPlaybackDidStopNotificiation;
return;
}
[self->visController copyVisPCM:&visAudio[0] visFFT:&visFFT[0] latencyOffset:0];
UInt64 samplesPosted = [self->visController samplesPosted];
if (samplesPosted != visSamplesLastPosted) {
visSamplesLastPosted = samplesPosted;
visLatencyOffset = 0.0;
}
[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);
@ -333,6 +342,7 @@ extern NSString *CogPlaybackDidStopNotificiation;
- (void)timerRun:(NSTimer *)timer {
[self repaint];
visLatencyOffset -= 1.0 / 60.0;
}
- (void)startPlayback {