Skip to content

Commit b74e926

Browse files
committed
Change Element datatype to be u32.
As i understand it, an audio unit can have several inputs and several outputs, and an 'element' is just an index of one of those. (https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html). Therefore, it's should be possible, for example, to have several render callbacks for a single audio unit. An example would be a crossfade unit with 2 inputs: it'll have 2 elements in its input scope and 1 in output scope, and it'll require either two render callbacks (one for each input), or two upstream audio units. This changes Element to be just a number and adds explicit element parameter to all the places where it hasn't been present before (i.e. setting callbacks and input/output stream formats). This relates to the issue #60 and PR #47.
1 parent 08c8b79 commit b74e926

File tree

4 files changed

+34
-34
lines changed

4 files changed

+34
-34
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ homepage = "https://github.com/RustAudio/coreaudio-rs"
1212
[lib]
1313
name = "coreaudio"
1414

15+
[[bin]]
16+
name = "example-sine"
17+
path = "examples/sine.rs"
18+
1519
[features]
1620
default = ["audio_toolbox", "audio_unit", "core_audio", "open_al", "core_midi"]
1721
audio_toolbox = ["coreaudio-sys/audio_toolbox"]

examples/sine.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,26 @@ fn run() -> Result<(), coreaudio::Error> {
3131
.map(|phase| (phase * PI * 2.0).sin() as f32 * 0.15);
3232

3333
// Construct an Output audio unit that delivers audio to the default output device.
34-
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
34+
let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?;
3535

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

3939
// For this example, our sine wave expects `f32` data.
40-
assert!(SampleFormat::F32 == stream_format.sample_format);
40+
assert_eq!(SampleFormat::F32, stream_format.sample_format);
4141

4242
type Args = render_callback::Args<data::NonInterleaved<f32>>;
43-
try!(audio_unit.set_render_callback(move |args| {
43+
audio_unit.set_render_callback(move |args| {
4444
let Args { num_frames, mut data, .. } = args;
4545
for i in 0..num_frames {
4646
let sample = samples.next().unwrap();
47-
for channel in data.channels_mut() {
47+
for mut channel in data.channels_mut() {
4848
channel[i] = sample;
4949
}
5050
}
5151
Ok(())
52-
}));
53-
try!(audio_unit.start());
52+
}, 0)?;
53+
audio_unit.start()?;
5454

5555
std::thread::sleep(std::time::Duration::from_millis(3000));
5656

src/audio_unit/mod.rs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,9 @@ pub enum Scope {
6262
LayerItem = 7,
6363
}
6464

65-
/// Represents the **Input** and **Output** **Element**s.
66-
///
67-
/// These are used when specifying which **Element** we're setting the properties of.
68-
#[derive(Copy, Clone, Debug)]
69-
pub enum Element {
70-
Output = 0,
71-
Input = 1,
72-
}
65+
/// These are used when specifying which **Element** (bus) we're setting the properties of.
66+
/// [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)
67+
type Element = u32;
7368

7469

7570
/// A rust representation of the sys::AudioUnit, including a pointer to the current rendering callback.
@@ -229,15 +224,15 @@ impl AudioUnit {
229224
/// Set the **AudioUnit**'s sample rate.
230225
///
231226
/// **Available** in iOS 2.0 and later.
232-
pub fn set_sample_rate(&mut self, sample_rate: f64) -> Result<(), Error> {
227+
pub fn set_sample_rate(&mut self, element: u32, sample_rate: f64) -> Result<(), Error> {
233228
let id = sys::kAudioUnitProperty_SampleRate;
234-
self.set_property(id, Scope::Input, Element::Output, Some(&sample_rate))
229+
self.set_property(id, Scope::Input, element, Some(&sample_rate))
235230
}
236231

237232
/// Get the **AudioUnit**'s sample rate.
238-
pub fn sample_rate(&self) -> Result<f64, Error> {
233+
pub fn sample_rate(&self, element: Element) -> Result<f64, Error> {
239234
let id = sys::kAudioUnitProperty_SampleRate;
240-
self.get_property(id, Scope::Input, Element::Output)
235+
self.get_property(id, Scope::Input, element)
241236
}
242237

243238
/// Sets the current **StreamFormat** for the AudioUnit.
@@ -258,27 +253,28 @@ impl AudioUnit {
258253
&mut self,
259254
stream_format: StreamFormat,
260255
scope: Scope,
256+
element: Element,
261257
) -> Result<(), Error> {
262258
let id = sys::kAudioUnitProperty_StreamFormat;
263259
let asbd = stream_format.to_asbd();
264-
self.set_property(id, scope, Element::Output, Some(&asbd))
260+
self.set_property(id, scope, element, Some(&asbd))
265261
}
266262

267263
/// Return the current Stream Format for the AudioUnit.
268-
pub fn stream_format(&self, scope: Scope) -> Result<StreamFormat, Error> {
264+
pub fn stream_format(&self, scope: Scope, element: Element) -> Result<StreamFormat, Error> {
269265
let id = sys::kAudioUnitProperty_StreamFormat;
270-
let asbd = try!(self.get_property(id, scope, Element::Output));
266+
let asbd = self.get_property(id, scope, element)?;
271267
StreamFormat::from_asbd(asbd)
272268
}
273269

274270
/// 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)
271+
pub fn output_stream_format(&self, element: Element) -> Result<StreamFormat, Error> {
272+
self.stream_format(Scope::Output, element)
277273
}
278274

279275
/// 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)
276+
pub fn input_stream_format(&self, element: Element) -> Result<StreamFormat, Error> {
277+
self.stream_format(Scope::Input, element)
282278
}
283279
}
284280

src/audio_unit/render_callback.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -390,15 +390,15 @@ pub mod action_flags {
390390

391391
impl AudioUnit {
392392
/// Pass a render callback (aka "Input Procedure") to the **AudioUnit**.
393-
pub fn set_render_callback<F, D>(&mut self, mut f: F) -> Result<(), Error>
393+
pub fn set_render_callback<F, D>(&mut self, mut f: F, element: Element) -> Result<(), Error>
394394
where
395395
F: FnMut(Args<D>) -> Result<(), ()> + 'static,
396396
D: Data,
397397
{
398398
// First, we'll retrieve the stream format so that we can ensure that the given callback
399399
// format matches the audio unit's format.
400400
let id = sys::kAudioUnitProperty_StreamFormat;
401-
let asbd = try!(self.get_property(id, Scope::Output, Element::Output));
401+
let asbd = self.get_property(id, Scope::Output, element)?;
402402
let stream_format = super::StreamFormat::from_asbd(asbd)?;
403403

404404
// If the stream format does not match, return an error indicating this.
@@ -453,7 +453,7 @@ impl AudioUnit {
453453
self.set_property(
454454
sys::kAudioUnitProperty_SetRenderCallback,
455455
Scope::Input,
456-
Element::Output,
456+
element,
457457
Some(&render_callback),
458458
)?;
459459

@@ -463,15 +463,15 @@ impl AudioUnit {
463463
}
464464

465465
/// Pass an input callback (aka "Input Procedure") to the **AudioUnit**.
466-
pub fn set_input_callback<F, D>(&mut self, mut f: F) -> Result<(), Error>
466+
pub fn set_input_callback<F, D>(&mut self, mut f: F, element: Element) -> Result<(), Error>
467467
where
468468
F: FnMut(Args<D>) -> Result<(), ()> + 'static,
469469
D: Data,
470470
{
471471
// First, we'll retrieve the stream format so that we can ensure that the given callback
472472
// format matches the audio unit's format.
473473
let id = sys::kAudioUnitProperty_StreamFormat;
474-
let asbd = self.get_property(id, Scope::Input, Element::Input)?;
474+
let asbd = self.get_property(id, Scope::Input, element)?;
475475
let stream_format = super::StreamFormat::from_asbd(asbd)?;
476476

477477
// If the stream format does not match, return an error indicating this.
@@ -483,7 +483,7 @@ impl AudioUnit {
483483
//
484484
// First, get the current buffer size for pre-allocating the `AudioBuffer`s.
485485
let id = sys::kAudioDevicePropertyBufferFrameSize;
486-
let mut buffer_frame_size: u32 = self.get_property(id, Scope::Global, Element::Output)?;
486+
let mut buffer_frame_size: u32 = self.get_property(id, Scope::Global, 0)?; // Always 0 bus for Scope::Global
487487
let mut data: Vec<u8> = vec![];
488488
let sample_bytes = stream_format.sample_format.size_in_bytes();
489489
let n_channels = stream_format.channels_per_frame;
@@ -525,7 +525,7 @@ impl AudioUnit {
525525
unsafe {
526526
// Retrieve the up-to-date stream format.
527527
let id = sys::kAudioUnitProperty_StreamFormat;
528-
let asbd = match super::get_property(audio_unit, id, Scope::Input, Element::Output) {
528+
let asbd = match super::get_property(audio_unit, id, Scope::Input, in_bus_number) {
529529
Err(err) => return err.to_os_status(),
530530
Ok(asbd) => asbd,
531531
};
@@ -607,7 +607,7 @@ impl AudioUnit {
607607
self.set_property(
608608
sys::kAudioOutputUnitProperty_SetInputCallback,
609609
Scope::Global,
610-
Element::Output,
610+
element,
611611
Some(&render_callback),
612612
)?;
613613

0 commit comments

Comments
 (0)