Skip to content

Commit

Permalink
Migrate Sample to dasp_sample (RustAudio#689)
Browse files Browse the repository at this point in the history
  • Loading branch information
kawogi authored and Hoodad committed Feb 8, 2023
1 parent 74a9370 commit d768244
Show file tree
Hide file tree
Showing 17 changed files with 319 additions and 337 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ asio = ["asio-sys", "num-traits"] # Only available on Windows. See README for se

[dependencies]
thiserror = "1.0.2"
dasp_sample = "0.11.0"

[dev-dependencies]
anyhow = "1.0.12"
Expand Down
26 changes: 21 additions & 5 deletions examples/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
extern crate anyhow;
extern crate cpal;

use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
SizedSample,
};
use cpal::{FromSample, Sample};

#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "full"))]
fn main() {
Expand All @@ -16,15 +20,27 @@ fn main() {
let config = device.default_output_config().unwrap();

match config.sample_format() {
cpal::SampleFormat::F32 => run::<f32>(&device, &config.into()).unwrap(),
cpal::SampleFormat::I8 => run::<i8>(&device, &config.into()).unwrap(),
cpal::SampleFormat::I16 => run::<i16>(&device, &config.into()).unwrap(),
// cpal::SampleFormat::I24 => run::<I24>(&device, &config.into()).unwrap(),
cpal::SampleFormat::I32 => run::<i32>(&device, &config.into()).unwrap(),
// cpal::SampleFormat::I48 => run::<I48>(&device, &config.into()).unwrap(),
cpal::SampleFormat::I64 => run::<i64>(&device, &config.into()).unwrap(),
cpal::SampleFormat::U8 => run::<u8>(&device, &config.into()).unwrap(),
cpal::SampleFormat::U16 => run::<u16>(&device, &config.into()).unwrap(),
// cpal::SampleFormat::U24 => run::<U24>(&device, &config.into()).unwrap(),
cpal::SampleFormat::U32 => run::<u32>(&device, &config.into()).unwrap(),
// cpal::SampleFormat::U48 => run::<U48>(&device, &config.into()).unwrap(),
cpal::SampleFormat::U64 => run::<u64>(&device, &config.into()).unwrap(),
cpal::SampleFormat::F32 => run::<f32>(&device, &config.into()).unwrap(),
cpal::SampleFormat::F64 => run::<f64>(&device, &config.into()).unwrap(),
sample_format => panic!("Unsupported sample format '{sample_format}'"),
}
}

fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyhow::Error>
where
T: cpal::Sample,
T: SizedSample + FromSample<f32>,
{
let sample_rate = config.sample_rate.0 as f32;
let channels = config.channels as usize;
Expand Down Expand Up @@ -54,10 +70,10 @@ where

fn write_data<T>(output: &mut [T], channels: usize, next_sample: &mut dyn FnMut() -> f32)
where
T: cpal::Sample,
T: Sample + FromSample<f32>,
{
for frame in output.chunks_mut(channels) {
let value: T = cpal::Sample::from::<f32>(&next_sample());
let value: T = T::from_sample(next_sample());
for sample in frame.iter_mut() {
*sample = value;
}
Expand Down
26 changes: 21 additions & 5 deletions examples/beep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ extern crate clap;
extern crate cpal;

use clap::arg;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
SizedSample,
};
use cpal::{FromSample, Sample};

#[derive(Debug)]
struct Opt {
Expand Down Expand Up @@ -84,15 +88,27 @@ fn main() -> anyhow::Result<()> {
println!("Default output config: {:?}", config);

match config.sample_format() {
cpal::SampleFormat::F32 => run::<f32>(&device, &config.into()),
cpal::SampleFormat::I8 => run::<i8>(&device, &config.into()),
cpal::SampleFormat::I16 => run::<i16>(&device, &config.into()),
// cpal::SampleFormat::I24 => run::<I24>(&device, &config.into()),
cpal::SampleFormat::I32 => run::<i32>(&device, &config.into()),
// cpal::SampleFormat::I48 => run::<I48>(&device, &config.into()),
cpal::SampleFormat::I64 => run::<i64>(&device, &config.into()),
cpal::SampleFormat::U8 => run::<u8>(&device, &config.into()),
cpal::SampleFormat::U16 => run::<u16>(&device, &config.into()),
// cpal::SampleFormat::U24 => run::<U24>(&device, &config.into()),
cpal::SampleFormat::U32 => run::<u32>(&device, &config.into()),
// cpal::SampleFormat::U48 => run::<U48>(&device, &config.into()),
cpal::SampleFormat::U64 => run::<u64>(&device, &config.into()),
cpal::SampleFormat::F32 => run::<f32>(&device, &config.into()),
cpal::SampleFormat::F64 => run::<f64>(&device, &config.into()),
sample_format => panic!("Unsupported sample format '{sample_format}'"),
}
}

pub fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyhow::Error>
where
T: cpal::Sample,
T: SizedSample + FromSample<f32>,
{
let sample_rate = config.sample_rate.0 as f32;
let channels = config.channels as usize;
Expand Down Expand Up @@ -122,10 +138,10 @@ where

fn write_data<T>(output: &mut [T], channels: usize, next_sample: &mut dyn FnMut() -> f32)
where
T: cpal::Sample,
T: Sample + FromSample<f32>,
{
for frame in output.chunks_mut(channels) {
let value: T = cpal::Sample::from::<f32>(&next_sample());
let value: T = T::from_sample(next_sample());
for sample in frame.iter_mut() {
*sample = value;
}
Expand Down
33 changes: 22 additions & 11 deletions examples/record_wav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern crate hound;

use clap::arg;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{FromSample, Sample};
use std::fs::File;
use std::io::BufWriter;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -112,21 +113,31 @@ fn main() -> Result<(), anyhow::Error> {
};

let stream = match config.sample_format() {
cpal::SampleFormat::F32 => device.build_input_stream(
cpal::SampleFormat::I8 => device.build_input_stream(
&config.into(),
move |data, _: &_| write_input_data::<f32, f32>(data, &writer_2),
move |data, _: &_| write_input_data::<i8, i8>(data, &writer_2),
err_fn,
)?,
cpal::SampleFormat::I16 => device.build_input_stream(
&config.into(),
move |data, _: &_| write_input_data::<i16, i16>(data, &writer_2),
err_fn,
)?,
cpal::SampleFormat::U16 => device.build_input_stream(
cpal::SampleFormat::I32 => device.build_input_stream(
&config.into(),
move |data, _: &_| write_input_data::<u16, i16>(data, &writer_2),
move |data, _: &_| write_input_data::<i32, i32>(data, &writer_2),
err_fn,
)?,
cpal::SampleFormat::F32 => device.build_input_stream(
&config.into(),
move |data, _: &_| write_input_data::<f32, f32>(data, &writer_2),
err_fn,
)?,
sample_format => {
return Err(anyhow::Error::msg(format!(
"Unsupported sample format '{sample_format}'"
)))
}
};

stream.play()?;
Expand All @@ -140,10 +151,10 @@ fn main() -> Result<(), anyhow::Error> {
}

fn sample_format(format: cpal::SampleFormat) -> hound::SampleFormat {
match format {
cpal::SampleFormat::U16 => hound::SampleFormat::Int,
cpal::SampleFormat::I16 => hound::SampleFormat::Int,
cpal::SampleFormat::F32 => hound::SampleFormat::Float,
if format.is_float() {
hound::SampleFormat::Float
} else {
hound::SampleFormat::Int
}
}

Expand All @@ -160,13 +171,13 @@ type WavWriterHandle = Arc<Mutex<Option<hound::WavWriter<BufWriter<File>>>>>;

fn write_input_data<T, U>(input: &[T], writer: &WavWriterHandle)
where
T: cpal::Sample,
U: cpal::Sample + hound::Sample,
T: Sample,
U: Sample + hound::Sample + FromSample<T>,
{
if let Ok(mut guard) = writer.try_lock() {
if let Some(writer) = guard.as_mut() {
for &sample in input.iter() {
let sample: U = cpal::Sample::from(&sample);
let sample: U = U::from_sample(sample);
writer.write_sample(sample).ok();
}
}
Expand Down
28 changes: 23 additions & 5 deletions examples/synth_tones.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ extern crate anyhow;
extern crate clap;
extern crate cpal;

use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
SizedSample,
};
use cpal::{FromSample, Sample};

fn main() -> anyhow::Result<()> {
let stream = stream_setup_for(sample_next)?;
Expand Down Expand Up @@ -43,9 +47,23 @@ where
let (_host, device, config) = host_device_setup()?;

match config.sample_format() {
cpal::SampleFormat::F32 => stream_make::<f32, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::I8 => stream_make::<i8, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::I16 => stream_make::<i16, _>(&device, &config.into(), on_sample),
// cpal::SampleFormat::I24 => stream_make::<I24, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::I32 => stream_make::<i32, _>(&device, &config.into(), on_sample),
// cpal::SampleFormat::I48 => stream_make::<I48, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::I64 => stream_make::<i64, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::U8 => stream_make::<u8, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::U16 => stream_make::<u16, _>(&device, &config.into(), on_sample),
// cpal::SampleFormat::U24 => stream_make::<U24, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::U32 => stream_make::<u32, _>(&device, &config.into(), on_sample),
// cpal::SampleFormat::U48 => stream_make::<U48, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::U64 => stream_make::<u64, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::F32 => stream_make::<f32, _>(&device, &config.into(), on_sample),
cpal::SampleFormat::F64 => stream_make::<f64, _>(&device, &config.into(), on_sample),
sample_format => Err(anyhow::Error::msg(format!(
"Unsupported sample format '{sample_format}'"
))),
}
}

Expand All @@ -70,7 +88,7 @@ pub fn stream_make<T, F>(
on_sample: F,
) -> Result<cpal::Stream, anyhow::Error>
where
T: cpal::Sample,
T: SizedSample + FromSample<f32>,
F: FnMut(&mut SampleRequestOptions) -> f32 + std::marker::Send + 'static + Copy,
{
let sample_rate = config.sample_rate.0 as f32;
Expand All @@ -96,11 +114,11 @@ where

fn on_window<T, F>(output: &mut [T], request: &mut SampleRequestOptions, mut on_sample: F)
where
T: cpal::Sample,
T: Sample + FromSample<f32>,
F: FnMut(&mut SampleRequestOptions) -> f32 + std::marker::Send + 'static,
{
for frame in output.chunks_mut(request.nchannels) {
let value: T = cpal::Sample::from::<f32>(&on_sample(request));
let value: T = T::from_sample(on_sample(request));
for sample in frame.iter_mut() {
*sample = value;
}
Expand Down
50 changes: 44 additions & 6 deletions src/host/alsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ impl Device {
let hw_params = alsa::pcm::HwParams::any(handle)?;

// TODO: check endianness
const FORMATS: [(SampleFormat, alsa::pcm::Format); 3] = [
//SND_PCM_FORMAT_S8,
//SND_PCM_FORMAT_U8,
const FORMATS: [(SampleFormat, alsa::pcm::Format); 8] = [
(SampleFormat::I8, alsa::pcm::Format::S8),
(SampleFormat::U8, alsa::pcm::Format::U8),
(SampleFormat::I16, alsa::pcm::Format::S16LE),
//SND_PCM_FORMAT_S16_BE,
(SampleFormat::U16, alsa::pcm::Format::U16LE),
Expand All @@ -323,13 +323,13 @@ impl Device {
//SND_PCM_FORMAT_S24_BE,
//SND_PCM_FORMAT_U24_LE,
//SND_PCM_FORMAT_U24_BE,
//SND_PCM_FORMAT_S32_LE,
(SampleFormat::I32, alsa::pcm::Format::S32LE),
//SND_PCM_FORMAT_S32_BE,
//SND_PCM_FORMAT_U32_LE,
(SampleFormat::U32, alsa::pcm::Format::U32LE),
//SND_PCM_FORMAT_U32_BE,
(SampleFormat::F32, alsa::pcm::Format::FloatLE),
//SND_PCM_FORMAT_FLOAT_BE,
//SND_PCM_FORMAT_FLOAT64_LE,
(SampleFormat::F64, alsa::pcm::Format::Float64LE),
//SND_PCM_FORMAT_FLOAT64_BE,
//SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
//SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
Expand Down Expand Up @@ -956,15 +956,53 @@ fn set_hw_params_from_format(

let sample_format = if cfg!(target_endian = "big") {
match sample_format {
SampleFormat::I8 => alsa::pcm::Format::S8,
SampleFormat::I16 => alsa::pcm::Format::S16BE,
// SampleFormat::I24 => alsa::pcm::Format::S24BE,
SampleFormat::I32 => alsa::pcm::Format::S32BE,
// SampleFormat::I48 => alsa::pcm::Format::S48BE,
// SampleFormat::I64 => alsa::pcm::Format::S64BE,
SampleFormat::U8 => alsa::pcm::Format::U8,
SampleFormat::U16 => alsa::pcm::Format::U16BE,
// SampleFormat::U24 => alsa::pcm::Format::U24BE,
SampleFormat::U32 => alsa::pcm::Format::U32BE,
// SampleFormat::U48 => alsa::pcm::Format::U48BE,
// SampleFormat::U64 => alsa::pcm::Format::U64BE,
SampleFormat::F32 => alsa::pcm::Format::FloatBE,
SampleFormat::F64 => alsa::pcm::Format::Float64BE,
sample_format => {
return Err(BackendSpecificError {
description: format!(
"Sample format '{}' is not supported by this backend",
sample_format
),
})
}
}
} else {
match sample_format {
SampleFormat::I8 => alsa::pcm::Format::S8,
SampleFormat::I16 => alsa::pcm::Format::S16LE,
// SampleFormat::I24 => alsa::pcm::Format::S24LE,
SampleFormat::I32 => alsa::pcm::Format::S32LE,
// SampleFormat::I48 => alsa::pcm::Format::S48LE,
// SampleFormat::I64 => alsa::pcm::Format::S64LE,
SampleFormat::U8 => alsa::pcm::Format::U8,
SampleFormat::U16 => alsa::pcm::Format::U16LE,
// SampleFormat::U24 => alsa::pcm::Format::U24LE,
SampleFormat::U32 => alsa::pcm::Format::U32LE,
// SampleFormat::U48 => alsa::pcm::Format::U48LE,
// SampleFormat::U64 => alsa::pcm::Format::U64LE,
SampleFormat::F32 => alsa::pcm::Format::FloatLE,
SampleFormat::F64 => alsa::pcm::Format::Float64LE,
sample_format => {
return Err(BackendSpecificError {
description: format!(
"Sample format '{}' is not supported by this backend",
sample_format
),
})
}
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/host/asio/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Device {
) -> Result<SupportedInputConfigs, SupportedStreamConfigsError> {
// Retrieve the default config for the total supported channels and supported sample
// format.
let mut f = match self.default_input_config() {
let f = match self.default_input_config() {
Err(_) => return Err(SupportedStreamConfigsError::DeviceNotAvailable),
Ok(f) => f,
};
Expand Down Expand Up @@ -98,7 +98,7 @@ impl Device {
) -> Result<SupportedOutputConfigs, SupportedStreamConfigsError> {
// Retrieve the default config for the total supported channels and supported sample
// format.
let mut f = match self.default_output_config() {
let f = match self.default_output_config() {
Err(_) => return Err(SupportedStreamConfigsError::DeviceNotAvailable),
Ok(f) => f,
};
Expand Down
2 changes: 1 addition & 1 deletion src/host/asio/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
extern crate asio_sys as sys;
extern crate parking_lot;

use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
use crate::{
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigsError,
};
use traits::{DeviceTrait, HostTrait, StreamTrait};

pub use self::device::{Device, Devices, SupportedInputConfigs, SupportedOutputConfigs};
pub use self::stream::Stream;
Expand Down
Loading

0 comments on commit d768244

Please sign in to comment.