diff --git a/rvsttd/src/main.rs b/rvsttd/src/main.rs index f2feee9..b50f661 100644 --- a/rvsttd/src/main.rs +++ b/rvsttd/src/main.rs @@ -113,17 +113,7 @@ impl DebugRecorder { self.audio.extend_from_slice(samples); } - fn save(mut self) { - // Apply 5ms fade-out to the end to avoid click at the trailing edge - let fade_samples = (SAMPLE_RATE as usize * 5) / 1000; // 5ms - if self.audio.len() > fade_samples { - let start = self.audio.len() - fade_samples; - for i in 0..fade_samples { - let t = 1.0 - (i as f32 / fade_samples as f32); - self.audio[start + i] *= t; - } - } - + fn save(self) { // Write log let log_path = self.dir.join("session.log"); match std::fs::File::create(&log_path) { @@ -335,26 +325,53 @@ 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; 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); } - unsafe { - moonshine_transcribe_add_audio_to_stream( - handle, stream_handle, - chunk.as_ptr(), chunk.len() as u64, - SAMPLE_RATE, 0, - ); + // 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); } 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; + } + } + + unsafe { + moonshine_transcribe_add_audio_to_stream( + handle, stream_handle, + chunk.as_ptr(), chunk.len() as u64, + SAMPLE_RATE, 0, + ); + } + } + // If aborted (new session took over), skip final flush entirely if aborted.load(Ordering::SeqCst) { unsafe { moonshine_stop_stream(handle, stream_handle) };