diff --git a/rvsttd/src/main.rs b/rvsttd/src/main.rs index b50f661..f81fc4f 100644 --- a/rvsttd/src/main.rs +++ b/rvsttd/src/main.rs @@ -113,6 +113,14 @@ impl DebugRecorder { self.audio.extend_from_slice(samples); } + fn audio_len(&self) -> usize { + self.audio.len() + } + + fn truncate_audio(&mut self, len: usize) { + self.audio.truncate(len); + } + fn save(self) { // Write log let log_path = self.dir.join("session.log"); @@ -325,48 +333,44 @@ fn transcriber_loop( // Fixed 100ms window — cpal delivers every ~50ms (800 samples @ 16kHz), // so this captures 1-2 more callbacks worth of trailing audio. let drain_deadline = std::time::Instant::now() + Duration::from_millis(100); - let mut last_chunk: Option> = None; + let mut drained: Vec = Vec::new(); while std::time::Instant::now() < drain_deadline { match rx.recv_timeout(drain_deadline - std::time::Instant::now()) { Ok(chunk) => { - // Record raw audio for debug WAV if let Some(ref mut r) = recorder { r.add_audio(&chunk); } - - // Feed previous chunk to Moonshine, hold the latest for fade - if let Some(prev) = last_chunk.take() { - unsafe { - moonshine_transcribe_add_audio_to_stream( - handle, stream_handle, - prev.as_ptr(), prev.len() as u64, - SAMPLE_RATE, 0, - ); - } - } - last_chunk = Some(chunk); + drained.extend_from_slice(&chunk); } Err(mpsc::RecvTimeoutError::Timeout) => break, Err(mpsc::RecvTimeoutError::Disconnected) => break, } } - // Apply 5ms fade-out to the last chunk before feeding to Moonshine. - // The recorder already captured the unmodified audio for the debug WAV. - if let Some(mut chunk) = last_chunk.take() { - let fade_samples = (SAMPLE_RATE as usize * 5) / 1000; - if chunk.len() > fade_samples { - let start = chunk.len() - fade_samples; - for i in 0..fade_samples { - let t = 1.0 - (i as f32 / fade_samples as f32); - chunk[start + i] *= t; - } + // Apply 5ms fade-out to the trailing edge of the drained audio. + // Both the debug WAV and Moonshine receive the same faded audio. + let fade_samples = (SAMPLE_RATE as usize * 5) / 1000; + if drained.len() > fade_samples { + let start = drained.len() - fade_samples; + for i in 0..fade_samples { + let t = 1.0 - (i as f32 / fade_samples as f32); + drained[start + i] *= t; } + } + // Update recorder with the faded audio (replaces the raw versions added above) + if let Some(ref mut r) = recorder { + // Remove the raw drained samples and re-add the faded ones + let raw_drained_len = r.audio_len(); + r.truncate_audio(raw_drained_len.saturating_sub(drained.len())); + r.add_audio(&drained); + } + + if !drained.is_empty() { unsafe { moonshine_transcribe_add_audio_to_stream( handle, stream_handle, - chunk.as_ptr(), chunk.len() as u64, + drained.as_ptr(), drained.len() as u64, SAMPLE_RATE, 0, ); }