Clean up audio engine cruft

This commit is contained in:
samhenrigold
2025-09-06 16:04:46 -04:00
parent 4b1159aa34
commit f4ca510ade

View File

@@ -76,8 +76,6 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
NSLog(@"[CreakAudioEngine] Failed to load audio files"); NSLog(@"[CreakAudioEngine] Failed to load audio files");
return nil; return nil;
} }
NSLog(@"[CreakAudioEngine] Successfully initialized");
} }
return self; return self;
} }
@@ -122,16 +120,12 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
return NO; return NO;
} }
// Now connect the audio graph using the file's native format // Connect the audio graph using the file's native format
AVAudioFormat *fileFormat = self.creakLoopFile.processingFormat; AVAudioFormat *fileFormat = self.creakLoopFile.processingFormat;
NSLog(@"[CreakAudioEngine] File format: %.0f Hz, %lu channels",
fileFormat.sampleRate, (unsigned long)fileFormat.channelCount);
// Connect audio graph: CreakPlayer -> Varispeed -> Mixer // Connect audio graph: CreakPlayer -> Varispeed -> Mixer
[self.audioEngine connect:self.creakPlayerNode to:self.varispeadUnit format:fileFormat]; [self.audioEngine connect:self.creakPlayerNode to:self.varispeadUnit format:fileFormat];
[self.audioEngine connect:self.varispeadUnit to:self.mixerNode format:fileFormat]; [self.audioEngine connect:self.varispeadUnit to:self.mixerNode format:fileFormat];
NSLog(@"[CreakAudioEngine] Successfully loaded creak loop and connected audio graph");
return YES; return YES;
} }
@@ -150,8 +144,6 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
// Start looping the creak sound // Start looping the creak sound
[self startCreakLoop]; [self startCreakLoop];
NSLog(@"[CreakAudioEngine] Audio engine started");
} }
- (void)stopEngine { - (void)stopEngine {
@@ -161,8 +153,6 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
[self.creakPlayerNode stop]; [self.creakPlayerNode stop];
[self.audioEngine stop]; [self.audioEngine stop];
NSLog(@"[CreakAudioEngine] Audio engine stopped");
} }
- (BOOL)isEngineRunning { - (BOOL)isEngineRunning {
@@ -219,45 +209,37 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
return; return;
} }
// Apply heavy smoothing to the angle input to eliminate sensor jitter // Stage 1: Smooth the raw angle input to eliminate sensor jitter
double angleSmoothingFactor = 0.05; // Very heavy smoothing (5% new, 95% old) self.smoothedLidAngle = (kAngleSmoothingFactor * lidAngle) +
self.smoothedLidAngle = (angleSmoothingFactor * lidAngle) + ((1.0 - kAngleSmoothingFactor) * self.smoothedLidAngle);
((1.0 - angleSmoothingFactor) * self.smoothedLidAngle);
// Calculate angular velocity using smoothed angle // Stage 2: Calculate velocity from smoothed angle data
double deltaAngle = self.smoothedLidAngle - self.lastLidAngle; double deltaAngle = self.smoothedLidAngle - self.lastLidAngle;
// Calculate instantaneous velocity
double instantVelocity; double instantVelocity;
// Much higher threshold to eliminate jitter completely // Apply movement threshold to eliminate remaining noise
if (fabs(deltaAngle) < 0.5) { // Ignore changes smaller than 0.5 degrees if (fabs(deltaAngle) < kMovementThreshold) {
deltaAngle = 0.0;
instantVelocity = 0.0; instantVelocity = 0.0;
} else { } else {
instantVelocity = deltaAngle / deltaTime; instantVelocity = fabs(deltaAngle / deltaTime);
// Update last angle only when we have significant movement
self.lastLidAngle = self.smoothedLidAngle; self.lastLidAngle = self.smoothedLidAngle;
} }
// Use absolute value early to avoid sign issues // Stage 3: Apply velocity smoothing and decay
instantVelocity = fabs(instantVelocity);
// Apply velocity smoothing only when there's actual movement
if (instantVelocity > 0.0) { if (instantVelocity > 0.0) {
double velocitySmoothingFactor = 0.3; // Moderate smoothing for real movement // Real movement detected - apply moderate smoothing
self.smoothedVelocity = (velocitySmoothingFactor * instantVelocity) + self.smoothedVelocity = (kVelocitySmoothingFactor * instantVelocity) +
((1.0 - velocitySmoothingFactor) * self.smoothedVelocity); ((1.0 - kVelocitySmoothingFactor) * self.smoothedVelocity);
self.lastMovementTime = currentTime; self.lastMovementTime = currentTime;
} else { } else {
// No movement detected - aggressively decay to zero // No movement detected - apply fast decay
self.smoothedVelocity *= 0.5; // Very fast decay when no movement self.smoothedVelocity *= kVelocityDecayFactor;
} }
// Additional decay if we haven't seen real movement for a while // Additional decay if no movement for extended period
double timeSinceMovement = currentTime - self.lastMovementTime; double timeSinceMovement = currentTime - self.lastMovementTime;
if (timeSinceMovement > 0.05) { // Only 50ms without movement if (timeSinceMovement > (kMovementTimeoutMs / 1000.0)) {
self.smoothedVelocity *= 0.8; // Additional decay self.smoothedVelocity *= kAdditionalDecayFactor;
} }
// Update state for next iteration // Update state for next iteration
@@ -273,24 +255,23 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
} }
- (void)updateAudioParametersWithVelocity:(double)velocity { - (void)updateAudioParametersWithVelocity:(double)velocity {
// Velocity is already absolute at this point double speed = velocity; // Velocity is already absolute
double speed = velocity;
// Calculate target gain - CORRECTED LOGIC: slow = loud, fast = quiet // Calculate target gain: slow movement = loud creak, fast movement = quiet/silent
double gain; double gain;
if (speed < kDeadzone) { if (speed < kDeadzone) {
gain = 0.0; // truly still no sound gain = 0.0; // Below deadzone: no sound
} else { } else {
// inverted smoothstep: slow => loud, fast => quiet // Use inverted smoothstep curve for natural volume response
double e0 = fmax(0.0, kVelocityFull - 0.5); double e0 = fmax(0.0, kVelocityFull - 0.5);
double e1 = kVelocityQuiet + 0.5; double e1 = kVelocityQuiet + 0.5;
double t = fmin(1.0, fmax(0.0, (speed - e0) / (e1 - e0))); double t = fmin(1.0, fmax(0.0, (speed - e0) / (e1 - e0)));
double s = t * t * (3.0 - 2.0 * t); // smoothstep double s = t * t * (3.0 - 2.0 * t); // smoothstep function
gain = 1.0 - s; // invert: slow = loud, fast = quiet gain = 1.0 - s; // invert: slow = loud, fast = quiet
gain = fmax(0.0, fmin(1.0, gain)); // Clamp to [0,1] gain = fmax(0.0, fmin(1.0, gain));
} }
// Calculate target rate (pitch/tempo) - wider range now // Calculate target pitch/tempo rate based on movement speed
double normalizedVelocity = fmax(0.0, fmin(1.0, speed / kVelocityQuiet)); double normalizedVelocity = fmax(0.0, fmin(1.0, speed / kVelocityQuiet));
double rate = kMinRate + normalizedVelocity * (kMaxRate - kMinRate); double rate = kMinRate + normalizedVelocity * (kMaxRate - kMinRate);
rate = fmax(kMinRate, fmin(kMaxRate, rate)); rate = fmax(kMinRate, fmin(kMaxRate, rate));
@@ -299,7 +280,7 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
self.targetGain = gain; self.targetGain = gain;
self.targetRate = rate; self.targetRate = rate;
// Apply smooth parameter changes // Apply smooth parameter transitions
[self rampToTargetParameters]; [self rampToTargetParameters];
} }
@@ -321,23 +302,15 @@ static const double kAdditionalDecayFactor = 0.8; // Additional decay after
double deltaTime = currentTime - lastRampTime; double deltaTime = currentTime - lastRampTime;
lastRampTime = currentTime; lastRampTime = currentTime;
// Ramp current values toward targets (much faster ramping for immediate response) // Ramp current values toward targets for smooth transitions
self.currentGain = [self rampValue:self.currentGain toward:self.targetGain withDeltaTime:deltaTime timeConstantMs:50.0]; self.currentGain = [self rampValue:self.currentGain toward:self.targetGain withDeltaTime:deltaTime timeConstantMs:kGainRampTimeMs];
self.currentRate = [self rampValue:self.currentRate toward:self.targetRate withDeltaTime:deltaTime timeConstantMs:80.0]; self.currentRate = [self rampValue:self.currentRate toward:self.targetRate withDeltaTime:deltaTime timeConstantMs:kRateRampTimeMs];
// Apply ramped values to audio nodes (make loop louder with 2x multiplier) // Apply ramped values to audio nodes (2x multiplier for audible volume)
self.creakPlayerNode.volume = (float)(self.currentGain * 2.0); self.creakPlayerNode.volume = (float)(self.currentGain * 2.0);
self.varispeadUnit.rate = (float)self.currentRate; self.varispeadUnit.rate = (float)self.currentRate;
// Debug logging
if (self.targetGain > 0.01) {
NSLog(@"[CreakAudioEngine] Target: %.3f/%.3f, Current: %.3f/%.3f",
self.targetGain, self.targetRate, self.currentGain, self.currentRate);
}
} }
// Grain system removed - loop only
#pragma mark - Property Accessors #pragma mark - Property Accessors
- (double)currentVelocity { - (double)currentVelocity {