33use crate :: common:: { ChannelCount , SampleRate } ;
44use crate :: source:: { SeekError , Source , UniformSourceIterator } ;
55use crate :: Sample ;
6- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
7- use std:: sync:: { Arc , Mutex } ;
6+ use std:: sync:: Arc ;
87use std:: time:: Duration ;
98
9+ #[ cfg( feature = "crossbeam-channel" ) ]
10+ use crossbeam_channel:: { unbounded as channel, Receiver , Sender } ;
11+ #[ cfg( not( feature = "crossbeam-channel" ) ) ]
12+ use std:: sync:: mpsc:: { channel, Receiver , Sender } ;
13+
1014/// Builds a new mixer.
1115///
1216/// You can choose the characteristics of the output thanks to this constructor. All the sounds
@@ -19,9 +23,10 @@ use std::time::Duration;
1923/// As a result, input sources added to the mixer later might not be forwarded to the sink.
2024/// Add `Zero` source to prevent detaching the mixer from sink.
2125pub fn mixer ( channels : ChannelCount , sample_rate : SampleRate ) -> ( Mixer , MixerSource ) {
26+ let ( tx, rx) = channel ( ) ;
27+
2228 let input = Mixer ( Arc :: new ( Inner {
23- has_pending : AtomicBool :: new ( false ) ,
24- pending_sources : Mutex :: new ( Vec :: new ( ) ) ,
29+ pending_tx : tx,
2530 channels,
2631 sample_rate,
2732 } ) ) ;
@@ -31,7 +36,7 @@ pub fn mixer(channels: ChannelCount, sample_rate: SampleRate) -> (Mixer, MixerSo
3136 input : input. clone ( ) ,
3237 sample_count : 0 ,
3338 still_pending : vec ! [ ] ,
34- still_current : vec ! [ ] ,
39+ pending_rx : rx ,
3540 } ;
3641
3742 ( input, output)
@@ -42,8 +47,7 @@ pub fn mixer(channels: ChannelCount, sample_rate: SampleRate) -> (Mixer, MixerSo
4247pub struct Mixer ( Arc < Inner > ) ;
4348
4449struct Inner {
45- has_pending : AtomicBool ,
46- pending_sources : Mutex < Vec < Box < dyn Source + Send > > > ,
50+ pending_tx : Sender < Box < dyn Source + Send > > ,
4751 channels : ChannelCount ,
4852 sample_rate : SampleRate ,
4953}
@@ -57,12 +61,8 @@ impl Mixer {
5761 {
5862 let uniform_source =
5963 UniformSourceIterator :: new ( source, self . 0 . channels , self . 0 . sample_rate ) ;
60- self . 0
61- . pending_sources
62- . lock ( )
63- . unwrap ( )
64- . push ( Box :: new ( uniform_source) as Box < _ > ) ;
65- self . 0 . has_pending . store ( true , Ordering :: SeqCst ) ; // TODO: can we relax this ordering?
64+ // Ignore send errors (channel dropped means MixerSource was dropped)
65+ let _ = self . 0 . pending_tx . send ( Box :: new ( uniform_source) ) ;
6666 }
6767}
6868
@@ -80,8 +80,8 @@ pub struct MixerSource {
8080 // A temporary vec used in start_pending_sources.
8181 still_pending : Vec < Box < dyn Source + Send > > ,
8282
83- // A temporary vec used in sum_current_sources .
84- still_current : Vec < Box < dyn Source + Send > > ,
83+ // Receiver for pending sources from the channel .
84+ pending_rx : Receiver < Box < dyn Source + Send > > ,
8585}
8686
8787impl Source for MixerSource {
@@ -118,9 +118,7 @@ impl Iterator for MixerSource {
118118
119119 #[ inline]
120120 fn next ( & mut self ) -> Option < Self :: Item > {
121- if self . input . 0 . has_pending . load ( Ordering :: SeqCst ) {
122- self . start_pending_sources ( ) ;
123- }
121+ self . start_pending_sources ( ) ;
124122
125123 self . sample_count += 1 ;
126124
@@ -145,9 +143,7 @@ impl MixerSource {
145143 // in-step with the modulo of the samples produced so far. Otherwise, the
146144 // sound will play on the wrong channels, e.g. left / right will be reversed.
147145 fn start_pending_sources ( & mut self ) {
148- let mut pending = self . input . 0 . pending_sources . lock ( ) . unwrap ( ) ; // TODO: relax ordering?
149-
150- for source in pending. drain ( ..) {
146+ while let Ok ( source) = self . pending_rx . try_recv ( ) {
151147 let in_step = self
152148 . sample_count
153149 . is_multiple_of ( source. channels ( ) . get ( ) as usize ) ;
@@ -158,24 +154,19 @@ impl MixerSource {
158154 self . still_pending . push ( source) ;
159155 }
160156 }
161- std:: mem:: swap ( & mut self . still_pending , & mut pending) ;
162-
163- let has_pending = !pending. is_empty ( ) ;
164- self . input
165- . 0
166- . has_pending
167- . store ( has_pending, Ordering :: SeqCst ) ; // TODO: relax ordering?
168157 }
169158
170159 fn sum_current_sources ( & mut self ) -> Sample {
171160 let mut sum = 0.0 ;
172- for mut source in self . current_sources . drain ( ..) {
173- if let Some ( value) = source. next ( ) {
174- sum += value;
175- self . still_current . push ( source) ;
161+ self . current_sources . retain_mut ( |source| {
162+ match source. next ( ) {
163+ Some ( value) => {
164+ sum += value;
165+ true // Keep this source
166+ }
167+ None => false , // Remove exhausted source
176168 }
177- }
178- std:: mem:: swap ( & mut self . still_current , & mut self . current_sources ) ;
169+ } ) ;
179170
180171 sum
181172 }
0 commit comments