audio plays, but pausing and playing again fails

main
aprzn 2 years ago
parent 7c6fac00ab
commit d96b9b6cbd

@ -86,10 +86,10 @@ struct WizardData {
struct Song { struct Song {
name: String, name: String,
id: i64, id: i64,
buffer: rodio::buffer::SamplesBuffer<i16>, source: rodio::source::Buffered<rodio::Decoder<File>>,
length: time::Duration,
stream: rodio::OutputStream, stream: rodio::OutputStream,
sink: rodio::Sink, sink: rodio::Sink,
playing: bool,
} }
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -219,23 +219,34 @@ impl Song {
(Err(err), Err(_)) => return Err(err.into()), (Err(err), Err(_)) => return Err(err.into()),
}; };
let decoder = rodio::Decoder::new_mp3(file)?; let source = rodio::Decoder::new_mp3(file)?.buffered();
let channels = decoder.channels();
let sample_rate = decoder.sample_rate();
let samples: Vec<i16> = decoder.collect();
let length = time::Duration::from_secs(samples.len() as u64 / channels as u64 / sample_rate as u64);
let buffer = rodio::buffer::SamplesBuffer::new(channels, sample_rate, samples);
let (stream, stream_handle) = rodio::OutputStream::try_default()?; let (stream, stream_handle) = rodio::OutputStream::try_default()?;
let sink = rodio::Sink::try_new(&stream_handle)?; let sink = rodio::Sink::try_new(&stream_handle)?;
Ok(Self { name, id, buffer, length, stream, sink }) Ok(Self { name, id, source, stream, sink, playing: false })
} else { } else {
Err(SongError::NotNewgrounds) Err(SongError::NotNewgrounds)
} }
} }
pub fn length(&self) -> time::Duration {
self.source.total_duration().expect("the source should have a well-defined duration")
}
pub fn play_from(&mut self, position: time::Duration) {
self.playing = true;
self.sink.append(self.source.clone().skip_duration(position))
}
pub fn stop(&mut self) {
self.playing = false;
self.sink.stop();
}
pub fn playing(&self) -> bool {
self.playing
}
} }
impl Editor { impl Editor {
@ -270,14 +281,21 @@ impl Editor {
/// points in width of entire song /// points in width of entire song
fn song_width(&self, song: &Song) -> f64 { fn song_width(&self, song: &Song) -> f64 {
song.length.as_secs_f64() * self.state.pts_per_second song.length().as_secs_f64() * self.state.pts_per_second
} }
fn play_pause(&self, song: &Song) { fn play_pause(&self, song: &mut Song) {
todo!("toggle song playback") if song.playing() {
println!("stopping");
song.stop();
} else {
println!("starting");
song.play_from(time::Duration::default());
}
// todo!("toggle song playback")
} }
fn handle_keyboard_input(&mut self, ctx: &egui::Context, song: &Song) { fn handle_keyboard_input(&mut self, ctx: &egui::Context, song: &mut Song) {
use egui::Key; use egui::Key;
use egui::Event; use egui::Event;
ctx.input().events ctx.input().events

@ -1,6 +1,7 @@
use std::time::Duration; use std::time::Duration;
use ordered_float::OrderedFloat as Float; use ordered_float::OrderedFloat as Float;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use rodio::{Source, Sample};
pub type BeatPosition = Float<f32>; pub type BeatPosition = Float<f32>;
@ -172,6 +173,43 @@ where
} }
} }
// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
// struct SamplesSlice<'a, T: Sample, const N: usize> {
// samples: &'a [T],
// frame_changes: [usize; N],
// channel_counts: &'a [u16; N],
// sample_rates: &'a [u32; N],
// position: usize,
// }
// impl<T: Sample, const N: usize> Iterator for SamplesSlice<'_, T, N> {
// type Item = T;
// fn next(&mut self) -> Option<Self::Item> {
// self.position += 1;
// self.samples.get(self.position - 1).map(|x| *x)
// }
// }
// impl<T: Sample, const N: usize> Source for SamplesSlice<'_, T, N> {
// fn current_frame_len(&self) -> Option<usize> {
// self.frame_changes.iter().find(|&f| f > &self.position).map(|f| f - self.position)
// }
// fn channels(&self) -> u16 {
// *self.frame_changes.iter().zip(self.channel_counts).rfind(|(&f, _)| f <= self.position).expect("there will always be a frame change before the current position").1
// }
// fn sample_rate(&self) -> u32 {
// *self.frame_changes.iter().zip(self.sample_rates).rfind(|(&f, _)| f <= self.position).expect("there will always be a frame change before the current position").1
// }
// fn total_duration(&self) -> Option<Duration> {
// todo!()
// }
// }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

Loading…
Cancel
Save