From fdf66980901a9264f8d31411e0583450e732fc65 Mon Sep 17 00:00:00 2001 From: Martin Billinger Date: Sun, 29 Jul 2018 18:49:25 +0200 Subject: [PATCH] Simplest source composition is best --- src/audio.rs | 112 +++++++++------------------------------------------ 1 file changed, 20 insertions(+), 92 deletions(-) diff --git a/src/audio.rs b/src/audio.rs index 6f65a716e..a3f24e946 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -165,29 +165,20 @@ impl Source { // See https://github.com/ggez/ggez/issues/98 for discussion use rodio::Source; let cursor = self.data.clone(); - let decoder = rodio::Decoder::new(cursor)?; - - // Using boxed sources is the solution with the nicest code I could come up with (the - // alternatives are nested `if`s or a *huge* ugly `match`). The drawback is that we end up - // with multiple nested boxed sources, each incurring dynamic dispatch. This might have - // a negative impact on playback performance. If performance becomes an issue it may be - // worth to revert to a static solution like, ugh!, nested `if`s (maybe time for macros?). - let mut sound = BoxedSource::new(decoder); if self.repeat { - sound = BoxedSource::new(sound.repeat_infinite()); - } - - if (self.pitch - 1.0).abs() < 1e-6 { - sound = BoxedSource::new(sound.speed(self.pitch)); - } - - if self.fade_in > time::Duration::from_secs(0) { - sound = BoxedSource::new(sound.fade_in(self.fade_in)); + let sound = rodio::Decoder::new(cursor)? + .repeat_infinite() + .speed(self.pitch) + .fade_in(self.fade_in); + self.sink.append(sound); + } else { + let sound = rodio::Decoder::new(cursor)? + .speed(self.pitch) + .fade_in(self.fade_in); + self.sink.append(sound); } - self.sink.append(sound); - Ok(()) } @@ -345,29 +336,20 @@ impl SpatialSource { pub fn play_later(&self) -> GameResult { use rodio::Source; let cursor = self.data.clone(); - let decoder = rodio::Decoder::new(cursor)?; - - // Using boxed sources is the solution with the nicest code I could come up with (the - // alternatives are nested `if`s or a *huge* ugly `match`). The drawback is that we end up - // with multiple nested boxed sources, each incurring dynamic dispatch. This might have - // a negative impact on playback performance. If performance becomes an issue it may be - // worth to revert to a static solution like, ugh!, nested `if`s (maybe time for macros?). - let mut sound = BoxedSource::new(decoder); if self.repeat { - sound = BoxedSource::new(sound.repeat_infinite()); + let sound = rodio::Decoder::new(cursor)? + .repeat_infinite() + .speed(self.pitch) + .fade_in(self.fade_in); + self.sink.append(sound); + } else { + let sound = rodio::Decoder::new(cursor)? + .speed(self.pitch) + .fade_in(self.fade_in); + self.sink.append(sound); } - if (self.pitch - 1.0).abs() < 1e-6 { - sound = BoxedSource::new(sound.speed(self.pitch)); - } - - if self.fade_in > time::Duration::from_secs(0) { - sound = BoxedSource::new(sound.fade_in(self.fade_in)); - } - - self.sink.append(sound); - Ok(()) } @@ -492,57 +474,3 @@ impl fmt::Debug for SpatialSource { write!(f, "", self) } } - -/// Boxed wrapper over `rodio::Source` trait objects. -/// -/// Used for dynamically composing sources. -struct BoxedSource { - input: Box + Send>, -} - -impl BoxedSource -where - T: rodio::Sample, -{ - fn new(source: S) -> Self - where - S: rodio::Source + Send, - { - BoxedSource { - input: Box::new(source), - } - } -} - -impl rodio::Source for BoxedSource -where - T: rodio::Sample, -{ - #[inline(always)] - fn current_frame_len(&self) -> Option { - self.input.current_frame_len() - } - - #[inline(always)] - fn channels(&self) -> u16 { - self.input.channels() - } - - #[inline(always)] - fn sample_rate(&self) -> u32 { - self.input.sample_rate() - } - - #[inline(always)] - fn total_duration(&self) -> Option { - self.input.total_duration() - } -} - -impl Iterator for BoxedSource { - type Item = T; - - fn next(&mut self) -> Option { - self.input.next() - } -}