Mercurial > core / rust/lib/audio/src/lib.rs
changeset 698: |
96958d3eb5b0 |
parent: |
920ded613f45
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
8 pub use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; 9 pub use hound::{Sample, SampleFormat, WavReader, WavSpec}; 11 /// convert between `cpal::SampleFormat` and `hound::SampleFormat` 12 pub fn sample_format(format: cpal::SampleFormat) -> hound::SampleFormat { 14 cpal::SampleFormat::U16 => hound::SampleFormat::Int, 15 cpal::SampleFormat::I16 => hound::SampleFormat::Int, 16 cpal::SampleFormat::F32 => hound::SampleFormat::Float, 20 /// Return `hound::WavSpec` from `cpal::SupportedStreamconfig` 21 pub fn wav_spec_from_config( 22 config: &cpal::SupportedStreamConfig, 25 channels: config.channels() as _, 26 sample_rate: config.sample_rate().0 as _, 27 bits_per_sample: (config.sample_format().sample_size() * 8) as _, 28 sample_format: sample_format(config.sample_format()), 32 /// A thread-safe handle to the WavWriter file 33 type WavWriterHandle = Arc<Mutex<Option<hound::WavWriter<BufWriter<File>>>>>; 35 /// Write incoming data to an owned `WavWriterHandle` 36 pub fn write_input_data<T, U>(input: &[T], writer: &WavWriterHandle) 39 U: cpal::Sample + hound::Sample, 41 if let Ok(mut guard) = writer.try_lock() { 42 if let Some(writer) = guard.as_mut() { 43 for &sample in input.iter() { 44 let sample: U = cpal::Sample::from(&sample); 45 writer.write_sample(sample).ok(); 51 /// Compute the RMS of either integers or float samples. 52 pub fn compute_rms<S, R>(reader: &mut WavReader<R>) -> f64 58 let sqr_sum = reader.samples::<S>().fold(0.0, |sqr_sum, s| { 59 let sample = f64::from(s.unwrap()); 60 sqr_sum + sample * sample 62 (sqr_sum / reader.len() as f64).sqrt() 65 /// Run a max volume sinusoid through the default audio output device 66 pub fn run<T: cpal::Sample>( 67 device: &cpal::Device, 68 config: &cpal::StreamConfig, 69 ) -> Result<(), Box<dyn std::error::Error + 'static>> { 70 let sample_rate = config.sample_rate.0 as f32; 71 let channels = config.channels as usize; 73 // Produce a sinusoid of maximum amplitude. 74 let mut sample_clock = 0f32; 75 let mut next_value = move || { 76 sample_clock = (sample_clock + 1.0) % sample_rate; 77 (sample_clock * 440.0 * 2.0 * std::f32::consts::PI / sample_rate).sin() 80 let err_fn = |err| eprintln!("an error occurred on stream: {}", err); 82 let stream = device.build_output_stream( 84 move |data: &mut [T], _: &cpal::OutputCallbackInfo| { 85 write_data(data, channels, &mut next_value) 91 std::thread::sleep(std::time::Duration::from_millis(1000)); 96 /// write a stream of data 100 next_sample: &mut dyn FnMut() -> f32, 104 for frame in output.chunks_mut(channels) { 105 let value: T = cpal::Sample::from::<f32>(&next_sample()); 106 for sample in frame.iter_mut() { 114 fn default_device() { 115 use cpal::traits::HostTrait; 116 let device = cpal::default_host().default_output_device(); 117 assert!(&device.is_some()); 118 let config = device.unwrap().default_output_config(); 119 assert!(&config.is_ok());