Skip to content

Commit f679f3e

Browse files
committed
Merge pull request #40 from mitchmindtree/sample_format
Implement proper handling of AudioFormat in `set_render_callback`
2 parents 79c74df + 168b152 commit f679f3e

File tree

11 files changed

+745
-202
lines changed

11 files changed

+745
-202
lines changed

Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "coreaudio-rs"
4-
version = "0.4.0"
4+
version = "0.5.0"
55
authors = ["mitchmindtree <mitchell.nordine@gmail.com>", "yupferris <jake@fusetools.com>"]
66
description = "A friendly rust interface for Apple's CoreAudio API."
77
keywords = ["core", "audio", "unit", "osx", "ios"]
@@ -10,9 +10,8 @@ license = "MIT/Apache-2.0"
1010
repository = "https://github.com/RustAudio/coreaudio-rs.git"
1111
homepage = "https://github.com/RustAudio/coreaudio-rs"
1212

13-
14-
[dev-dependencies]
15-
num = "0.1.27"
13+
[lib]
14+
name = "coreaudio"
1615

1716
[dependencies]
1817
bitflags = "0.3.2"

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# coreaudio-rs [![Build Status](https://travis-ci.org/RustAudio/coreaudio-rs.svg?branch=master)](https://travis-ci.org/RustAudio/coreaudio-rs) [![Crates.io](https://img.shields.io/crates/v/coreaudio-rs.svg)](https://crates.io/crates/coreaudio-rs) [![Crates.io](https://img.shields.io/crates/l/coreaudio-rs.svg)](https://github.com/RustAudio/coreaudio-rs/blob/master/LICENSE-MIT)
22

3-
A friendly rust interface for Apple's CoreAudio API.
3+
A friendly rust interface for [Apple's Core Audio API](https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/CoreAudioEssentials/CoreAudioEssentials.html).
4+
5+
This crate aims to expose and wrap the functionality of the original C API in a zero-cost, safe, Rust-esque manner.
6+
7+
If you just want direct access to the unsafe bindings, use [coreaudio-sys](https://crates.io/crates/coreaudio-sys).
48

59
[Documentation](http://rustaudio.github.io/coreaudio-rs/coreaudio_rs)

examples/sine.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! A basic output stream example, using an Output AudioUnit to generate a sine wave.
22
3-
extern crate coreaudio_rs as coreaudio;
4-
extern crate num;
3+
extern crate coreaudio;
54

6-
use coreaudio::audio_unit::{AudioUnit, IOType};
7-
use num::Float;
5+
use coreaudio::audio_unit::{AudioUnit, IOType, SampleFormat};
6+
use coreaudio::audio_unit::render_callback::{self, data};
87
use std::f64::consts::PI;
98

109

@@ -22,26 +21,40 @@ impl Iterator for Iter {
2221

2322

2423
fn main() {
24+
run().unwrap()
25+
}
26+
27+
fn run() -> Result<(), coreaudio::Error> {
2528

2629
// 440hz sine wave generator.
2730
let mut samples = Iter { value: 0.0 }
2831
.map(|phase| (phase * PI * 2.0).sin() as f32 * 0.15);
2932

30-
// Construct an Output audio unit.
31-
let mut audio_unit = AudioUnit::new(IOType::HalOutput).unwrap();
33+
// Construct an Output audio unit that delivers audio to the default output device.
34+
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
3235

33-
// Pass the audio unit a callback for filling the buffer.
34-
audio_unit.set_render_callback(Some(Box::new(move |buffer, num_frames| {
35-
for frame in 0..num_frames {
36-
let sample = samples.next().unwrap();
37-
for channel in buffer.iter_mut() {
38-
channel[frame] = sample;
39-
}
40-
}
41-
Ok(())
42-
}))).ok();
36+
let stream_format = try!(audio_unit.stream_format());
37+
println!("{:#?}", &stream_format);
38+
39+
// For this example, our sine wave expects `f32` data.
40+
assert!(SampleFormat::F32 == stream_format.sample_format);
41+
42+
try!(audio_unit.set_render_callback(move |args| callback(args, &mut samples)));
43+
try!(audio_unit.start());
4344

44-
audio_unit.start().unwrap();
45+
std::thread::sleep_ms(3000);
4546

46-
::std::thread::sleep_ms(3000);
47+
Ok(())
48+
}
49+
50+
type Args<'a> = render_callback::Args<'a, data::NonInterleaved<'a, f32>>;
51+
fn callback<'a, I: Iterator<Item=f32>>(args: Args<'a>, samples: &mut I) -> Result<(), ()> {
52+
let Args { num_frames, mut data, .. } = args;
53+
for i in 0..num_frames {
54+
let sample = samples.next().unwrap();
55+
for channel in data.channels_mut() {
56+
channel[i] = sample;
57+
}
58+
}
59+
Ok(())
4760
}

src/audio_unit/audio_format.rs

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub enum AudioFormat {
1919
/// Linear PCM; a non-compressed audio data format with one frame per packet.
2020
///
2121
/// **Available** in OS X v10.0 and later.
22-
LinearPCM(Option<LinearPCMFlags>), // = 1819304813,
22+
LinearPCM(LinearPCMFlags), // = 1819304813,
2323
/// An AC-3 codec.
2424
///
2525
/// **Available** in OS X v10.2 and later.
@@ -28,27 +28,27 @@ pub enum AudioFormat {
2828
/// audio interface.
2929
///
3030
/// **Available** in OS X v10.2 and later.
31-
F60958AC3(Option<StandardFlags>), // = 1667326771,
31+
F60958AC3(StandardFlags), // = 1667326771,
3232
/// Apple's implementation of the IMA 4:1 ADPCM codec.
3333
///
3434
/// **Available** in OS X v10.2 and later.
3535
AppleIMA4, // = 1768775988,
3636
/// MPEG-4 AAC codec.
3737
///
3838
/// **Available** in OS X v10.2 and later.
39-
MPEG4AAC(Option<Mpeg4ObjectId>), // = 1633772320,
39+
MPEG4AAC(Mpeg4ObjectId), // = 1633772320,
4040
/// MPEG-4 CELP codec.
4141
///
4242
/// **Available** in OS X v10.2 and later.
43-
MPEG4CELP(Option<Mpeg4ObjectId>), // = 1667591280,
43+
MPEG4CELP(Mpeg4ObjectId), // = 1667591280,
4444
/// MPEG-4 HVXC codec.
4545
///
4646
/// **Available** in OS X v10.2 and later.
47-
MPEG4HVXC(Option<Mpeg4ObjectId>), // = 1752594531,
47+
MPEG4HVXC(Mpeg4ObjectId), // = 1752594531,
4848
/// MPEG-4 TwinVQ codec.
4949
///
5050
/// **Available** in OS X v10.2 and later.
51-
MPEG4TwinVQ(Option<Mpeg4ObjectId>), // = 1953986161,
51+
MPEG4TwinVQ(Mpeg4ObjectId), // = 1953986161,
5252
/// MACE 3:1.
5353
///
5454
/// **Available** in OS X v10.3 and later.
@@ -92,7 +92,7 @@ pub enum AudioFormat {
9292
/// A stream of IOAudioTimeStamp structures.
9393
///
9494
/// **Available** in OS X v10.2 and later.
95-
TimeCode(Option<AudioTimeStampFlags>), // = 1953066341,
95+
TimeCode(AudioTimeStampFlags), // = 1953066341,
9696
/// A stream of MIDIPacketList structures where the time stamps in the MIDIPacket structures
9797
/// are sample offsets in the stream. The `sample_rate` field in the **StreamFormat** structure
9898
/// is used to describe how time is passed in this kind of stream.
@@ -122,7 +122,7 @@ pub enum AudioFormat {
122122
/// Apple Lossless format.
123123
///
124124
/// **Available** in OS X v10.3 and later.
125-
AppleLossless, // = 1634492771,
125+
AppleLossless(AppleLosslessFlags), // = 1634492771,
126126
/// MPEG-4 High Efficiency AAC audio object.
127127
///
128128
/// **Available** in OS X v10.5 and later.
@@ -183,14 +183,14 @@ impl AudioFormat {
183183
/// Convert from the FFI C format and flags to a typesafe Rust enum representation.
184184
pub fn from_format_and_flag(format: libc::c_uint, flag: Option<u32>) -> Option<AudioFormat> {
185185
match (format, flag) {
186-
(1819304813, Some(i)) => Some(AudioFormat::LinearPCM(LinearPCMFlags::from_bits(i))),
186+
(1819304813, Some(i)) => Some(AudioFormat::LinearPCM(LinearPCMFlags::from_bits_truncate(i))),
187187
(1633889587, _) => Some(AudioFormat::AC3),
188-
(1667326771, Some(i)) => Some(AudioFormat::F60958AC3(StandardFlags::from_bits(i))),
188+
(1667326771, Some(i)) => Some(AudioFormat::F60958AC3(StandardFlags::from_bits_truncate(i))),
189189
(1768775988, _) => Some(AudioFormat::AppleIMA4),
190-
(1633772320, Some(i)) => Some(AudioFormat::MPEG4AAC(Mpeg4ObjectId::from_u32(i))),
191-
(1667591280, Some(i)) => Some(AudioFormat::MPEG4CELP(Mpeg4ObjectId::from_u32(i))),
192-
(1752594531, Some(i)) => Some(AudioFormat::MPEG4HVXC(Mpeg4ObjectId::from_u32(i))),
193-
(1953986161, Some(i)) => Some(AudioFormat::MPEG4TwinVQ(Mpeg4ObjectId::from_u32(i))),
190+
(1633772320, Some(i)) => Some(AudioFormat::MPEG4AAC(Mpeg4ObjectId::from_u32(i).expect("Unknown Mpeg4ObjectId"))),
191+
(1667591280, Some(i)) => Some(AudioFormat::MPEG4CELP(Mpeg4ObjectId::from_u32(i).expect("Unknown Mpeg4ObjectId"))),
192+
(1752594531, Some(i)) => Some(AudioFormat::MPEG4HVXC(Mpeg4ObjectId::from_u32(i).expect("Unknown Mpeg4ObjectId"))),
193+
(1953986161, Some(i)) => Some(AudioFormat::MPEG4TwinVQ(Mpeg4ObjectId::from_u32(i).expect("Unknown Mpeg4ObjectId"))),
194194
(1296122675, _) => Some(AudioFormat::MACE3),
195195
(1296122678, _) => Some(AudioFormat::MACE6),
196196
(1970037111, _) => Some(AudioFormat::ULaw),
@@ -201,10 +201,10 @@ impl AudioFormat {
201201
(778924081, _) => Some(AudioFormat::MPEGLayer1),
202202
(778924082, _) => Some(AudioFormat::MPEGLayer2),
203203
(778924083, _) => Some(AudioFormat::MPEGLayer3),
204-
(1953066341, Some(i)) => Some(AudioFormat::TimeCode(AudioTimeStampFlags::from_bits(i))),
204+
(1953066341, Some(i)) => Some(AudioFormat::TimeCode(AudioTimeStampFlags::from_bits_truncate(i))),
205205
(1835623529, _) => Some(AudioFormat::MIDIStream),
206206
(1634760307, _) => Some(AudioFormat::ParameterValueStream),
207-
(1634492771, _) => Some(AudioFormat::AppleLossless),
207+
(1634492771, Some(i)) => Some(AudioFormat::AppleLossless(AppleLosslessFlags::from_bits_truncate(i))),
208208
(1633772392, _) => Some(AudioFormat::MPEG4AAC_HE),
209209
(1633772396, _) => Some(AudioFormat::MPEG4AAC_LD),
210210
(1633772389, _) => Some(AudioFormat::MPEG4AAC_ELD),
@@ -226,14 +226,14 @@ impl AudioFormat {
226226
/// Convert from the Rust enum to the C format and flag.
227227
pub fn to_format_and_flag(&self) -> (libc::c_uint, Option<u32>) {
228228
match *self {
229-
AudioFormat::LinearPCM(flag) => (1819304813, flag.map(|flag| flag.bits())),
229+
AudioFormat::LinearPCM(flag) => (1819304813, Some(flag.bits())),
230230
AudioFormat::AC3 => (1633889587, None),
231-
AudioFormat::F60958AC3(flag) => (1667326771, flag.map(|flag| flag.bits())),
231+
AudioFormat::F60958AC3(flag) => (1667326771, Some(flag.bits())),
232232
AudioFormat::AppleIMA4 => (1768775988, None),
233-
AudioFormat::MPEG4AAC(flag) => (1633772320, flag.map(|flag| flag as u32)),
234-
AudioFormat::MPEG4CELP(flag) => (1667591280, flag.map(|flag| flag as u32)),
235-
AudioFormat::MPEG4HVXC(flag) => (1752594531, flag.map(|flag| flag as u32)),
236-
AudioFormat::MPEG4TwinVQ(flag) => (1953986161, flag.map(|flag| flag as u32)),
233+
AudioFormat::MPEG4AAC(flag) => (1633772320, Some(flag as u32)),
234+
AudioFormat::MPEG4CELP(flag) => (1667591280, Some(flag as u32)),
235+
AudioFormat::MPEG4HVXC(flag) => (1752594531, Some(flag as u32)),
236+
AudioFormat::MPEG4TwinVQ(flag) => (1953986161, Some(flag as u32)),
237237
AudioFormat::MACE3 => (1296122675, None),
238238
AudioFormat::MACE6 => (1296122678, None),
239239
AudioFormat::ULaw => (1970037111, None),
@@ -244,10 +244,10 @@ impl AudioFormat {
244244
AudioFormat::MPEGLayer1 => (778924081, None),
245245
AudioFormat::MPEGLayer2 => (778924082, None),
246246
AudioFormat::MPEGLayer3 => (778924083, None),
247-
AudioFormat::TimeCode(flag) => (1953066341, flag.map(|flag| flag.bits())),
247+
AudioFormat::TimeCode(flag) => (1953066341, Some(flag.bits())),
248248
AudioFormat::MIDIStream => (1835623529, None),
249249
AudioFormat::ParameterValueStream => (1634760307, None),
250-
AudioFormat::AppleLossless => (1634492771, None),
250+
AudioFormat::AppleLossless(flag) => (1634492771, Some(flag.bits())),
251251
AudioFormat::MPEG4AAC_HE => (1633772392, None),
252252
AudioFormat::MPEG4AAC_LD => (1633772396, None),
253253
AudioFormat::MPEG4AAC_ELD => (1633772389, None),
@@ -312,10 +312,6 @@ pub mod standard_flags {
312312
/// Clear if the samples for each frame are laid out contiguously and the frames laid out
313313
/// end to end.
314314
///
315-
/// In the original API, this flag affects the use of AudioStreamBasicDescription and
316-
/// AudioBufferList structures, however in this Rust implementation we aim to make this
317-
/// behaviour type safe so that you need not worry about this.
318-
///
319315
/// **Available** in OS X v10.2 and later.
320316
const IS_NON_INTERLEAVED = 32,
321317
/// Set to indicate when a format is nonmixable.
@@ -501,4 +497,3 @@ pub mod audio_time_stamp_flags {
501497
}
502498
}
503499
}
504-

0 commit comments

Comments
 (0)