From d83a7ecb4dbbcbf1bb7df7724414a6f3e7eef13f Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 4 Sep 2020 14:00:09 +0200 Subject: [PATCH] audio timescale support --- src/sound/mod.rs | 19 +++++++++++++++++-- src/sound/playback.rs | 5 +++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/sound/mod.rs b/src/sound/mod.rs index 98e01d7..b835d4e 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -6,11 +6,12 @@ use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use crate::engine_constants::EngineConstants; use crate::ggez::{Context, filesystem, GameResult}; -use crate::ggez::GameError::AudioError; +use crate::ggez::GameError::{AudioError, InvalidValue}; use crate::sound::organya::Song; use crate::sound::playback::{PlaybackEngine, SavedPlaybackState}; use crate::sound::wave_bank::SoundBank; use crate::str; +use cpal::Sample; pub mod pixtone; mod wave_bank; @@ -126,11 +127,21 @@ impl SoundManager { Ok(()) } + + pub fn set_speed(&mut self, speed: f32) -> GameResult { + if speed <= 0.0 { + return Err(InvalidValue(str!("Speed must be bigger than 0.0!"))); + } + self.tx.send(PlaybackMessage::SetSpeed(speed))?; + + Ok(()) + } } enum PlaybackMessage { Stop, PlaySong(Box), + SetSpeed(f32), SaveState, RestoreState, } @@ -177,6 +188,10 @@ fn run(rx: Receiver, bank: SoundBank, Ok(PlaybackMessage::Stop) => { state = PlaybackState::Stopped; } + Ok(PlaybackMessage::SetSpeed(speed)) => { + assert!(speed > 0.0); + engine.set_sample_rate((sample_rate / speed) as usize); + } Ok(PlaybackMessage::SaveState) => { saved_state = Some(engine.get_state()); } @@ -212,7 +227,7 @@ fn run(rx: Receiver, bank: SoundBank, } }; - let value: T = cpal::Sample::from::(&sample); + let value: T = Sample::from::(&sample); for sample in frame.iter_mut() { *sample = value; } diff --git a/src/sound/playback.rs b/src/sound/playback.rs index 72246a3..452801c 100644 --- a/src/sound/playback.rs +++ b/src/sound/playback.rs @@ -103,8 +103,13 @@ impl PlaybackEngine { } pub fn set_sample_rate(&mut self, sample_rate: usize) { + self.frames_this_tick = (self.frames_this_tick as f32 * (self.output_format.sample_rate as f32 / sample_rate as f32)) as usize; self.output_format.sample_rate = sample_rate as u32; self.frames_per_tick = (sample_rate / 1000) * self.song.time.wait as usize; + + if self.frames_this_tick >= self.frames_per_tick { + self.frames_this_tick = 0; + } } pub fn get_state(&self) -> SavedPlaybackState {