@@ -4,7 +4,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
44use std:: sync:: { Arc , Mutex } ;
55use std:: time:: Duration ;
66
7- use crate :: math:: nz;
87use crate :: source:: { Empty , SeekError , Source , Zero } ;
98use crate :: Sample ;
109
@@ -121,9 +120,6 @@ pub struct SourcesQueueOutput {
121120 padding_samples_remaining : usize ,
122121}
123122
124- const SILENCE_SAMPLE_RATE : SampleRate = nz ! ( 44100 ) ;
125- const SILENCE_CHANNELS : ChannelCount = nz ! ( 1 ) ;
126-
127123/// Returns a threshold span length that ensures frame alignment.
128124///
129125/// Spans must end on frame boundaries (multiples of channel count) to prevent
@@ -173,27 +169,38 @@ impl Source for SourcesQueueOutput {
173169
174170 #[ inline]
175171 fn channels ( & self ) -> ChannelCount {
176- // When current source is exhausted, peek at the next source's metadata
177172 if !self . current . is_exhausted ( ) {
173+ // Current source is active (producing samples)
174+ // - Initially: never (Empty is exhausted immediately)
175+ // - After append: the appended source while playing
176+ // - With keep_alive: Zero (silence) while playing
178177 self . current . channels ( )
179178 } else if let Some ( ( next, _) ) = self . input . next_sounds . lock ( ) . unwrap ( ) . first ( ) {
179+ // Current source exhausted, peek at next queued source
180+ // This is critical: UniformSourceIterator queries metadata during append,
181+ // before any samples are pulled. We must report the next source's metadata.
180182 next. channels ( )
181183 } else {
182- // Queue is empty - return silence metadata
183- SILENCE_CHANNELS
184+ // Queue is empty, no sources queued
185+ // - Initially: Empty
186+ // - With keep_alive: exhausted Zero between silence chunks (matches Empty)
187+ // - Without keep_alive: Empty (will end on next())
188+ self . current . channels ( )
184189 }
185190 }
186191
187192 #[ inline]
188193 fn sample_rate ( & self ) -> SampleRate {
189- // When current source is exhausted, peek at the next source's metadata
190194 if !self . current . is_exhausted ( ) {
195+ // Current source is active (producing samples)
191196 self . current . sample_rate ( )
192197 } else if let Some ( ( next, _) ) = self . input . next_sounds . lock ( ) . unwrap ( ) . first ( ) {
198+ // Current source exhausted, peek at next queued source
199+ // This prevents wrong resampling setup in UniformSourceIterator
193200 next. sample_rate ( )
194201 } else {
195- // Queue is empty - return silence metadata
196- SILENCE_SAMPLE_RATE
202+ // Queue is empty, no sources queued
203+ self . current . sample_rate ( )
197204 }
198205 }
199206
@@ -276,10 +283,11 @@ impl SourcesQueueOutput {
276283 let mut next = self . input . next_sounds . lock ( ) . unwrap ( ) ;
277284
278285 if next. is_empty ( ) {
286+ let channels = self . current . channels ( ) ;
279287 let silence = Box :: new ( Zero :: new_samples (
280- SILENCE_CHANNELS ,
281- SILENCE_SAMPLE_RATE ,
282- threshold ( SILENCE_CHANNELS ) ,
288+ channels ,
289+ self . current . sample_rate ( ) ,
290+ threshold ( channels ) ,
283291 ) ) as Box < _ > ;
284292 if self . input . keep_alive_if_empty . load ( Ordering :: Acquire ) {
285293 // Play a short silence in order to avoid spinlocking.
@@ -381,6 +389,40 @@ mod tests {
381389 assert_eq ! ( rx. next( ) , Some ( -10.0 ) ) ;
382390 }
383391
392+ #[ test]
393+ fn append_updates_metadata ( ) {
394+ for keep_alive in [ false , true ] {
395+ let ( tx, rx) = queue:: queue ( keep_alive) ;
396+ assert_eq ! (
397+ rx. channels( ) ,
398+ nz!( 1 ) ,
399+ "Initial channels should be 1 (keep_alive={keep_alive})"
400+ ) ;
401+ assert_eq ! (
402+ rx. sample_rate( ) ,
403+ nz!( 48000 ) ,
404+ "Initial sample rate should be 48000 (keep_alive={keep_alive})"
405+ ) ;
406+
407+ tx. append ( SamplesBuffer :: new (
408+ nz ! ( 2 ) ,
409+ nz ! ( 44100 ) ,
410+ vec ! [ 0.1 , 0.2 , 0.3 , 0.4 ] ,
411+ ) ) ;
412+
413+ assert_eq ! (
414+ rx. channels( ) ,
415+ nz!( 2 ) ,
416+ "Channels should update to 2 (keep_alive={keep_alive})"
417+ ) ;
418+ assert_eq ! (
419+ rx. sample_rate( ) ,
420+ nz!( 44100 ) ,
421+ "Sample rate should update to 44100 (keep_alive={keep_alive})"
422+ ) ;
423+ }
424+ }
425+
384426 #[ test]
385427 fn span_ending_mid_frame ( ) {
386428 let mut test_source1 = TestSource :: new ( & [ 0.1 , 0.2 , 0.1 , 0.2 , 0.1 ] )
0 commit comments