diff --git a/Cargo.toml b/Cargo.toml index 599cb059..81b39df8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,11 +10,11 @@ exclude = ["assets/**", "tests/**"] edition = "2021" [dependencies] -cpal = "0.15.3" +cpal = { version = "0.15.3", optional = true } claxon = { version = "0.4.2", optional = true } hound = { version = "3.3.1", optional = true } lewton = { version = "0.10", optional = true } -minimp3_fixed = { version = "0.5.4", optional = true} +minimp3_fixed = { version = "0.5.4", optional = true } symphonia = { version = "0.5.4", optional = true, default-features = false } crossbeam-channel = { version = "0.5.8", optional = true } @@ -25,7 +25,7 @@ atomic_float = { version = "1.1.0", optional = true } num-rational = "0.4.2" [features] -default = ["flac", "vorbis", "wav", "mp3"] +default = ["flac", "vorbis", "wav", "mp3", "cpal"] tracing = ["dep:tracing"] experimental = ["dep:atomic_float"] diff --git a/benches/shared.rs b/benches/shared.rs index 77e426d7..6122f64f 100644 --- a/benches/shared.rs +++ b/benches/shared.rs @@ -30,11 +30,11 @@ impl<T: rodio::Sample> Source for TestSource<T> { None // forever } - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } diff --git a/examples/custom_config.rs b/examples/custom_config.rs index 40b6ca47..4e1ff76a 100644 --- a/examples/custom_config.rs +++ b/examples/custom_config.rs @@ -1,5 +1,5 @@ use cpal::traits::HostTrait; -use cpal::{BufferSize, SampleFormat, SampleRate}; +use cpal::{BufferSize, SampleFormat}; use rodio::source::SineWave; use rodio::Source; use std::error::Error; @@ -15,7 +15,7 @@ fn main() -> Result<(), Box<dyn Error>> { // No need to set all parameters explicitly here, // the defaults were set from the device's description. .with_buffer_size(BufferSize::Fixed(256)) - .with_sample_rate(SampleRate(48_000)) + .with_sample_rate(48_000) .with_sample_format(SampleFormat::F32) // Note that the function below still tries alternative configs if the specified one fails. // If you need to only use the exact specified configuration, diff --git a/examples/noise_generator.rs b/examples/noise_generator.rs index 577f9d01..23a86b90 100644 --- a/examples/noise_generator.rs +++ b/examples/noise_generator.rs @@ -22,11 +22,9 @@ fn main() -> Result<(), Box<dyn Error>> { thread::sleep(interval_duration); - stream_handle.mixer().add( - pink(cpal::SampleRate(48000)) - .amplify(0.1) - .take_duration(noise_duration), - ); + stream_handle + .mixer() + .add(pink(48000).amplify(0.1).take_duration(noise_duration)); println!("Playing pink noise"); thread::sleep(interval_duration); diff --git a/examples/signal_generator.rs b/examples/signal_generator.rs index e746692d..1ae4048e 100644 --- a/examples/signal_generator.rs +++ b/examples/signal_generator.rs @@ -11,7 +11,7 @@ fn main() -> Result<(), Box<dyn Error>> { let test_signal_duration = Duration::from_millis(1000); let interval_duration = Duration::from_millis(1500); - let sample_rate = cpal::SampleRate(48000); + let sample_rate = 48000; println!("Playing 1000 Hz tone"); stream_handle.mixer().add( diff --git a/src/buffer.rs b/src/buffer.rs index 1522faf9..ebaf114b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -10,18 +10,18 @@ //! ``` //! -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::source::SeekError; use crate::{Sample, Source}; +use std::time::Duration; /// A buffer of samples treated as a source. #[derive(Debug, Clone)] pub struct SamplesBuffer<S> { data: Vec<S>, pos: usize, - channels: u16, - sample_rate: u32, + channels: ChannelCount, + sample_rate: SampleRate, duration: Duration, } @@ -38,7 +38,7 @@ where /// - Panics if the length of the buffer is larger than approximately 16 billion elements. /// This is because the calculation of the duration would overflow. /// - pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S> + pub fn new<D>(channels: ChannelCount, sample_rate: SampleRate, data: D) -> SamplesBuffer<S> where D: Into<Vec<S>>, { @@ -74,12 +74,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } @@ -174,12 +174,13 @@ mod tests { #[cfg(test)] mod try_seek { use super::*; + use crate::common::{ChannelCount, SampleRate}; use std::time::Duration; #[test] fn channel_order_stays_correct() { - const SAMPLE_RATE: u32 = 100; - const CHANNELS: u16 = 2; + const SAMPLE_RATE: SampleRate = 100; + const CHANNELS: ChannelCount = 2; let mut buf = SamplesBuffer::new( CHANNELS, SAMPLE_RATE, diff --git a/src/conversions/channels.rs b/src/conversions/channels.rs index 45bf767f..ac8980b9 100644 --- a/src/conversions/channels.rs +++ b/src/conversions/channels.rs @@ -1,3 +1,4 @@ +use crate::common::ChannelCount; use cpal::Sample; /// Iterator that converts from a certain channel count to another. @@ -7,10 +8,10 @@ where I: Iterator, { input: I, - from: cpal::ChannelCount, - to: cpal::ChannelCount, + from: ChannelCount, + to: ChannelCount, sample_repeat: Option<I::Item>, - next_output_sample_pos: cpal::ChannelCount, + next_output_sample_pos: ChannelCount, } impl<I> ChannelCountConverter<I> @@ -24,11 +25,7 @@ where /// Panics if `from` or `to` are equal to 0. /// #[inline] - pub fn new( - input: I, - from: cpal::ChannelCount, - to: cpal::ChannelCount, - ) -> ChannelCountConverter<I> { + pub fn new(input: I, from: ChannelCount, to: ChannelCount) -> ChannelCountConverter<I> { assert!(from >= 1); assert!(to >= 1); @@ -118,6 +115,7 @@ where #[cfg(test)] mod test { use super::ChannelCountConverter; + use crate::common::ChannelCount; #[test] fn remove_channels() { @@ -147,7 +145,7 @@ mod test { #[test] fn size_hint() { - fn test(input: &[i16], from: cpal::ChannelCount, to: cpal::ChannelCount) { + fn test(input: &[i16], from: ChannelCount, to: ChannelCount) { let mut converter = ChannelCountConverter::new(input.iter().copied(), from, to); let count = converter.clone().count(); for left_in_iter in (0..=count).rev() { diff --git a/src/conversions/sample_rate.rs b/src/conversions/sample_rate.rs index 05f8a2e9..3d882d9f 100644 --- a/src/conversions/sample_rate.rs +++ b/src/conversions/sample_rate.rs @@ -1,5 +1,6 @@ use crate::conversions::Sample; +use crate::common::{ChannelCount, SampleRate}; use num_rational::Ratio; use std::mem; @@ -16,7 +17,7 @@ where /// We convert chunks of `from` samples into chunks of `to` samples. to: u32, /// Number of channels in the stream - channels: cpal::ChannelCount, + channels: ChannelCount, /// One sample per channel, extracted from `input`. current_span: Vec<I::Item>, /// Position of `current_sample` modulo `from`. @@ -51,12 +52,12 @@ where #[inline] pub fn new( mut input: I, - from: cpal::SampleRate, - to: cpal::SampleRate, - num_channels: cpal::ChannelCount, + from: SampleRate, + to: SampleRate, + num_channels: ChannelCount, ) -> SampleRateConverter<I> { - let from = from.0; - let to = to.0; + let from = from; + let to = to; assert!(num_channels >= 1); assert!(from >= 1); @@ -251,8 +252,8 @@ where #[cfg(test)] mod test { use super::SampleRateConverter; + use crate::common::{ChannelCount, SampleRate}; use core::time::Duration; - use cpal::{ChannelCount, SampleRate}; use quickcheck::{quickcheck, TestResult}; quickcheck! { @@ -264,8 +265,8 @@ mod test { { return TestResult::discard(); } - let from = SampleRate(from as u32); - let to = SampleRate(to as u32); + let from = from as SampleRate; + let to = to as SampleRate; let input: Vec<u16> = Vec::new(); let output = @@ -279,7 +280,7 @@ mod test { /// Check that resampling to the same rate does not change the signal. fn identity(from: u16, channels: u8, input: Vec<u16>) -> TestResult { if channels == 0 || channels > 128 || from == 0 { return TestResult::discard(); } - let from = SampleRate(from as u32); + let from = from as SampleRate; let output = SampleRateConverter::new(input.clone().into_iter(), from, from, channels as ChannelCount) @@ -295,7 +296,7 @@ mod test { return TestResult::discard(); } - let to = SampleRate(to as u32); + let to = to as SampleRate; let from = to * k as u32; // Truncate the input, so it contains an integer number of spans. @@ -321,7 +322,7 @@ mod test { return TestResult::discard(); } - let from = SampleRate(from as u32); + let from = from as SampleRate; let to = from * k as u32; // Truncate the input, so it contains an integer number of spans. @@ -345,19 +346,19 @@ mod test { /// Check that resampling does not change the audio duration, /// except by a negligible amount (± 1ms). Reproduces #316. /// Ignored, pending a bug fix. - fn preserve_durations(d: Duration, freq: f32, to: u32) -> TestResult { + fn preserve_durations(d: Duration, freq: f32, to: SampleRate) -> TestResult { if to == 0 { return TestResult::discard(); } use crate::source::{SineWave, Source}; - let to = SampleRate(to); + let to = to; let source = SineWave::new(freq).take_duration(d); - let from = SampleRate(source.sample_rate()); + let from = source.sample_rate(); let resampled = SampleRateConverter::new(source, from, to, 1); let duration = - Duration::from_secs_f32(resampled.count() as f32 / to.0 as f32); + Duration::from_secs_f32(resampled.count() as f32 / to as f32); let delta = if d < duration { duration - d } else { d - duration }; TestResult::from_bool(delta < Duration::from_millis(1)) @@ -367,8 +368,7 @@ mod test { #[test] fn upsample() { let input = vec![2u16, 16, 4, 18, 6, 20, 8, 22]; - let output = - SampleRateConverter::new(input.into_iter(), SampleRate(2000), SampleRate(3000), 2); + let output = SampleRateConverter::new(input.into_iter(), 2000, 3000, 2); assert_eq!(output.len(), 12); // Test the source's Iterator::size_hint() let output = output.collect::<Vec<_>>(); @@ -378,8 +378,7 @@ mod test { #[test] fn upsample2() { let input = vec![1u16, 14]; - let output = - SampleRateConverter::new(input.into_iter(), SampleRate(1000), SampleRate(7000), 1); + let output = SampleRateConverter::new(input.into_iter(), 1000, 7000, 1); let size_estimation = output.len(); let output = output.collect::<Vec<_>>(); assert_eq!(output, [1, 2, 4, 6, 8, 10, 12, 14]); @@ -389,8 +388,7 @@ mod test { #[test] fn downsample() { let input = Vec::from_iter(0u16..17); - let output = - SampleRateConverter::new(input.into_iter(), SampleRate(12000), SampleRate(2400), 1); + let output = SampleRateConverter::new(input.into_iter(), 12000, 2400, 1); let size_estimation = output.len(); let output = output.collect::<Vec<_>>(); assert_eq!(output, [0, 5, 10, 15]); diff --git a/src/decoder/flac.rs b/src/decoder/flac.rs index a3ab8532..9773f9d8 100644 --- a/src/decoder/flac.rs +++ b/src/decoder/flac.rs @@ -6,6 +6,7 @@ use std::time::Duration; use crate::source::SeekError; use crate::Source; +use crate::common::{ChannelCount, SampleRate}; use claxon::FlacReader; /// Decoder for the Flac format. @@ -18,8 +19,8 @@ where current_block_channel_len: usize, current_block_off: usize, bits_per_sample: u32, - sample_rate: u32, - channels: u16, + sample_rate: SampleRate, + channels: ChannelCount, samples: Option<u64>, } @@ -45,7 +46,7 @@ where current_block_off: 0, bits_per_sample: spec.bits_per_sample, sample_rate: spec.sample_rate, - channels: spec.channels as u16, + channels: spec.channels as ChannelCount, samples: spec.samples, }) } @@ -64,12 +65,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 29ba027a..ad1e61d7 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -13,6 +13,7 @@ use crate::Source; #[cfg(feature = "symphonia")] use self::read_seek_source::ReadSeekSource; +use crate::common::{ChannelCount, SampleRate}; #[cfg(feature = "symphonia")] use ::symphonia::core::io::{MediaSource, MediaSourceStream}; @@ -118,7 +119,7 @@ impl<R: Read + Seek> DecoderImpl<R> { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { match self { #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))] DecoderImpl::Wav(source) => source.channels(), @@ -135,7 +136,7 @@ impl<R: Read + Seek> DecoderImpl<R> { } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { match self { #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))] DecoderImpl::Wav(source) => source.sample_rate(), @@ -418,11 +419,11 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.0.channels() } - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.0.sample_rate() } @@ -516,12 +517,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.0.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.0.sample_rate() } diff --git a/src/decoder/mp3.rs b/src/decoder/mp3.rs index ebc9a759..f85605c7 100644 --- a/src/decoder/mp3.rs +++ b/src/decoder/mp3.rs @@ -59,12 +59,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.current_span.channels as _ } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.current_span.sample_rate as _ } diff --git a/src/decoder/symphonia.rs b/src/decoder/symphonia.rs index 77da85ac..c466e6ee 100644 --- a/src/decoder/symphonia.rs +++ b/src/decoder/symphonia.rs @@ -14,9 +14,9 @@ use symphonia::{ default::get_probe, }; -use crate::{source, Source}; - use super::DecoderError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{source, Source}; // Decoder errors are not considered fatal. // The correct action is to just get a new packet and try again. @@ -159,12 +159,12 @@ impl Source for SymphoniaDecoder { } #[inline] - fn channels(&self) -> u16 { - self.spec.channels.count() as u16 + fn channels(&self) -> ChannelCount { + self.spec.channels.count() as ChannelCount } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.spec.rate } diff --git a/src/decoder/vorbis.rs b/src/decoder/vorbis.rs index dcf6a441..2e936171 100644 --- a/src/decoder/vorbis.rs +++ b/src/decoder/vorbis.rs @@ -4,6 +4,7 @@ use std::time::Duration; use crate::source::SeekError; use crate::Source; +use crate::common::{ChannelCount, SampleRate}; use lewton::inside_ogg::OggStreamReader; /// Decoder for an OGG file that contains Vorbis sound format. @@ -62,12 +63,12 @@ where } #[inline] - fn channels(&self) -> u16 { - self.stream_reader.ident_hdr.audio_channels as u16 + fn channels(&self) -> ChannelCount { + self.stream_reader.ident_hdr.audio_channels as ChannelCount } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.stream_reader.ident_hdr.audio_sample_rate } diff --git a/src/decoder/wav.rs b/src/decoder/wav.rs index b4a3eaa2..76c27150 100644 --- a/src/decoder/wav.rs +++ b/src/decoder/wav.rs @@ -4,6 +4,7 @@ use std::time::Duration; use crate::source::SeekError; use crate::Source; +use crate::common::{ChannelCount, SampleRate}; use hound::{SampleFormat, WavReader}; /// Decoder for the WAV format. @@ -13,8 +14,8 @@ where { reader: SamplesIterator<R>, total_duration: Duration, - sample_rate: u32, - channels: u16, + sample_rate: SampleRate, + channels: ChannelCount, } impl<R> WavDecoder<R> @@ -43,8 +44,8 @@ where Ok(WavDecoder { reader, total_duration, - sample_rate, - channels, + sample_rate: sample_rate as SampleRate, + channels: channels as ChannelCount, }) } pub fn into_inner(self) -> R { @@ -115,12 +116,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } diff --git a/src/file_output.rs b/src/file_output.rs index 322c94a2..21f2c41a 100644 --- a/src/file_output.rs +++ b/src/file_output.rs @@ -10,7 +10,7 @@ pub fn output_to_wav<S: Sample>( wav_file: impl AsRef<path::Path>, ) -> Result<(), Box<dyn std::error::Error>> { let format = WavSpec { - channels: source.channels(), + channels: source.channels() as u16, sample_rate: source.sample_rate(), bits_per_sample: 32, sample_format: SampleFormat::Float, @@ -26,6 +26,7 @@ pub fn output_to_wav<S: Sample>( #[cfg(test)] mod test { use super::output_to_wav; + use crate::common::ChannelCount; use crate::Source; use std::io::BufReader; use std::time::Duration; @@ -46,7 +47,7 @@ mod test { hound::WavReader::new(BufReader::new(file)).expect("wav file can be read back"); let reference = make_source(); assert_eq!(reference.sample_rate(), reader.spec().sample_rate); - assert_eq!(reference.channels(), reader.spec().channels); + assert_eq!(reference.channels(), reader.spec().channels as ChannelCount); let actual_samples: Vec<f32> = reader.samples::<f32>().map(|x| x.unwrap()).collect(); let expected_samples: Vec<f32> = reference.convert_samples().collect(); diff --git a/src/lib.rs b/src/lib.rs index 339f319f..0450eb95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,7 @@ //! use rodio::{Decoder, OutputStream, source::Source}; //! //! // Get an output stream handle to the default physical sound device. -//! // Note that the playback stops when the stream_handle is dropped. +//! // Note that the playback stops when the stream_handle is dropped.//! //! let stream_handle = rodio::OutputStreamBuilder::open_default_stream() //! .expect("open default audio stream"); //! let sink = rodio::Sink::connect_new(&stream_handle.mixer()); @@ -150,14 +150,17 @@ //! down your program). #![cfg_attr(test, deny(missing_docs))] +#[cfg(feature = "cpal")] pub use cpal::{ self, traits::DeviceTrait, Device, Devices, DevicesError, InputDevices, OutputDevices, SupportedStreamConfig, }; +mod common; mod conversions; mod sink; mod spatial_sink; +#[cfg(feature = "cpal")] mod stream; pub mod buffer; @@ -168,10 +171,12 @@ pub mod queue; pub mod source; pub mod static_buffer; +pub use crate::common::{ChannelCount, SampleRate}; pub use crate::conversions::Sample; pub use crate::decoder::Decoder; pub use crate::file_output::output_to_wav; pub use crate::sink::Sink; pub use crate::source::Source; pub use crate::spatial_sink::SpatialSink; +#[cfg(feature = "cpal")] pub use crate::stream::{play, OutputStream, OutputStreamBuilder, PlayError, StreamError}; diff --git a/src/mixer.rs b/src/mixer.rs index 313e4654..f2719c83 100644 --- a/src/mixer.rs +++ b/src/mixer.rs @@ -1,19 +1,19 @@ //! Mixer that plays multiple sounds at the same time. +use crate::common::{ChannelCount, SampleRate}; +use crate::source::{SeekError, Source, UniformSourceIterator}; +use crate::Sample; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::time::Duration; -use crate::source::{SeekError, Source, UniformSourceIterator}; -use crate::Sample; - /// Builds a new mixer. /// /// You can choose the characteristics of the output thanks to this constructor. All the sounds /// added to the mixer will be converted to these values. /// /// After creating a mixer, you can add new sounds with the controller. -pub fn mixer<S>(channels: u16, sample_rate: u32) -> (Arc<Mixer<S>>, MixerSource<S>) +pub fn mixer<S>(channels: ChannelCount, sample_rate: SampleRate) -> (Arc<Mixer<S>>, MixerSource<S>) where S: Sample + Send + 'static, { @@ -39,8 +39,8 @@ where pub struct Mixer<S> { has_pending: AtomicBool, pending_sources: Mutex<Vec<Box<dyn Source<Item = S> + Send>>>, - channels: u16, - sample_rate: u32, + channels: ChannelCount, + sample_rate: SampleRate, } impl<S> Mixer<S> @@ -90,12 +90,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate } diff --git a/src/queue.rs b/src/queue.rs index cb17973b..2a2f434f 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -7,6 +7,7 @@ use std::time::Duration; use crate::source::{Empty, SeekError, Source, Zero}; use crate::Sample; +use crate::common::{ChannelCount, SampleRate}; #[cfg(feature = "crossbeam-channel")] use crossbeam_channel::{unbounded as channel, Receiver, Sender}; #[cfg(not(feature = "crossbeam-channel"))] @@ -159,12 +160,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.current.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.current.sample_rate() } diff --git a/src/source/agc.rs b/src/source/agc.rs index 88958558..1268e9fb 100644 --- a/src/source/agc.rs +++ b/src/source/agc.rs @@ -23,6 +23,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Duration; +use crate::common::{ChannelCount, SampleRate}; #[cfg(feature = "tracing")] use tracing; @@ -472,12 +473,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/amplify.rs b/src/source/amplify.rs index 14382ceb..11225e1b 100644 --- a/src/source/amplify.rs +++ b/src/source/amplify.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `Amplify` object. pub fn amplify<I>(input: I, factor: f32) -> Amplify<I> @@ -82,12 +82,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/blt.rs b/src/source/blt.rs index 1ba26198..6a973d7b 100644 --- a/src/source/blt.rs +++ b/src/source/blt.rs @@ -1,8 +1,8 @@ +use crate::common::{ChannelCount, SampleRate}; +use crate::Source; use std::f32::consts::PI; use std::time::Duration; -use crate::Source; - use super::SeekError; // Implemented following http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt @@ -163,12 +163,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/buffered.rs b/src/source/buffered.rs index 52b5ff7a..dc85db73 100644 --- a/src/source/buffered.rs +++ b/src/source/buffered.rs @@ -3,9 +3,9 @@ use std::mem; use std::sync::{Arc, Mutex}; use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `Buffered` object. #[inline] @@ -63,8 +63,8 @@ where I::Item: Sample, { data: Vec<I::Item>, - channels: u16, - rate: u32, + channels: ChannelCount, + rate: SampleRate, next: Mutex<Arc<Span<I>>>, } @@ -220,7 +220,7 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { match *self.current_span { Span::Data(SpanData { channels, .. }) => channels, Span::End => 1, @@ -229,7 +229,7 @@ where } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { match *self.current_span { Span::Data(SpanData { rate, .. }) => rate, Span::End => 44100, diff --git a/src/source/channel_volume.rs b/src/source/channel_volume.rs index 7dce1a6f..84862875 100644 --- a/src/source/channel_volume.rs +++ b/src/source/channel_volume.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Combines channels in input into a single mono source, then plays that mono sound /// to each channel at the volume given for that channel. @@ -129,12 +129,12 @@ where } #[inline] - fn channels(&self) -> u16 { - self.channel_volumes.len() as u16 + fn channels(&self) -> ChannelCount { + self.channel_volumes.len() as ChannelCount } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/chirp.rs b/src/source/chirp.rs index 11d97d31..4b99eb85 100644 --- a/src/source/chirp.rs +++ b/src/source/chirp.rs @@ -1,13 +1,13 @@ //! Chirp/sweep source. -use std::{f32::consts::TAU, time::Duration}; - +use crate::common::{ChannelCount, SampleRate}; use crate::Source; +use std::{f32::consts::TAU, time::Duration}; /// Convenience function to create a new `Chirp` source. #[inline] pub fn chirp( - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, start_frequency: f32, end_frequency: f32, duration: Duration, @@ -21,14 +21,14 @@ pub fn chirp( pub struct Chirp { start_frequency: f32, end_frequency: f32, - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, total_samples: u64, elapsed_samples: u64, } impl Chirp { fn new( - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, start_frequency: f32, end_frequency: f32, duration: Duration, @@ -37,7 +37,7 @@ impl Chirp { sample_rate, start_frequency, end_frequency, - total_samples: (duration.as_secs_f64() * (sample_rate.0 as f64)) as u64, + total_samples: (duration.as_secs_f64() * (sample_rate as f64)) as u64, elapsed_samples: 0, } } @@ -61,16 +61,16 @@ impl Source for Chirp { None } - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } - fn sample_rate(&self) -> u32 { - self.sample_rate.0 + fn sample_rate(&self) -> SampleRate { + self.sample_rate } fn total_duration(&self) -> Option<Duration> { - let secs: f64 = self.total_samples as f64 / self.sample_rate.0 as f64; + let secs: f64 = self.total_samples as f64 / self.sample_rate as f64; Some(Duration::new(1, 0).mul_f64(secs)) } } diff --git a/src/source/delay.rs b/src/source/delay.rs index 80384981..a10e5311 100644 --- a/src/source/delay.rs +++ b/src/source/delay.rs @@ -1,10 +1,14 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; -fn remaining_samples(until_playback: Duration, sample_rate: u32, channels: u16) -> usize { +fn remaining_samples( + until_playback: Duration, + sample_rate: SampleRate, + channels: ChannelCount, +) -> usize { let ns = until_playback.as_secs() * 1_000_000_000 + until_playback.subsec_nanos() as u64; let samples = ns * channels as u64 * sample_rate as u64 / 1_000_000_000; samples as usize @@ -95,12 +99,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/done.rs b/src/source/done.rs index c3087434..3ce8a5a3 100644 --- a/src/source/done.rs +++ b/src/source/done.rs @@ -2,9 +2,9 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// When the inner source is empty this decrements a `AtomicUsize`. #[derive(Debug, Clone)] @@ -78,12 +78,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/empty.rs b/src/source/empty.rs index db61defe..c546e5be 100644 --- a/src/source/empty.rs +++ b/src/source/empty.rs @@ -1,9 +1,9 @@ use std::marker::PhantomData; use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// An empty source. #[derive(Debug, Copy, Clone)] @@ -44,12 +44,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { 48000 } diff --git a/src/source/empty_callback.rs b/src/source/empty_callback.rs index 0f7864eb..df7e2a20 100644 --- a/src/source/empty_callback.rs +++ b/src/source/empty_callback.rs @@ -1,9 +1,9 @@ use std::marker::PhantomData; use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// An empty source which executes a callback function pub struct EmptyCallback<S> { @@ -47,12 +47,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { 48000 } diff --git a/src/source/fadein.rs b/src/source/fadein.rs index af884fb7..3eb202c9 100644 --- a/src/source/fadein.rs +++ b/src/source/fadein.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::{linear_ramp::linear_gain_ramp, LinearGainRamp, SeekError}; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `FadeIn` object. pub fn fadein<I>(input: I, duration: Duration) -> FadeIn<I> @@ -81,12 +81,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.inner().channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.inner().sample_rate() } diff --git a/src/source/fadeout.rs b/src/source/fadeout.rs index e3a07fe6..24cac2b3 100644 --- a/src/source/fadeout.rs +++ b/src/source/fadeout.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::{linear_ramp::linear_gain_ramp, LinearGainRamp, SeekError}; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `FadeOut` object. pub fn fadeout<I>(input: I, duration: Duration) -> FadeOut<I> @@ -81,12 +81,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.inner().channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.inner().sample_rate() } diff --git a/src/source/from_iter.rs b/src/source/from_iter.rs index fe8d9fe6..f1709301 100644 --- a/src/source/from_iter.rs +++ b/src/source/from_iter.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Builds a source that chains sources provided by an iterator. /// @@ -114,7 +114,7 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { if let Some(src) = &self.current_source { src.channels() } else { @@ -124,7 +124,7 @@ where } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { if let Some(src) = &self.current_source { src.sample_rate() } else { diff --git a/src/source/linear_ramp.rs b/src/source/linear_ramp.rs index c1ddebfa..bf03855c 100644 --- a/src/source/linear_ramp.rs +++ b/src/source/linear_ramp.rs @@ -1,6 +1,7 @@ use std::time::Duration; use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; use crate::{Sample, Source}; /// Internal function that builds a `LinearRamp` object. @@ -121,12 +122,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/mix.rs b/src/source/mix.rs index d32e55b1..9c573811 100644 --- a/src/source/mix.rs +++ b/src/source/mix.rs @@ -1,6 +1,7 @@ use std::cmp; use std::time::Duration; +use crate::common::{ChannelCount, SampleRate}; use crate::source::uniform::UniformSourceIterator; use crate::source::SeekError; use crate::{Sample, Source}; @@ -101,12 +102,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input1.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input1.sample_rate() } diff --git a/src/source/mod.rs b/src/source/mod.rs index a5f6a3e9..3211301e 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -3,9 +3,9 @@ use core::fmt; use core::time::Duration; -use cpal::FromSample; - +use crate::common::{ChannelCount, SampleRate}; use crate::Sample; +use cpal::FromSample; pub use self::agc::AutomaticGainControl; pub use self::amplify::Amplify; @@ -165,10 +165,10 @@ where fn current_span_len(&self) -> Option<usize>; /// Returns the number of channels. Channels are always interleaved. - fn channels(&self) -> u16; + fn channels(&self) -> ChannelCount; /// Returns the rate at which the source should be played. In number of samples per second. - fn sample_rate(&self) -> u32; + fn sample_rate(&self) -> SampleRate; /// Returns the total duration of this source, if known. /// @@ -669,12 +669,12 @@ macro_rules! source_pointer_impl { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { (**self).channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { (**self).sample_rate() } diff --git a/src/source/noise.rs b/src/source/noise.rs index 350050a9..60937446 100644 --- a/src/source/noise.rs +++ b/src/source/noise.rs @@ -6,17 +6,18 @@ use crate::Source; use super::SeekError; +use crate::common::SampleRate; use rand::{rngs::SmallRng, RngCore, SeedableRng}; /// Convenience function to create a new `WhiteNoise` noise source. #[inline] -pub fn white(sample_rate: cpal::SampleRate) -> WhiteNoise { +pub fn white(sample_rate: SampleRate) -> WhiteNoise { WhiteNoise::new(sample_rate) } /// Convenience function to create a new `PinkNoise` noise source. #[inline] -pub fn pink(sample_rate: cpal::SampleRate) -> PinkNoise { +pub fn pink(sample_rate: SampleRate) -> PinkNoise { PinkNoise::new(sample_rate) } @@ -24,7 +25,7 @@ pub fn pink(sample_rate: cpal::SampleRate) -> PinkNoise { /// samples as provided by the `rand::rngs::SmallRng` randomness source. #[derive(Clone, Debug)] pub struct WhiteNoise { - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, rng: SmallRng, } @@ -38,7 +39,7 @@ impl WhiteNoise { } /// Create a new white noise generator, seeding the RNG with system entropy. - pub fn new(sample_rate: cpal::SampleRate) -> Self { + pub fn new(sample_rate: SampleRate) -> Self { Self { sample_rate, rng: SmallRng::from_entropy(), @@ -64,12 +65,12 @@ impl Source for WhiteNoise { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate.0 } @@ -99,7 +100,7 @@ pub struct PinkNoise { impl PinkNoise { /// Create new pink noise source with given sample rate. - pub fn new(sample_rate: cpal::SampleRate) -> Self { + pub fn new(sample_rate: SampleRate) -> Self { Self { white_noise: WhiteNoise::new(sample_rate), b: [0.0f32, 0.0f32, 0.0f32, 0.0f32, 0.0f32, 0.0f32, 0.0f32], @@ -139,11 +140,11 @@ impl Source for PinkNoise { None } - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.white_noise.sample_rate() } diff --git a/src/source/pausable.rs b/src/source/pausable.rs index fa3a5266..220ed69b 100644 --- a/src/source/pausable.rs +++ b/src/source/pausable.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Builds a `Pausable` object. pub fn pausable<I>(source: I, paused: bool) -> Pausable<I> @@ -31,8 +31,8 @@ where #[derive(Clone, Debug)] pub struct Pausable<I> { input: I, - paused_channels: Option<u16>, - remaining_paused_samples: u16, + paused_channels: Option<ChannelCount>, + remaining_paused_samples: ChannelCount, } impl<I> Pausable<I> @@ -110,12 +110,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/periodic.rs b/src/source/periodic.rs index 08e4f25c..5ce4f74b 100644 --- a/src/source/periodic.rs +++ b/src/source/periodic.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `PeriodicAccess` object. pub fn periodic<I, F>(source: I, period: Duration, modifier: F) -> PeriodicAccess<I, F> @@ -106,12 +106,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/position.rs b/src/source/position.rs index 92758568..b06cc021 100644 --- a/src/source/position.rs +++ b/src/source/position.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `TrackPosition` object. See trait docs for /// details @@ -23,8 +23,8 @@ pub struct TrackPosition<I> { input: I, samples_counted: usize, offset_duration: f64, - current_span_sample_rate: u32, - current_span_channels: u16, + current_span_sample_rate: SampleRate, + current_span_channels: ChannelCount, current_span_len: Option<usize>, } @@ -130,12 +130,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/repeat.rs b/src/source/repeat.rs index 122f24c8..5ccb879e 100644 --- a/src/source/repeat.rs +++ b/src/source/repeat.rs @@ -2,9 +2,9 @@ use std::time::Duration; use crate::source::buffered::Buffered; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `Repeat` object. pub fn repeat<I>(input: I) -> Repeat<I> @@ -67,7 +67,7 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { match self.inner.current_span_len() { Some(0) => self.next.channels(), _ => self.inner.channels(), @@ -75,7 +75,7 @@ where } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { match self.inner.current_span_len() { Some(0) => self.next.sample_rate(), _ => self.inner.sample_rate(), diff --git a/src/source/samples_converter.rs b/src/source/samples_converter.rs index 2dbd42bc..173d262b 100644 --- a/src/source/samples_converter.rs +++ b/src/source/samples_converter.rs @@ -1,11 +1,11 @@ use std::marker::PhantomData; use std::time::Duration; +use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; use crate::{Sample, Source}; use cpal::{FromSample, Sample as CpalSample}; -use super::SeekError; - /// Wrap the input and lazily converts the samples it provides to the type /// specified by the generic parameter D #[derive(Clone)] @@ -83,12 +83,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.inner.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.inner.sample_rate() } diff --git a/src/source/sawtooth.rs b/src/source/sawtooth.rs index 58e56d03..c6ae01f3 100644 --- a/src/source/sawtooth.rs +++ b/src/source/sawtooth.rs @@ -1,7 +1,7 @@ -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::source::{Function, SignalGenerator}; use crate::Source; +use std::time::Duration; use super::SeekError; @@ -17,14 +17,13 @@ pub struct SawtoothWave { } impl SawtoothWave { - const SAMPLE_RATE: u32 = 48000; + const SAMPLE_RATE: SampleRate = 48000; /// The frequency of the sine. #[inline] pub fn new(freq: f32) -> SawtoothWave { - let sr = cpal::SampleRate(Self::SAMPLE_RATE); SawtoothWave { - test_saw: SignalGenerator::new(sr, freq, Function::Sawtooth), + test_saw: SignalGenerator::new(Self::SAMPLE_RATE, freq, Function::Sawtooth), } } } @@ -45,12 +44,12 @@ impl Source for SawtoothWave { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { Self::SAMPLE_RATE } diff --git a/src/source/signal_generator.rs b/src/source/signal_generator.rs index e724297b..e0c33bb8 100644 --- a/src/source/signal_generator.rs +++ b/src/source/signal_generator.rs @@ -9,13 +9,13 @@ //! ``` //! use rodio::source::{SignalGenerator,Function}; //! -//! let tone = SignalGenerator::new(cpal::SampleRate(48000), 440.0, Function::Sine); +//! let tone = SignalGenerator::new(48000, 440.0, Function::Sine); //! ``` -use std::f32::consts::TAU; -use std::time::Duration; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; use crate::Source; +use std::f32::consts::TAU; +use std::time::Duration; /// Generator function. /// @@ -71,7 +71,7 @@ fn sawtooth_signal(phase: f32) -> f32 { /// An infinite source that produces one of a selection of test waveforms. #[derive(Clone, Debug)] pub struct SignalGenerator { - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, function: GeneratorFunction, phase_step: f32, phase: f32, @@ -86,7 +86,7 @@ impl SignalGenerator { /// /// Will panic if `frequency` is equal to zero. #[inline] - pub fn new(sample_rate: cpal::SampleRate, frequency: f32, f: Function) -> Self { + pub fn new(sample_rate: SampleRate, frequency: f32, f: Function) -> Self { let function: GeneratorFunction = match f { Function::Sine => sine_signal, Function::Triangle => triangle_signal, @@ -105,12 +105,12 @@ impl SignalGenerator { /// Will panic if `frequency` is equal to zero. #[inline] pub fn with_function( - sample_rate: cpal::SampleRate, + sample_rate: SampleRate, frequency: f32, generator_function: GeneratorFunction, ) -> Self { assert!(frequency != 0.0, "frequency must be greater than zero"); - let period = sample_rate.0 as f32 / frequency; + let period = sample_rate as f32 / frequency; let phase_step = 1.0f32 / period; SignalGenerator { @@ -142,13 +142,13 @@ impl Source for SignalGenerator { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { - self.sample_rate.0 + fn sample_rate(&self) -> SampleRate { + self.sample_rate } #[inline] @@ -158,7 +158,7 @@ impl Source for SignalGenerator { #[inline] fn try_seek(&mut self, duration: Duration) -> Result<(), SeekError> { - let seek = duration.as_secs_f32() * (self.sample_rate.0 as f32) / self.period; + let seek = duration.as_secs_f32() * (self.sample_rate as f32) / self.period; self.phase = seek.rem_euclid(1.0f32); Ok(()) } @@ -171,7 +171,7 @@ mod tests { #[test] fn square() { - let mut wf = SignalGenerator::new(cpal::SampleRate(2000), 500.0f32, Function::Square); + let mut wf = SignalGenerator::new(2000, 500.0f32, Function::Square); assert_eq!(wf.next(), Some(1.0f32)); assert_eq!(wf.next(), Some(1.0f32)); assert_eq!(wf.next(), Some(-1.0f32)); @@ -184,7 +184,7 @@ mod tests { #[test] fn triangle() { - let mut wf = SignalGenerator::new(cpal::SampleRate(8000), 1000.0f32, Function::Triangle); + let mut wf = SignalGenerator::new(8000, 1000.0f32, Function::Triangle); assert_eq!(wf.next(), Some(-1.0f32)); assert_eq!(wf.next(), Some(-0.5f32)); assert_eq!(wf.next(), Some(0.0f32)); @@ -205,7 +205,7 @@ mod tests { #[test] fn saw() { - let mut wf = SignalGenerator::new(cpal::SampleRate(200), 50.0f32, Function::Sawtooth); + let mut wf = SignalGenerator::new(200, 50.0f32, Function::Sawtooth); assert_eq!(wf.next(), Some(0.0f32)); assert_eq!(wf.next(), Some(0.5f32)); assert_eq!(wf.next(), Some(-1.0f32)); @@ -217,7 +217,7 @@ mod tests { #[test] fn sine() { - let mut wf = SignalGenerator::new(cpal::SampleRate(1000), 100f32, Function::Sine); + let mut wf = SignalGenerator::new(1000, 100f32, Function::Sine); assert_abs_diff_eq!(wf.next().unwrap(), 0.0f32); assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525f32); diff --git a/src/source/sine.rs b/src/source/sine.rs index c10c536c..e3814435 100644 --- a/src/source/sine.rs +++ b/src/source/sine.rs @@ -1,7 +1,7 @@ -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::source::{Function, SignalGenerator}; use crate::Source; +use std::time::Duration; use super::SeekError; @@ -22,9 +22,8 @@ impl SineWave { /// The frequency of the sine. #[inline] pub fn new(freq: f32) -> SineWave { - let sr = cpal::SampleRate(Self::SAMPLE_RATE); SineWave { - test_sine: SignalGenerator::new(sr, freq, Function::Sine), + test_sine: SignalGenerator::new(Self::SAMPLE_RATE, freq, Function::Sine), } } } @@ -45,12 +44,12 @@ impl Source for SineWave { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { Self::SAMPLE_RATE } diff --git a/src/source/skip.rs b/src/source/skip.rs index 96ebd3c9..ef80227e 100644 --- a/src/source/skip.rs +++ b/src/source/skip.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; const NS_PER_SECOND: u128 = 1_000_000_000; @@ -143,12 +143,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } @@ -171,11 +171,12 @@ mod tests { use std::time::Duration; use crate::buffer::SamplesBuffer; + use crate::common::{ChannelCount, SampleRate}; use crate::source::Source; fn test_skip_duration_samples_left( - channels: u16, - sample_rate: u32, + channels: ChannelCount, + sample_rate: SampleRate, seconds: u32, seconds_to_skip: u32, ) { diff --git a/src/source/skippable.rs b/src/source/skippable.rs index 9bcd559a..d77447cf 100644 --- a/src/source/skippable.rs +++ b/src/source/skippable.rs @@ -1,7 +1,7 @@ -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::Sample; use crate::Source; +use std::time::Duration; use super::SeekError; @@ -83,12 +83,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/spatial.rs b/src/source/spatial.rs index 3c0f4b70..f8a2b5ca 100644 --- a/src/source/spatial.rs +++ b/src/source/spatial.rs @@ -1,10 +1,10 @@ use std::time::Duration; +use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; use crate::source::ChannelVolume; use crate::{Sample, Source}; -use super::SeekError; - /// A simple spatial audio source. The underlying source is transformed to Mono /// and then played in stereo. The left and right channel's volume are amplified /// differently depending on the distance of the left and right ear to the source. @@ -108,12 +108,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/speed.rs b/src/source/speed.rs index 76f00e4f..6409dff2 100644 --- a/src/source/speed.rs +++ b/src/source/speed.rs @@ -47,9 +47,9 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `Speed` object. pub fn speed<I>(input: I, factor: f32) -> Speed<I> { @@ -129,12 +129,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { (self.input.sample_rate() as f32 * self.factor) as u32 } diff --git a/src/source/square.rs b/src/source/square.rs index 40c10511..ac6bd678 100644 --- a/src/source/square.rs +++ b/src/source/square.rs @@ -1,7 +1,7 @@ -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::source::{Function, SignalGenerator}; use crate::Source; +use std::time::Duration; use super::SeekError; @@ -22,9 +22,8 @@ impl SquareWave { /// The frequency of the sine. #[inline] pub fn new(freq: f32) -> SquareWave { - let sr = cpal::SampleRate(Self::SAMPLE_RATE); SquareWave { - test_square: SignalGenerator::new(sr, freq, Function::Square), + test_square: SignalGenerator::new(Self::SAMPLE_RATE, freq, Function::Square), } } } @@ -45,12 +44,12 @@ impl Source for SquareWave { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { Self::SAMPLE_RATE } diff --git a/src/source/stoppable.rs b/src/source/stoppable.rs index cde1b1d2..116efe39 100644 --- a/src/source/stoppable.rs +++ b/src/source/stoppable.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// This is the same as [`skippable`](crate::source::skippable) see its docs pub fn stoppable<I>(source: I) -> Stoppable<I> { @@ -78,12 +78,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/take.rs b/src/source/take.rs index 6b8f4bbf..9e036f6e 100644 --- a/src/source/take.rs +++ b/src/source/take.rs @@ -1,8 +1,8 @@ use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// Internal function that builds a `TakeDuration` object. pub fn take_duration<I>(input: I, duration: Duration) -> TakeDuration<I> @@ -160,12 +160,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.input.channels() } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.input.sample_rate() } diff --git a/src/source/triangle.rs b/src/source/triangle.rs index 89889a98..eb73801d 100644 --- a/src/source/triangle.rs +++ b/src/source/triangle.rs @@ -1,7 +1,7 @@ -use std::time::Duration; - +use crate::common::{ChannelCount, SampleRate}; use crate::source::{Function, SignalGenerator}; use crate::Source; +use std::time::Duration; use super::SeekError; @@ -17,14 +17,13 @@ pub struct TriangleWave { } impl TriangleWave { - const SAMPLE_RATE: u32 = 48000; + const SAMPLE_RATE: SampleRate = 48000; /// The frequency of the sine. #[inline] pub fn new(freq: f32) -> TriangleWave { - let sr = cpal::SampleRate(Self::SAMPLE_RATE); TriangleWave { - test_tri: SignalGenerator::new(sr, freq, Function::Triangle), + test_tri: SignalGenerator::new(Self::SAMPLE_RATE, freq, Function::Triangle), } } } @@ -45,12 +44,12 @@ impl Source for TriangleWave { } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { 1 } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { Self::SAMPLE_RATE } diff --git a/src/source/uniform.rs b/src/source/uniform.rs index 8454927d..30472ed9 100644 --- a/src/source/uniform.rs +++ b/src/source/uniform.rs @@ -3,11 +3,11 @@ use std::time::Duration; use cpal::FromSample; +use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; use crate::conversions::{ChannelCountConverter, DataConverter, SampleRateConverter}; use crate::{Sample, Source}; -use super::SeekError; - /// An iterator that reads from a `Source` and converts the samples to a /// specific type, sample-rate and channels count. /// @@ -21,8 +21,8 @@ where D: Sample, { inner: Option<DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D>>, - target_channels: u16, - target_sample_rate: u32, + target_channels: ChannelCount, + target_sample_rate: SampleRate, total_duration: Option<Duration>, } @@ -37,8 +37,8 @@ where #[inline] pub fn new( input: I, - target_channels: u16, - target_sample_rate: u32, + target_channels: ChannelCount, + target_sample_rate: SampleRate, ) -> UniformSourceIterator<I, D> { let total_duration = input.total_duration(); let input = UniformSourceIterator::bootstrap(input, target_channels, target_sample_rate); @@ -54,8 +54,8 @@ where #[inline] fn bootstrap( input: I, - target_channels: u16, - target_sample_rate: u32, + target_channels: ChannelCount, + target_sample_rate: SampleRate, ) -> DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D> { // Limit the span length to something reasonable let span_len = input.current_span_len().map(|x| x.min(32768)); @@ -67,12 +67,8 @@ where iter: input, n: span_len, }; - let input = SampleRateConverter::new( - input, - cpal::SampleRate(from_sample_rate), - cpal::SampleRate(target_sample_rate), - from_channels, - ); + let input = + SampleRateConverter::new(input, from_sample_rate, target_sample_rate, from_channels); let input = ChannelCountConverter::new(input, from_channels, target_channels); DataConverter::new(input) @@ -128,12 +124,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.target_channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.target_sample_rate } diff --git a/src/source/zero.rs b/src/source/zero.rs index 8fe2dda7..69e3a295 100644 --- a/src/source/zero.rs +++ b/src/source/zero.rs @@ -1,17 +1,17 @@ use std::marker::PhantomData; use std::time::Duration; -use crate::{Sample, Source}; - use super::SeekError; +use crate::common::{ChannelCount, SampleRate}; +use crate::{Sample, Source}; /// An source that produces samples with value zero (silence). Depending on if /// it where created with [`Zero::new`] or [`Zero::new_samples`] it can be never /// ending or finite. #[derive(Clone, Debug)] pub struct Zero<S> { - channels: u16, - sample_rate: u32, + channels: ChannelCount, + sample_rate: SampleRate, num_samples: Option<usize>, marker: PhantomData<S>, } @@ -19,7 +19,7 @@ pub struct Zero<S> { impl<S> Zero<S> { /// Create a new source that never ends and produces total silence. #[inline] - pub fn new(channels: u16, sample_rate: u32) -> Zero<S> { + pub fn new(channels: ChannelCount, sample_rate: SampleRate) -> Zero<S> { Zero { channels, sample_rate, @@ -29,7 +29,11 @@ impl<S> Zero<S> { } /// Create a new source that never ends and produces total silence. #[inline] - pub fn new_samples(channels: u16, sample_rate: u32, num_samples: usize) -> Zero<S> { + pub fn new_samples( + channels: ChannelCount, + sample_rate: SampleRate, + num_samples: usize, + ) -> Zero<S> { Zero { channels, sample_rate, @@ -70,12 +74,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } diff --git a/src/static_buffer.rs b/src/static_buffer.rs index b43c1917..4b2c650e 100644 --- a/src/static_buffer.rs +++ b/src/static_buffer.rs @@ -13,6 +13,7 @@ use std::slice::Iter as SliceIter; use std::time::Duration; +use crate::common::{ChannelCount, SampleRate}; use crate::source::SeekError; use crate::{Sample, Source}; @@ -23,8 +24,8 @@ where S: 'static, { data: SliceIter<'static, S>, - channels: u16, - sample_rate: u32, + channels: ChannelCount, + sample_rate: SampleRate, duration: Duration, } @@ -41,7 +42,11 @@ where /// - Panics if the length of the buffer is larger than approximately 16 billion elements. /// This is because the calculation of the duration would overflow. /// - pub fn new(channels: u16, sample_rate: u32, data: &'static [S]) -> StaticSamplesBuffer<S> { + pub fn new( + channels: ChannelCount, + sample_rate: SampleRate, + data: &'static [S], + ) -> StaticSamplesBuffer<S> { assert!(channels != 0); assert!(sample_rate != 0); @@ -72,12 +77,12 @@ where } #[inline] - fn channels(&self) -> u16 { + fn channels(&self) -> ChannelCount { self.channels } #[inline] - fn sample_rate(&self) -> u32 { + fn sample_rate(&self) -> SampleRate { self.sample_rate } diff --git a/src/stream.rs b/src/stream.rs index 246f0c98..48616eea 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -3,16 +3,14 @@ use std::marker::Sync; use std::sync::Arc; use std::{error, fmt}; +use crate::common::{ChannelCount, SampleRate}; use crate::decoder; use crate::mixer::{mixer, Mixer, MixerSource}; use crate::sink::Sink; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use cpal::{ - BufferSize, ChannelCount, FrameCount, Sample, SampleFormat, SampleRate, StreamConfig, - SupportedBufferSize, -}; +use cpal::{BufferSize, FrameCount, Sample, SampleFormat, StreamConfig, SupportedBufferSize}; -const HZ_44100: cpal::SampleRate = cpal::SampleRate(44_100); +const HZ_44100: SampleRate = 44_100; /// `cpal::Stream` container. /// Use `mixer()` method to control output. @@ -85,14 +83,14 @@ impl OutputStreamBuilder { } /// Sets number of output stream's channels. - pub fn with_channels(mut self, channel_count: cpal::ChannelCount) -> OutputStreamBuilder { + pub fn with_channels(mut self, channel_count: ChannelCount) -> OutputStreamBuilder { assert!(channel_count > 0); self.config.channel_count = channel_count; self } /// Sets output stream's sample rate. - pub fn with_sample_rate(mut self, sample_rate: cpal::SampleRate) -> OutputStreamBuilder { + pub fn with_sample_rate(mut self, sample_rate: SampleRate) -> OutputStreamBuilder { self.config.sample_rate = sample_rate; self } @@ -118,8 +116,8 @@ impl OutputStreamBuilder { config: &cpal::SupportedStreamConfig, ) -> OutputStreamBuilder { self.config = OutputStreamConfig { - channel_count: config.channels(), - sample_rate: config.sample_rate(), + channel_count: config.channels() as ChannelCount, + sample_rate: config.sample_rate().0 as SampleRate, // In case of supported range limit buffer size to avoid unexpectedly long playback delays. buffer_size: clamp_supported_buffer_size(config.buffer_size(), 1024), sample_format: config.sample_format(), @@ -130,8 +128,8 @@ impl OutputStreamBuilder { /// Set all output stream parameters at once from CPAL stream config. pub fn with_config(mut self, config: &cpal::StreamConfig) -> OutputStreamBuilder { self.config = OutputStreamConfig { - channel_count: config.channels, - sample_rate: config.sample_rate, + channel_count: config.channels as ChannelCount, + sample_rate: config.sample_rate.0 as SampleRate, buffer_size: config.buffer_size, ..self.config }; @@ -220,8 +218,8 @@ where impl From<&OutputStreamConfig> for StreamConfig { fn from(config: &OutputStreamConfig) -> Self { cpal::StreamConfig { - channels: config.channel_count, - sample_rate: config.sample_rate, + channels: config.channel_count as cpal::ChannelCount, + sample_rate: cpal::SampleRate(config.sample_rate), buffer_size: config.buffer_size, } } @@ -307,7 +305,7 @@ impl OutputStream { device: &cpal::Device, config: &OutputStreamConfig, ) -> Result<OutputStream, StreamError> { - let (controller, source) = mixer(config.channel_count, config.sample_rate.0); + let (controller, source) = mixer(config.channel_count, config.sample_rate); Self::init_stream(device, config, source) .map_err(StreamError::BuildStreamError) .and_then(|stream| { @@ -458,8 +456,9 @@ fn supported_output_configs( let max_rate = sf.max_sample_rate(); let min_rate = sf.min_sample_rate(); let mut formats = vec![sf.with_max_sample_rate()]; - if HZ_44100 < max_rate && HZ_44100 > min_rate { - formats.push(sf.with_sample_rate(HZ_44100)) + let preferred_rate = cpal::SampleRate(HZ_44100); + if preferred_rate < max_rate && preferred_rate > min_rate { + formats.push(sf.with_sample_rate(preferred_rate)) } formats.push(sf.with_sample_rate(min_rate)); formats diff --git a/tests/seek.rs b/tests/seek.rs index 4c49ad80..0cc47c97 100644 --- a/tests/seek.rs +++ b/tests/seek.rs @@ -1,11 +1,10 @@ +use rodio::{ChannelCount, Decoder, Source}; +use rstest::rstest; +use rstest_reuse::{self, *}; use std::io::{BufReader, Read, Seek}; use std::path::Path; use std::time::Duration; -use rodio::{Decoder, Source}; -use rstest::rstest; -use rstest_reuse::{self, *}; - #[template] #[rstest] // note: disabled, broken decoder see issue: #516 and #539 @@ -203,17 +202,22 @@ where .next_multiple_of(channels); let samples = &samples[beep_starts..beep_starts + 100]; - assert!(is_silent(samples, channels as u16, 0), "{samples:?}"); - assert!(!is_silent(samples, channels as u16, 1), "{samples:?}"); + assert!( + is_silent(samples, channels as ChannelCount, 0), + "{samples:?}" + ); + assert!( + !is_silent(samples, channels as ChannelCount, 1), + "{samples:?}" + ); beep_starts..beep_ends } -fn is_silent(samples: &[f32], channels: u16, channel: usize) -> bool { +fn is_silent(samples: &[f32], channels: ChannelCount, channel: usize) -> bool { assert_eq!(samples.len(), 100); let channel = samples.iter().skip(channel).step_by(channels as usize); - let volume = - channel.map(|s| s.abs()).sum::<f32>() as f32 / samples.len() as f32 * channels as f32; + let volume = channel.map(|s| s.abs()).sum::<f32>() / samples.len() as f32 * channels as f32; const BASICALLY_ZERO: f32 = 0.0001; volume < BASICALLY_ZERO