diff --git a/Cargo.toml b/Cargo.toml index e64a073fd..ec279fb36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,10 @@ homepage = "https://github.com/RustAudio/coreaudio-rs" [lib] name = "coreaudio" +[[bin]] +name = "example-sine" +path = "examples/sine.rs" + [features] default = ["audio_toolbox", "audio_unit", "core_audio", "open_al", "core_midi"] audio_toolbox = ["coreaudio-sys/audio_toolbox"] diff --git a/examples/sine.rs b/examples/sine.rs index f6aac6d67..6d1939f5e 100644 --- a/examples/sine.rs +++ b/examples/sine.rs @@ -31,26 +31,26 @@ fn run() -> Result<(), coreaudio::Error> { .map(|phase| (phase * PI * 2.0).sin() as f32 * 0.15); // Construct an Output audio unit that delivers audio to the default output device. - let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput)); + let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?; - let stream_format = try!(audio_unit.output_stream_format()); + let stream_format = audio_unit.output_stream_format(0)?; println!("{:#?}", &stream_format); // For this example, our sine wave expects `f32` data. - assert!(SampleFormat::F32 == stream_format.sample_format); + assert_eq!(SampleFormat::F32, stream_format.sample_format); type Args = render_callback::Args>; - try!(audio_unit.set_render_callback(move |args| { + audio_unit.set_render_callback(move |args| { let Args { num_frames, mut data, .. } = args; for i in 0..num_frames { let sample = samples.next().unwrap(); - for channel in data.channels_mut() { + for mut channel in data.channels_mut() { channel[i] = sample; } } Ok(()) - })); - try!(audio_unit.start()); + }, 0)?; + audio_unit.start()?; std::thread::sleep(std::time::Duration::from_millis(3000)); diff --git a/src/audio_unit/mod.rs b/src/audio_unit/mod.rs index 9e4459bbe..43826380b 100644 --- a/src/audio_unit/mod.rs +++ b/src/audio_unit/mod.rs @@ -62,14 +62,9 @@ pub enum Scope { LayerItem = 7, } -/// Represents the **Input** and **Output** **Element**s. -/// -/// These are used when specifying which **Element** we're setting the properties of. -#[derive(Copy, Clone, Debug)] -pub enum Element { - Output = 0, - Input = 1, -} +/// These are used when specifying which **Element** (bus) we're setting the properties of. +/// [The anatomy of an AudioUnit](https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW11) +type Element = u32; /// A rust representation of the sys::AudioUnit, including a pointer to the current rendering callback. @@ -229,15 +224,15 @@ impl AudioUnit { /// Set the **AudioUnit**'s sample rate. /// /// **Available** in iOS 2.0 and later. - pub fn set_sample_rate(&mut self, sample_rate: f64) -> Result<(), Error> { + pub fn set_sample_rate(&mut self, element: u32, sample_rate: f64) -> Result<(), Error> { let id = sys::kAudioUnitProperty_SampleRate; - self.set_property(id, Scope::Input, Element::Output, Some(&sample_rate)) + self.set_property(id, Scope::Input, element, Some(&sample_rate)) } /// Get the **AudioUnit**'s sample rate. - pub fn sample_rate(&self) -> Result { + pub fn sample_rate(&self, element: Element) -> Result { let id = sys::kAudioUnitProperty_SampleRate; - self.get_property(id, Scope::Input, Element::Output) + self.get_property(id, Scope::Input, element) } /// Sets the current **StreamFormat** for the AudioUnit. @@ -258,27 +253,28 @@ impl AudioUnit { &mut self, stream_format: StreamFormat, scope: Scope, + element: Element, ) -> Result<(), Error> { let id = sys::kAudioUnitProperty_StreamFormat; let asbd = stream_format.to_asbd(); - self.set_property(id, scope, Element::Output, Some(&asbd)) + self.set_property(id, scope, element, Some(&asbd)) } /// Return the current Stream Format for the AudioUnit. - pub fn stream_format(&self, scope: Scope) -> Result { + pub fn stream_format(&self, scope: Scope, element: Element) -> Result { let id = sys::kAudioUnitProperty_StreamFormat; - let asbd = try!(self.get_property(id, scope, Element::Output)); + let asbd = self.get_property(id, scope, element)?; StreamFormat::from_asbd(asbd) } /// Return the current output Stream Format for the AudioUnit. - pub fn output_stream_format(&self) -> Result { - self.stream_format(Scope::Output) + pub fn output_stream_format(&self, element: Element) -> Result { + self.stream_format(Scope::Output, element) } /// Return the current input Stream Format for the AudioUnit. - pub fn input_stream_format(&self) -> Result { - self.stream_format(Scope::Input) + pub fn input_stream_format(&self, element: Element) -> Result { + self.stream_format(Scope::Input, element) } } diff --git a/src/audio_unit/render_callback.rs b/src/audio_unit/render_callback.rs index e0c5668a7..cfb82d8ef 100644 --- a/src/audio_unit/render_callback.rs +++ b/src/audio_unit/render_callback.rs @@ -390,7 +390,7 @@ pub mod action_flags { impl AudioUnit { /// Pass a render callback (aka "Input Procedure") to the **AudioUnit**. - pub fn set_render_callback(&mut self, mut f: F) -> Result<(), Error> + pub fn set_render_callback(&mut self, mut f: F, element: Element) -> Result<(), Error> where F: FnMut(Args) -> Result<(), ()> + 'static, D: Data, @@ -398,7 +398,7 @@ impl AudioUnit { // First, we'll retrieve the stream format so that we can ensure that the given callback // format matches the audio unit's format. let id = sys::kAudioUnitProperty_StreamFormat; - let asbd = try!(self.get_property(id, Scope::Output, Element::Output)); + let asbd = self.get_property(id, Scope::Output, element)?; let stream_format = super::StreamFormat::from_asbd(asbd)?; // If the stream format does not match, return an error indicating this. @@ -453,7 +453,7 @@ impl AudioUnit { self.set_property( sys::kAudioUnitProperty_SetRenderCallback, Scope::Input, - Element::Output, + element, Some(&render_callback), )?; @@ -463,7 +463,7 @@ impl AudioUnit { } /// Pass an input callback (aka "Input Procedure") to the **AudioUnit**. - pub fn set_input_callback(&mut self, mut f: F) -> Result<(), Error> + pub fn set_input_callback(&mut self, mut f: F, element: Element) -> Result<(), Error> where F: FnMut(Args) -> Result<(), ()> + 'static, D: Data, @@ -471,7 +471,7 @@ impl AudioUnit { // First, we'll retrieve the stream format so that we can ensure that the given callback // format matches the audio unit's format. let id = sys::kAudioUnitProperty_StreamFormat; - let asbd = self.get_property(id, Scope::Input, Element::Input)?; + let asbd = self.get_property(id, Scope::Input, element)?; let stream_format = super::StreamFormat::from_asbd(asbd)?; // If the stream format does not match, return an error indicating this. @@ -483,7 +483,7 @@ impl AudioUnit { // // First, get the current buffer size for pre-allocating the `AudioBuffer`s. let id = sys::kAudioDevicePropertyBufferFrameSize; - let mut buffer_frame_size: u32 = self.get_property(id, Scope::Global, Element::Output)?; + let mut buffer_frame_size: u32 = self.get_property(id, Scope::Global, 0)?; // Always 0 bus for Scope::Global let mut data: Vec = vec![]; let sample_bytes = stream_format.sample_format.size_in_bytes(); let n_channels = stream_format.channels_per_frame; @@ -525,7 +525,7 @@ impl AudioUnit { unsafe { // Retrieve the up-to-date stream format. let id = sys::kAudioUnitProperty_StreamFormat; - let asbd = match super::get_property(audio_unit, id, Scope::Input, Element::Output) { + let asbd = match super::get_property(audio_unit, id, Scope::Input, in_bus_number) { Err(err) => return err.to_os_status(), Ok(asbd) => asbd, }; @@ -607,7 +607,7 @@ impl AudioUnit { self.set_property( sys::kAudioOutputUnitProperty_SetInputCallback, Scope::Global, - Element::Output, + element, Some(&render_callback), )?;