Skip to content

Commit 1cf3a7c

Browse files
authored
Merge pull request #96 from BillyDM/cpal_17
update to cpal version 0.17
2 parents f72f532 + fcc7296 commit 1cf3a7c

File tree

11 files changed

+523
-437
lines changed

11 files changed

+523
-437
lines changed

Cargo.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@ musical_transport = [
5454
cpal = ["std", "dep:firewheel-cpal"]
5555
# Enables resampling input streams in the cpal backend
5656
cpal_resample_inputs = ["firewheel-cpal?/resample_inputs"]
57-
# Enables using Symphonium for loading audio files
58-
symphonium = ["firewheel-core/symphonium"]
59-
# Enables resampling audio files when loading them with Symphonium
60-
symphonium_resample = ["firewheel-core/symphonium_resample"]
57+
# Enables using Symphonium for loading audio files.
58+
# Requires the standard library.
59+
symphonium = ["dep:firewheel-symphonium"]
60+
# Enables resampling audio files when loading them with Symphonium.
61+
symphonium_resample = ["symphonium", "firewheel-symphonium?/resample"]
6162
# Enables the "arbitrary sinc" resampler for changing the pitch/length
6263
# of samples at load time.
63-
symphonium_stretch = ["firewheel-core/symphonium_stretch"]
64+
symphonium_stretch = ["symphonium", "firewheel-symphonium?/stretch"]
6465
# Enables the `AudioNodePool` helper type for constructing a pool of
6566
# audio node chains that can dynamically be assigned work.
6667
pool = ["dep:firewheel-pool"]
@@ -154,6 +155,7 @@ members = [
154155
"crates/firewheel-nodes",
155156
"crates/firewheel-macros",
156157
"crates/firewheel-pool",
158+
"crates/firewheel-symphonium",
157159
"examples/beep_test",
158160
"examples/cpal_input",
159161
"examples/custom_nodes",
@@ -204,6 +206,7 @@ firewheel-graph = { path = "crates/firewheel-graph", version = "0.10.0", default
204206
firewheel-cpal = { path = "crates/firewheel-cpal", version = "0.10.0", default-features = false, optional = true }
205207
firewheel-nodes = { path = "crates/firewheel-nodes", version = "0.10.0", default-features = false }
206208
firewheel-pool = { path = "crates/firewheel-pool", version = "0.10.0", default-features = false, optional = true }
209+
firewheel-symphonium = { path = "crates/firewheel-symphonium", version = "0.10.0", default-features = false, optional = true }
207210
thunderdome = { workspace = true, optional = true }
208211
smallvec = { workspace = true, optional = true }
209212
thiserror.workspace = true

crates/firewheel-core/Cargo.toml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,6 @@ scheduled_events = []
7676
# can still schedule musical events for your node even if you have this
7777
# feature disabled in your library.
7878
musical_transport = ["scheduled_events"]
79-
symphonium = ["std", "dep:symphonium"]
80-
symphonium_resample = [
81-
"symphonium",
82-
"dep:fixed-resample",
83-
"symphonium?/resampler",
84-
]
85-
# Enables the "arbitrary sinc" resampler in Symphonium for changing the
86-
# pitch/length of samples at load time.
87-
symphonium_stretch = [
88-
"symphonium",
89-
"symphonium_resample",
90-
"symphonium?/stretch-sinc-resampler",
91-
]
9279
# Enables `Component` derives for parameters.
9380
bevy = ["dep:bevy_ecs"]
9481
# Enables `Reflect` derives for core types.
@@ -107,11 +94,6 @@ firewheel-macros.workspace = true
10794
arrayvec.workspace = true
10895
bitflags.workspace = true
10996
thunderdome.workspace = true
110-
symphonium = { version = "0.6.5", default-features = false, optional = true }
111-
fixed-resample = { version = "0.9.2", default-features = false, features = [
112-
"resampler",
113-
"fft-resampler",
114-
], optional = true }
11597
smallvec.workspace = true
11698
bevy_platform.workspace = true
11799
thiserror.workspace = true

crates/firewheel-core/src/lib.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ pub struct StreamInfo {
3737
/// The latency of the input to output stream in seconds.
3838
pub input_to_output_latency_seconds: f64,
3939
pub declick_frames: NonZeroU32,
40-
/// The name of the input audio device.
41-
pub input_device_name: Option<String>,
42-
/// The name of the output audio device.
43-
pub output_device_name: Option<String>,
40+
/// The identifier of the output audio device (converted to a string).
41+
pub output_device_id: String,
42+
/// The identifier of the input audio device (converted to a string).
43+
pub input_device_id: Option<String>,
4444
}
4545

4646
impl Default for StreamInfo {
@@ -54,11 +54,8 @@ impl Default for StreamInfo {
5454
num_stream_out_channels: 2,
5555
input_to_output_latency_seconds: 0.0,
5656
declick_frames: NonZeroU32::MIN,
57-
input_device_name: None,
58-
output_device_name: None,
57+
output_device_id: String::new(),
58+
input_device_id: None,
5959
}
6060
}
6161
}
62-
63-
#[cfg(feature = "symphonium")]
64-
pub use sample_resource::{load_audio_file, load_audio_file_from_source};

crates/firewheel-core/src/sample_resource.rs

Lines changed: 0 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -374,238 +374,3 @@ pub fn fill_buffers_deinterleaved_f32<V: AsRef<[f32]>>(
374374
);
375375
}
376376
}
377-
378-
#[cfg(feature = "symphonium")]
379-
/// A wrapper around [`symphonium::DecodedAudio`] which implements the
380-
/// [`SampleResource`] trait.
381-
#[derive(Debug, Clone)]
382-
pub struct DecodedAudio(pub symphonium::DecodedAudio);
383-
384-
#[cfg(feature = "symphonium")]
385-
impl DecodedAudio {
386-
pub fn duration_seconds(&self) -> f64 {
387-
self.0.frames() as f64 / self.0.sample_rate() as f64
388-
}
389-
390-
pub fn into_dyn_resource(self) -> crate::collector::ArcGc<dyn SampleResource> {
391-
crate::collector::ArcGc::new_unsized(|| {
392-
bevy_platform::sync::Arc::new(self) as bevy_platform::sync::Arc<dyn SampleResource>
393-
})
394-
}
395-
}
396-
397-
#[cfg(feature = "symphonium")]
398-
impl From<DecodedAudio> for crate::collector::ArcGc<dyn SampleResource> {
399-
fn from(value: DecodedAudio) -> Self {
400-
value.into_dyn_resource()
401-
}
402-
}
403-
404-
#[cfg(feature = "symphonium")]
405-
impl SampleResourceInfo for DecodedAudio {
406-
fn num_channels(&self) -> NonZeroUsize {
407-
NonZeroUsize::new(self.0.channels()).unwrap()
408-
}
409-
410-
fn len_frames(&self) -> u64 {
411-
self.0.frames() as u64
412-
}
413-
}
414-
415-
#[cfg(feature = "symphonium")]
416-
impl SampleResource for DecodedAudio {
417-
fn fill_buffers(
418-
&self,
419-
buffers: &mut [&mut [f32]],
420-
buffer_range: Range<usize>,
421-
start_frame: u64,
422-
) {
423-
let channels = self.0.channels().min(buffers.len());
424-
425-
if channels == 2 {
426-
let (b1, b2) = buffers.split_first_mut().unwrap();
427-
428-
self.0.fill_stereo(
429-
start_frame as usize,
430-
&mut b1[buffer_range.clone()],
431-
&mut b2[0][buffer_range.clone()],
432-
);
433-
} else {
434-
for (ch_i, b) in buffers[0..channels].iter_mut().enumerate() {
435-
self.0
436-
.fill_channel(ch_i, start_frame as usize, &mut b[buffer_range.clone()])
437-
.unwrap();
438-
}
439-
}
440-
}
441-
}
442-
443-
#[cfg(feature = "symphonium")]
444-
impl From<symphonium::DecodedAudio> for DecodedAudio {
445-
fn from(data: symphonium::DecodedAudio) -> Self {
446-
Self(data)
447-
}
448-
}
449-
450-
#[cfg(feature = "symphonium")]
451-
/// A wrapper around [`symphonium::DecodedAudioF32`] which implements the
452-
/// [`SampleResource`] trait.
453-
#[derive(Debug, Clone)]
454-
pub struct DecodedAudioF32(pub symphonium::DecodedAudioF32);
455-
456-
#[cfg(feature = "symphonium")]
457-
impl DecodedAudioF32 {
458-
pub fn duration_seconds(&self, sample_rate: u32) -> f64 {
459-
self.0.frames() as f64 / sample_rate as f64
460-
}
461-
}
462-
463-
#[cfg(feature = "symphonium")]
464-
impl SampleResourceInfo for DecodedAudioF32 {
465-
fn num_channels(&self) -> NonZeroUsize {
466-
NonZeroUsize::new(self.0.channels()).unwrap()
467-
}
468-
469-
fn len_frames(&self) -> u64 {
470-
self.0.frames() as u64
471-
}
472-
}
473-
474-
#[cfg(feature = "symphonium")]
475-
impl SampleResource for DecodedAudioF32 {
476-
fn fill_buffers(
477-
&self,
478-
buffers: &mut [&mut [f32]],
479-
buffer_range: Range<usize>,
480-
start_frame: u64,
481-
) {
482-
fill_buffers_deinterleaved_f32(buffers, buffer_range, start_frame as usize, &self.0.data);
483-
}
484-
}
485-
486-
#[cfg(feature = "symphonium")]
487-
impl From<symphonium::DecodedAudioF32> for DecodedAudioF32 {
488-
fn from(data: symphonium::DecodedAudioF32) -> Self {
489-
Self(data)
490-
}
491-
}
492-
493-
/// A helper method to load an audio file from a path using Symphonium.
494-
///
495-
/// * `loader` - The symphonium loader.
496-
/// * `path`` - The path to the audio file stored on disk.
497-
/// * `sample_rate` - The sample rate of the audio stream.
498-
/// * `resample_quality` - The quality of the resampler to use.
499-
#[cfg(feature = "symphonium")]
500-
pub fn load_audio_file<P: AsRef<std::path::Path>>(
501-
loader: &mut symphonium::SymphoniumLoader,
502-
path: P,
503-
#[cfg(feature = "symphonium_resample")] sample_rate: core::num::NonZeroU32,
504-
#[cfg(feature = "symphonium_resample")] resample_quality: symphonium::ResampleQuality,
505-
) -> Result<DecodedAudio, symphonium::error::LoadError> {
506-
loader
507-
.load(
508-
path,
509-
#[cfg(feature = "symphonium_resample")]
510-
Some(sample_rate.get()),
511-
#[cfg(feature = "symphonium_resample")]
512-
resample_quality,
513-
None,
514-
)
515-
.map(|d| DecodedAudio(d))
516-
}
517-
518-
/// A helper method to load an audio file from a custom source using Symphonium.
519-
///
520-
/// * `loader` - The symphonium loader.
521-
/// * `source` - The audio source which implements the [`MediaSource`] trait.
522-
/// * `hint` - An optional hint to help the format registry guess what format reader is appropriate.
523-
/// * `sample_rate` - The sample rate of the audio stream.
524-
/// * `resample_quality` - The quality of the resampler to use.
525-
///
526-
/// [`MediaSource`]: symphonium::symphonia::core::io::MediaSource
527-
#[cfg(feature = "symphonium")]
528-
pub fn load_audio_file_from_source(
529-
loader: &mut symphonium::SymphoniumLoader,
530-
source: Box<dyn symphonium::symphonia::core::io::MediaSource>,
531-
hint: Option<symphonium::symphonia::core::probe::Hint>,
532-
#[cfg(feature = "symphonium_resample")] sample_rate: core::num::NonZeroU32,
533-
#[cfg(feature = "symphonium_resample")] resample_quality: symphonium::ResampleQuality,
534-
) -> Result<DecodedAudio, symphonium::error::LoadError> {
535-
loader
536-
.load_from_source(
537-
source,
538-
hint,
539-
#[cfg(feature = "symphonium_resample")]
540-
Some(sample_rate.get()),
541-
#[cfg(feature = "symphonium_resample")]
542-
resample_quality,
543-
None,
544-
)
545-
.map(|d| DecodedAudio(d))
546-
}
547-
548-
/// A helper method to load an audio file from a path using Symphonium. This
549-
/// also stretches (pitch shifts) the sample by the given amount.
550-
///
551-
/// * `loader` - The symphonium loader.
552-
/// * `path`` - The path to the audio file stored on disk.
553-
/// * `sample_rate` - The sample rate of the audio stream.
554-
/// * `stretch` - The amount of stretching (`new_length / old_length`). A value of `1.0` is no
555-
/// change, a value less than `1.0` will increase the pitch & decrease the length, and a value
556-
/// greater than `1.0` will decrease the pitch & increase the length. If a `target_sample_rate`
557-
/// is given, then the final amount will automatically be adjusted to account for that.
558-
#[cfg(feature = "symphonium_stretch")]
559-
pub fn load_audio_file_stretched<P: AsRef<std::path::Path>>(
560-
loader: &mut symphonium::SymphoniumLoader,
561-
path: P,
562-
sample_rate: core::num::NonZeroU32,
563-
stretch: f64,
564-
) -> Result<DecodedAudio, symphonium::error::LoadError> {
565-
loader
566-
.load_f32_stretched(path, stretch, Some(sample_rate.get()), None)
567-
.map(|d| DecodedAudio(d.into()))
568-
}
569-
570-
/// A helper method to load an audio file from a custom source using Symphonium. This
571-
/// also stretches (pitch shifts) the sample by the given amount.
572-
///
573-
/// * `loader` - The symphonium loader.
574-
/// * `source` - The audio source which implements the [`symphonium::symphonia::core::io::MediaSource`]
575-
/// trait.
576-
/// * `hint` - An optional hint to help the format registry guess what format reader is appropriate.
577-
/// * `sample_rate` - The sample rate of the audio stream.
578-
/// * `stretch` - The amount of stretching (`new_length / old_length`). A value of `1.0` is no
579-
/// change, a value less than `1.0` will increase the pitch & decrease the length, and a value
580-
/// greater than `1.0` will decrease the pitch & increase the length. If a `target_sample_rate`
581-
/// is given, then the final amount will automatically be adjusted to account for that.
582-
#[cfg(feature = "symphonium_stretch")]
583-
pub fn load_audio_file_from_source_stretched(
584-
loader: &mut symphonium::SymphoniumLoader,
585-
source: Box<dyn symphonium::symphonia::core::io::MediaSource>,
586-
hint: Option<symphonium::symphonia::core::probe::Hint>,
587-
sample_rate: core::num::NonZeroU32,
588-
stretch: f64,
589-
) -> Result<DecodedAudio, symphonium::error::LoadError> {
590-
loader
591-
.load_f32_from_source_stretched(source, hint, stretch, Some(sample_rate.get()), None)
592-
.map(|d| DecodedAudio(d.into()))
593-
}
594-
595-
#[cfg(feature = "symphonium")]
596-
/// A helper method to convert a [`symphonium::DecodedAudio`] resource into
597-
/// a [`SampleResource`].
598-
pub fn decoded_to_resource(
599-
data: symphonium::DecodedAudio,
600-
) -> bevy_platform::sync::Arc<dyn SampleResource> {
601-
bevy_platform::sync::Arc::new(DecodedAudio(data))
602-
}
603-
604-
#[cfg(feature = "symphonium")]
605-
/// A helper method to convert a [`symphonium::DecodedAudioF32`] resource into
606-
/// a [`SampleResource`].
607-
pub fn decoded_f32_to_resource(
608-
data: symphonium::DecodedAudioF32,
609-
) -> bevy_platform::sync::Arc<dyn SampleResource> {
610-
bevy_platform::sync::Arc::new(DecodedAudioF32(data))
611-
}

crates/firewheel-cpal/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ log = ["dep:log"]
2727
[dependencies]
2828
firewheel-core = { path = "../firewheel-core", version = "0.10.0", default-features = false }
2929
firewheel-graph = { path = "../firewheel-graph", version = "0.10.0", default-features = false }
30-
cpal = "0.16.0"
30+
cpal = "0.17.1"
3131
tracing = { workspace = true, optional = true }
3232
log = { workspace = true, optional = true }
3333
ringbuf.workspace = true

0 commit comments

Comments
 (0)