Skip to content

Commit 1bdf9c4

Browse files
Merge pull request #59 from mitchmindtree/input
Add support for AudioUnits with input streams
2 parents ff0942c + d03ad51 commit 1bdf9c4

File tree

4 files changed

+324
-46
lines changed

4 files changed

+324
-46
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "coreaudio-rs"
3-
version = "0.8.1"
3+
version = "0.9.0"
44
authors = ["mitchmindtree <mitchell.nordine@gmail.com>", "yupferris <jake@fusetools.com>"]
55
description = "A friendly rust interface for Apple's CoreAudio API."
66
keywords = ["core", "audio", "unit", "osx", "ios"]

examples/sine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn run() -> Result<(), coreaudio::Error> {
3333
// Construct an Output audio unit that delivers audio to the default output device.
3434
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
3535

36-
let stream_format = try!(audio_unit.stream_format());
36+
let stream_format = try!(audio_unit.output_stream_format());
3737
println!("{:#?}", &stream_format);
3838

3939
// For this example, our sine wave expects `f32` data.

src/audio_unit/mod.rs

Lines changed: 102 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ pub enum Element {
7777
/// Find the original Audio Unit Programming Guide [here](https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html).
7878
pub struct AudioUnit {
7979
instance: sys::AudioUnit,
80-
maybe_callback: Option<*mut render_callback::InputProcFnWrapper>
80+
maybe_render_callback: Option<*mut render_callback::InputProcFnWrapper>,
81+
maybe_input_callback: Option<InputCallback>,
82+
}
83+
84+
struct InputCallback {
85+
// The audio buffer list to which input data is rendered.
86+
buffer_list: *mut sys::AudioBufferList,
87+
callback: *mut render_callback::InputProcFnWrapper,
8188
}
8289

8390

@@ -158,7 +165,8 @@ impl AudioUnit {
158165
try_os_status!(sys::AudioUnitInitialize(instance));
159166
Ok(AudioUnit {
160167
instance: instance,
161-
maybe_callback: None
168+
maybe_render_callback: None,
169+
maybe_input_callback: None,
162170
})
163171
}
164172
}
@@ -183,17 +191,7 @@ impl AudioUnit {
183191
pub fn set_property<T>(&mut self, id: u32, scope: Scope, elem: Element, maybe_data: Option<&T>)
184192
-> Result<(), Error>
185193
{
186-
let (data_ptr, size) = maybe_data.map(|data| {
187-
let ptr = data as *const _ as *const c_void;
188-
let size = ::std::mem::size_of::<T>() as u32;
189-
(ptr, size)
190-
}).unwrap_or_else(|| (::std::ptr::null(), 0));
191-
let scope = scope as c_uint;
192-
let elem = elem as c_uint;
193-
unsafe {
194-
try_os_status!(sys::AudioUnitSetProperty(self.instance, id, scope, elem, data_ptr, size))
195-
}
196-
Ok(())
194+
set_property(self.instance, id, scope, elem, maybe_data)
197195
}
198196

199197
/// Gets the value of an **AudioUnit** property.
@@ -207,18 +205,7 @@ impl AudioUnit {
207205
/// - **scope**: The audio unit scope for the property.
208206
/// - **elem**: The audio unit element for the property.
209207
pub fn get_property<T>(&self, id: u32, scope: Scope, elem: Element) -> Result<T, Error> {
210-
let scope = scope as c_uint;
211-
let elem = elem as c_uint;
212-
let mut size = ::std::mem::size_of::<T>() as u32;
213-
unsafe {
214-
let mut data: T = ::std::mem::uninitialized();
215-
let data_ptr = &mut data as *mut _ as *mut c_void;
216-
let size_ptr = &mut size as *mut _;
217-
try_os_status!(
218-
sys::AudioUnitGetProperty(self.instance, id, scope, elem, data_ptr, size_ptr)
219-
);
220-
Ok(data)
221-
}
208+
get_property(self.instance, id, scope, elem)
222209
}
223210

224211
/// Starts an I/O **AudioUnit**, which in turn starts the audio unit processing graph that it is
@@ -267,19 +254,32 @@ impl AudioUnit {
267254
/// > - Mac input and output: Linear PCM with 32-bit floating point samples.
268255
/// > - Mac audio units and other audio processing: Noninterleaved linear PCM with 32-bit
269256
/// floating-point
270-
pub fn set_stream_format(&mut self, stream_format: StreamFormat) -> Result<(), Error> {
257+
pub fn set_stream_format(
258+
&mut self,
259+
stream_format: StreamFormat,
260+
scope: Scope,
261+
) -> Result<(), Error> {
271262
let id = sys::kAudioUnitProperty_StreamFormat;
272263
let asbd = stream_format.to_asbd();
273-
self.set_property(id, Scope::Input, Element::Output, Some(&asbd))
264+
self.set_property(id, scope, Element::Output, Some(&asbd))
274265
}
275266

276267
/// Return the current Stream Format for the AudioUnit.
277-
pub fn stream_format(&self) -> Result<StreamFormat, Error> {
268+
pub fn stream_format(&self, scope: Scope) -> Result<StreamFormat, Error> {
278269
let id = sys::kAudioUnitProperty_StreamFormat;
279-
let asbd = try!(self.get_property(id, Scope::Output, Element::Output));
270+
let asbd = try!(self.get_property(id, scope, Element::Output));
280271
StreamFormat::from_asbd(asbd)
281272
}
282273

274+
/// Return the current output Stream Format for the AudioUnit.
275+
pub fn output_stream_format(&self) -> Result<StreamFormat, Error> {
276+
self.stream_format(Scope::Output)
277+
}
278+
279+
/// Return the current input Stream Format for the AudioUnit.
280+
pub fn input_stream_format(&self) -> Result<StreamFormat, Error> {
281+
self.stream_format(Scope::Input)
282+
}
283283
}
284284

285285

@@ -299,6 +299,79 @@ impl Drop for AudioUnit {
299299
error::Error::from_os_status(sys::AudioUnitUninitialize(self.instance)).ok();
300300

301301
self.free_render_callback();
302+
self.free_input_callback();
302303
}
303304
}
304305
}
306+
307+
308+
/// Sets the value for some property of the **AudioUnit**.
309+
///
310+
/// To clear an audio unit property value, set the data paramater with `None::<()>`.
311+
///
312+
/// Clearing properties only works for those properties that do not have a default value.
313+
///
314+
/// For more on "properties" see [the reference](https://developer.apple.com/library/ios/documentation/AudioUnit/Reference/AudioUnitPropertiesReference/index.html#//apple_ref/doc/uid/TP40007288).
315+
///
316+
/// **Available** in iOS 2.0 and later.
317+
///
318+
/// Parameters
319+
/// ----------
320+
///
321+
/// - **au**: The AudioUnit instance.
322+
/// - **id**: The identifier of the property.
323+
/// - **scope**: The audio unit scope for the property.
324+
/// - **elem**: The audio unit element for the property.
325+
/// - **maybe_data**: The value that you want to apply to the property.
326+
pub fn set_property<T>(
327+
au: sys::AudioUnit,
328+
id: u32,
329+
scope: Scope,
330+
elem: Element,
331+
maybe_data: Option<&T>,
332+
) -> Result<(), Error>
333+
{
334+
let (data_ptr, size) = maybe_data.map(|data| {
335+
let ptr = data as *const _ as *const c_void;
336+
let size = ::std::mem::size_of::<T>() as u32;
337+
(ptr, size)
338+
}).unwrap_or_else(|| (::std::ptr::null(), 0));
339+
let scope = scope as c_uint;
340+
let elem = elem as c_uint;
341+
unsafe {
342+
try_os_status!(sys::AudioUnitSetProperty(au, id, scope, elem, data_ptr, size))
343+
}
344+
Ok(())
345+
}
346+
347+
/// Gets the value of an **AudioUnit** property.
348+
///
349+
/// **Available** in iOS 2.0 and later.
350+
///
351+
/// Parameters
352+
/// ----------
353+
///
354+
/// - **au**: The AudioUnit instance.
355+
/// - **id**: The identifier of the property.
356+
/// - **scope**: The audio unit scope for the property.
357+
/// - **elem**: The audio unit element for the property.
358+
pub fn get_property<T>(
359+
au: sys::AudioUnit,
360+
id: u32,
361+
scope: Scope,
362+
elem: Element,
363+
) -> Result<T, Error>
364+
{
365+
let scope = scope as c_uint;
366+
let elem = elem as c_uint;
367+
let mut size = ::std::mem::size_of::<T>() as u32;
368+
unsafe {
369+
let mut data: T = ::std::mem::uninitialized();
370+
let data_ptr = &mut data as *mut _ as *mut c_void;
371+
let size_ptr = &mut size as *mut _;
372+
try_os_status!(
373+
sys::AudioUnitGetProperty(au, id, scope, elem, data_ptr, size_ptr)
374+
);
375+
Ok(data)
376+
}
377+
}

0 commit comments

Comments
 (0)