AudioUnit

Struct AudioUnit 

Source
pub struct AudioUnit { /* private fields */ }
Expand description

A rust representation of the objc2_audio_toolbox::AudioUnit, including a pointer to the current rendering callback.

Find the original Audio Unit Programming Guide here.

Implementations§

Source§

impl AudioUnit

Source

pub fn set_render_callback<F, D>(&mut self, f: F) -> Result<(), Error>
where F: FnMut(Args<D>) -> Result<(), ()> + 'static, D: Data,

Pass a render callback (aka “Input Procedure”) to the AudioUnit.

Examples found in repository?
examples/sine.rs (lines 54-67)
36fn main() -> Result<(), coreaudio::Error> {
37    let frequency_hz = 440.;
38    let volume = 0.15;
39    let mut samples = SineWaveGenerator::new(frequency_hz, volume);
40
41    // Construct an Output audio unit that delivers audio to the default output device.
42    let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?;
43
44    // Read the input format. This is counterintuitive, but it's the format used when sending
45    // audio data to the AudioUnit representing the output device. This is separate from the
46    // format the AudioUnit later uses to send the data to the hardware device.
47    let stream_format = audio_unit.output_stream_format()?;
48    println!("{:#?}", &stream_format);
49
50    // For this example, our sine wave expects `f32` data.
51    assert!(SampleFormat::F32 == stream_format.sample_format);
52
53    type Args = render_callback::Args<data::NonInterleaved<f32>>;
54    audio_unit.set_render_callback(move |args| {
55        let Args {
56            num_frames,
57            mut data,
58            ..
59        } = args;
60        for i in 0..num_frames {
61            let sample = samples.next().unwrap();
62            for channel in data.channels_mut() {
63                channel[i] = sample;
64            }
65        }
66        Ok(())
67    })?;
68    audio_unit.start()?;
69
70    std::thread::sleep(std::time::Duration::from_millis(3000));
71
72    Ok(())
73}
More examples
Hide additional examples
examples/feedback.rs (lines 109-133)
22fn main() -> Result<(), coreaudio::Error> {
23    let mut input_audio_unit =
24        audio_unit_from_device_id(get_default_device_id(true).unwrap(), true)?;
25    let mut output_audio_unit =
26        audio_unit_from_device_id(get_default_device_id(false).unwrap(), false)?;
27
28    let format_flag = match SAMPLE_FORMAT {
29        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT,
30        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
31            LinearPcmFlags::IS_SIGNED_INTEGER
32        }
33        _ => {
34            unimplemented!("Other formats are not implemented for this example.");
35        }
36    };
37
38    // Using IS_NON_INTERLEAVED everywhere because data::Interleaved is commented out / not implemented
39    let in_stream_format = StreamFormat {
40        sample_rate: SAMPLE_RATE,
41        sample_format: SAMPLE_FORMAT,
42        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
43        // audio_unit.set_input_callback is hardcoded to 1 buffer, and when using non_interleaved
44        // we are forced to 1 channel
45        channels: 1,
46    };
47
48    let out_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
52        // you can change this to 1
53        channels: 2,
54    };
55
56    println!("input={:#?}", &in_stream_format);
57    println!("output={:#?}", &out_stream_format);
58    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
59    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
60
61    let id = kAudioUnitProperty_StreamFormat;
62    let asbd = in_stream_format.to_asbd();
63    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
64
65    let asbd = out_stream_format.to_asbd();
66    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
67
68    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
69    let producer_left = buffer_left.clone();
70    let consumer_left = buffer_left.clone();
71    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
72    let producer_right = buffer_right.clone();
73    let consumer_right = buffer_right.clone();
74
75    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
76    for buffer in vec![buffer_left, buffer_right] {
77        let mut buffer = buffer.lock().unwrap();
78        for _ in 0..(out_stream_format.sample_rate as i32) {
79            buffer.push_back(0 as S);
80        }
81    }
82
83    type Args = render_callback::Args<data::NonInterleaved<S>>;
84
85    input_audio_unit.set_input_callback(move |args| {
86        let Args {
87            num_frames,
88            mut data,
89            ..
90        } = args;
91        // Print the number of frames the callback provides.
92        // Included to aid understanding, don't use println and other things
93        // that may block for an unknown amount of time inside the callback
94        // of a real application.
95        println!("input cb {} frames", num_frames);
96        let buffer_left = producer_left.lock().unwrap();
97        let buffer_right = producer_right.lock().unwrap();
98        let mut buffers = vec![buffer_left, buffer_right];
99        for i in 0..num_frames {
100            for (ch, channel) in data.channels_mut().enumerate() {
101                let value: S = channel[i];
102                buffers[ch].push_back(value);
103            }
104        }
105        Ok(())
106    })?;
107    input_audio_unit.start()?;
108
109    output_audio_unit.set_render_callback(move |args: Args| {
110        let Args {
111            num_frames,
112            mut data,
113            ..
114        } = args;
115        // Print the number of frames the callback requests.
116        // Included to aid understanding, don't use println and other things
117        // that may block for an unknown amount of time inside the callback
118        // of a real application.
119        println!("output cb {} frames", num_frames);
120        let buffer_left = consumer_left.lock().unwrap();
121        let buffer_right = consumer_right.lock().unwrap();
122        let mut buffers = vec![buffer_left, buffer_right];
123        for i in 0..num_frames {
124            // Default other channels to copy value from first channel as a fallback
125            let zero: S = 0 as S;
126            let f: S = *buffers[0].front().unwrap_or(&zero);
127            for (ch, channel) in data.channels_mut().enumerate() {
128                let sample: S = buffers[ch].pop_front().unwrap_or(f);
129                channel[i] = sample;
130            }
131        }
132        Ok(())
133    })?;
134    output_audio_unit.start()?;
135
136    std::thread::sleep(std::time::Duration::from_millis(100000));
137
138    Ok(())
139}
examples/feedback_interleaved.rs (lines 121-140)
24fn main() -> Result<(), coreaudio::Error> {
25    let input_device_id = get_default_device_id(true).unwrap();
26    let output_device_id = get_default_device_id(false).unwrap();
27    println!(
28        "Input device: {}",
29        get_device_name(input_device_id).unwrap()
30    );
31    println!(
32        "Output device: {}",
33        get_device_name(output_device_id).unwrap()
34    );
35    let mut input_audio_unit = audio_unit_from_device_id(input_device_id, true)?;
36    let mut output_audio_unit = audio_unit_from_device_id(output_device_id, false)?;
37
38    let format_flag = match SAMPLE_FORMAT {
39        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
40        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
41            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
42        }
43        _ => {
44            unimplemented!("Please use one of the packed formats");
45        }
46    };
47
48    let in_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag,
52        channels: 2,
53    };
54
55    let out_stream_format = StreamFormat {
56        sample_rate: SAMPLE_RATE,
57        sample_format: SAMPLE_FORMAT,
58        flags: format_flag,
59        channels: 2,
60    };
61
62    println!("input={:#?}", &in_stream_format);
63    println!("output={:#?}", &out_stream_format);
64    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
65    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
66
67    let id = kAudioUnitProperty_StreamFormat;
68    let asbd = in_stream_format.to_asbd();
69    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
70
71    let asbd = out_stream_format.to_asbd();
72    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
73
74    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
75    let producer_left = buffer_left.clone();
76    let consumer_left = buffer_left.clone();
77    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
78    let producer_right = buffer_right.clone();
79    let consumer_right = buffer_right.clone();
80
81    // Register a rate listener for playback
82    let mut listener_pb = RateListener::new(output_device_id, None);
83    listener_pb.register()?;
84
85    // Register a rate listener for capture
86    let mut listener_cap = RateListener::new(input_device_id, None);
87    listener_cap.register()?;
88
89    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
90    for buffer in vec![buffer_left, buffer_right] {
91        let mut buffer = buffer.lock().unwrap();
92        for _ in 0..(out_stream_format.sample_rate as i32) {
93            buffer.push_back(0 as S);
94        }
95    }
96
97    type Args = render_callback::Args<data::Interleaved<S>>;
98
99    input_audio_unit.set_input_callback(move |args| {
100        let Args {
101            num_frames, data, ..
102        } = args;
103        // Print the number of frames the callback requests.
104        // Included to aid understanding, don't use println and other things
105        // that may block for an unknown amount of time inside the callback
106        // of a real application.
107        println!("input cb {} frames", num_frames);
108        let buffer_left = producer_left.lock().unwrap();
109        let buffer_right = producer_right.lock().unwrap();
110        let mut buffers = vec![buffer_left, buffer_right];
111        for i in 0..num_frames {
112            for channel in 0..2 {
113                let value: S = data.buffer[2 * i + channel];
114                buffers[channel].push_back(value);
115            }
116        }
117        Ok(())
118    })?;
119    input_audio_unit.start()?;
120
121    output_audio_unit.set_render_callback(move |args: Args| {
122        let Args {
123            num_frames, data, ..
124        } = args;
125        // Print the number of frames the callback requests.
126        println!("output cb {} frames", num_frames);
127        let buffer_left = consumer_left.lock().unwrap();
128        let buffer_right = consumer_right.lock().unwrap();
129        let mut buffers = vec![buffer_left, buffer_right];
130        for i in 0..num_frames {
131            // Default other channels to copy value from first channel as a fallback
132            let zero: S = 0 as S;
133            let f: S = *buffers[0].front().unwrap_or(&zero);
134            for channel in 0..2 {
135                let sample: S = buffers[channel].pop_front().unwrap_or(f);
136                data.buffer[2 * i + channel] = sample;
137            }
138        }
139        Ok(())
140    })?;
141    output_audio_unit.start()?;
142    for _ in 0..1000 {
143        std::thread::sleep(std::time::Duration::from_millis(100));
144        if listener_cap.get_nbr_values() > 0 {
145            println!("capture rate change: {:?}", listener_cap.drain_values());
146        }
147        if listener_pb.get_nbr_values() > 0 {
148            println!("playback rate change: {:?}", listener_pb.drain_values());
149        }
150    }
151    Ok(())
152}
examples/sine_advanced.rs (lines 154-170)
54fn main() -> Result<(), coreaudio::Error> {
55    let frequency_hz_l = 1000.;
56    let frequency_hz_r = 1200.;
57    let volume = 0.95;
58    let mut samples_l = SineWaveGenerator::new(frequency_hz_l, volume);
59    let mut samples_r = SineWaveGenerator::new(frequency_hz_r, volume);
60
61    // Construct an Output audio unit that delivers audio to the default output device.
62    let audio_unit_id = get_default_device_id(false).unwrap();
63    let mut audio_unit = audio_unit_from_device_id(audio_unit_id, false)?;
64
65    let pid = get_hogging_pid(audio_unit_id)?;
66    if pid != -1 {
67        println!("Device is owned by another process with pid {}!", pid);
68    } else {
69        println!("Device is free, trying to get exclusive access..");
70        let new_pid = toggle_hog_mode(audio_unit_id)?;
71        let process_id = process::id();
72        if new_pid == process_id as i32 {
73            println!("We have exclusive access.");
74        } else {
75            println!(
76                "Could not get exclusive access. Process pid: {}, new pid value: {}",
77                process_id, new_pid
78            );
79        }
80    }
81
82    let mut format_flag = match SAMPLE_FORMAT {
83        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
84        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
85            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
86        }
87        _ => {
88            unimplemented!("Please use one of the packed formats");
89        }
90    };
91
92    if !INTERLEAVED {
93        format_flag = format_flag | LinearPcmFlags::IS_NON_INTERLEAVED;
94    }
95
96    let stream_format = StreamFormat {
97        sample_rate: SAMPLE_RATE,
98        sample_format: SAMPLE_FORMAT,
99        flags: format_flag,
100        // you can change this to 1
101        channels: 2,
102    };
103
104    println!("stream format={:#?}", &stream_format);
105    println!("asbd={:#?}", &stream_format.to_asbd());
106
107    // Lets print all supported formats, disabled for now since it often crashes.
108    println!("All supported formats");
109    let formats = get_supported_physical_stream_formats(audio_unit_id)?;
110    for fmt in formats {
111        println!("{:?}", &fmt);
112    }
113
114    // set the sample rate. This isn't actually needed since the sample rate
115    // will anyway be changed when setting the sample format later.
116    // Keeping it here as an example.
117    //println!("set device sample rate");
118    //set_device_sample_rate(audio_unit_id, SAMPLE_RATE)?;
119
120    println!("setting hardware (physical) format");
121    let hw_stream_format = StreamFormat {
122        sample_rate: SAMPLE_RATE,
123        sample_format: SampleFormat::I16,
124        flags: LinearPcmFlags::empty(),
125        channels: 2,
126    };
127
128    let hw_asbd = find_matching_physical_format(audio_unit_id, hw_stream_format)
129        .ok_or(coreaudio::Error::UnsupportedStreamFormat)?;
130
131    println!("asbd: {:?}", hw_asbd);
132
133    // Note that using a StreamFormat here is convenient, but it only supports a few sample formats.
134    // Setting the format to for example 24 bit integers requires using an ASBD.
135    set_device_physical_stream_format(audio_unit_id, hw_asbd)?;
136
137    println!("write audio unit StreamFormat property");
138    let id = kAudioUnitProperty_StreamFormat;
139    let asbd = stream_format.to_asbd();
140    audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
141
142    // For this example, our sine wave expects `f32` data.
143    assert!(SampleFormat::F32 == stream_format.sample_format);
144
145    // Register rate and alive listeners
146    let mut rate_listener = RateListener::new(audio_unit_id, None);
147    rate_listener.register()?;
148    let mut alive_listener = AliveListener::new(audio_unit_id);
149    alive_listener.register()?;
150
151    if INTERLEAVED {
152        println!("Register interleaved callback");
153        type Args = render_callback::Args<data::Interleaved<f32>>;
154        audio_unit.set_render_callback(move |args| {
155            let Args {
156                num_frames, data, ..
157            } = args;
158            // Print the number of frames the callback requests.
159            // Included to aid understanding, don't use println and other things
160            // that may block for an unknown amount of time inside the callback
161            // of a real application.
162            println!("frames: {}", num_frames);
163            for i in 0..num_frames {
164                let sample_l = samples_l.next().unwrap();
165                let sample_r = samples_r.next().unwrap();
166                data.buffer[2 * i] = sample_l;
167                data.buffer[2 * i + 1] = sample_r;
168            }
169            Ok(())
170        })?;
171    } else {
172        println!("Register non-interleaved callback");
173        type Args = render_callback::Args<data::NonInterleaved<f32>>;
174        audio_unit.set_render_callback(move |args| {
175            let Args {
176                num_frames,
177                mut data,
178                ..
179            } = args;
180            for i in 0..num_frames {
181                let sample_l = samples_l.next().unwrap();
182                let sample_r = samples_r.next().unwrap();
183                let mut channels = data.channels_mut();
184                let left = channels.next().unwrap();
185                left[i] = sample_l;
186                let right = channels.next().unwrap();
187                right[i] = sample_r;
188            }
189            Ok(())
190        })?;
191    }
192    audio_unit.start()?;
193
194    for _ in 0..100 {
195        std::thread::sleep(std::time::Duration::from_millis(100));
196        // print all sample change events
197        println!("rate events: {:?}", rate_listener.copy_values());
198        println!("alive state: {}", alive_listener.is_alive());
199    }
200
201    // Release exclusive access, not really needed as the process exits anyway after this.
202    let owner_pid = get_hogging_pid(audio_unit_id)?;
203    let process_id = process::id();
204    if owner_pid == process_id as i32 {
205        println!("Releasing exclusive access");
206        let new_pid = toggle_hog_mode(audio_unit_id)?;
207        if new_pid == -1 {
208            println!("Exclusive access released.");
209        } else {
210            println!(
211                "Could not release exclusive access. Process pid: {}, new pid value: {}",
212                process_id, new_pid
213            );
214        }
215    }
216    Ok(())
217}
Source

pub fn set_input_callback<F, D>(&mut self, f: F) -> Result<(), Error>
where F: FnMut(Args<D>) -> Result<(), ()> + 'static, D: Data,

Pass an input callback (aka “Input Procedure”) to the AudioUnit.

Examples found in repository?
examples/feedback.rs (lines 85-106)
22fn main() -> Result<(), coreaudio::Error> {
23    let mut input_audio_unit =
24        audio_unit_from_device_id(get_default_device_id(true).unwrap(), true)?;
25    let mut output_audio_unit =
26        audio_unit_from_device_id(get_default_device_id(false).unwrap(), false)?;
27
28    let format_flag = match SAMPLE_FORMAT {
29        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT,
30        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
31            LinearPcmFlags::IS_SIGNED_INTEGER
32        }
33        _ => {
34            unimplemented!("Other formats are not implemented for this example.");
35        }
36    };
37
38    // Using IS_NON_INTERLEAVED everywhere because data::Interleaved is commented out / not implemented
39    let in_stream_format = StreamFormat {
40        sample_rate: SAMPLE_RATE,
41        sample_format: SAMPLE_FORMAT,
42        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
43        // audio_unit.set_input_callback is hardcoded to 1 buffer, and when using non_interleaved
44        // we are forced to 1 channel
45        channels: 1,
46    };
47
48    let out_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
52        // you can change this to 1
53        channels: 2,
54    };
55
56    println!("input={:#?}", &in_stream_format);
57    println!("output={:#?}", &out_stream_format);
58    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
59    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
60
61    let id = kAudioUnitProperty_StreamFormat;
62    let asbd = in_stream_format.to_asbd();
63    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
64
65    let asbd = out_stream_format.to_asbd();
66    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
67
68    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
69    let producer_left = buffer_left.clone();
70    let consumer_left = buffer_left.clone();
71    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
72    let producer_right = buffer_right.clone();
73    let consumer_right = buffer_right.clone();
74
75    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
76    for buffer in vec![buffer_left, buffer_right] {
77        let mut buffer = buffer.lock().unwrap();
78        for _ in 0..(out_stream_format.sample_rate as i32) {
79            buffer.push_back(0 as S);
80        }
81    }
82
83    type Args = render_callback::Args<data::NonInterleaved<S>>;
84
85    input_audio_unit.set_input_callback(move |args| {
86        let Args {
87            num_frames,
88            mut data,
89            ..
90        } = args;
91        // Print the number of frames the callback provides.
92        // Included to aid understanding, don't use println and other things
93        // that may block for an unknown amount of time inside the callback
94        // of a real application.
95        println!("input cb {} frames", num_frames);
96        let buffer_left = producer_left.lock().unwrap();
97        let buffer_right = producer_right.lock().unwrap();
98        let mut buffers = vec![buffer_left, buffer_right];
99        for i in 0..num_frames {
100            for (ch, channel) in data.channels_mut().enumerate() {
101                let value: S = channel[i];
102                buffers[ch].push_back(value);
103            }
104        }
105        Ok(())
106    })?;
107    input_audio_unit.start()?;
108
109    output_audio_unit.set_render_callback(move |args: Args| {
110        let Args {
111            num_frames,
112            mut data,
113            ..
114        } = args;
115        // Print the number of frames the callback requests.
116        // Included to aid understanding, don't use println and other things
117        // that may block for an unknown amount of time inside the callback
118        // of a real application.
119        println!("output cb {} frames", num_frames);
120        let buffer_left = consumer_left.lock().unwrap();
121        let buffer_right = consumer_right.lock().unwrap();
122        let mut buffers = vec![buffer_left, buffer_right];
123        for i in 0..num_frames {
124            // Default other channels to copy value from first channel as a fallback
125            let zero: S = 0 as S;
126            let f: S = *buffers[0].front().unwrap_or(&zero);
127            for (ch, channel) in data.channels_mut().enumerate() {
128                let sample: S = buffers[ch].pop_front().unwrap_or(f);
129                channel[i] = sample;
130            }
131        }
132        Ok(())
133    })?;
134    output_audio_unit.start()?;
135
136    std::thread::sleep(std::time::Duration::from_millis(100000));
137
138    Ok(())
139}
More examples
Hide additional examples
examples/feedback_interleaved.rs (lines 99-118)
24fn main() -> Result<(), coreaudio::Error> {
25    let input_device_id = get_default_device_id(true).unwrap();
26    let output_device_id = get_default_device_id(false).unwrap();
27    println!(
28        "Input device: {}",
29        get_device_name(input_device_id).unwrap()
30    );
31    println!(
32        "Output device: {}",
33        get_device_name(output_device_id).unwrap()
34    );
35    let mut input_audio_unit = audio_unit_from_device_id(input_device_id, true)?;
36    let mut output_audio_unit = audio_unit_from_device_id(output_device_id, false)?;
37
38    let format_flag = match SAMPLE_FORMAT {
39        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
40        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
41            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
42        }
43        _ => {
44            unimplemented!("Please use one of the packed formats");
45        }
46    };
47
48    let in_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag,
52        channels: 2,
53    };
54
55    let out_stream_format = StreamFormat {
56        sample_rate: SAMPLE_RATE,
57        sample_format: SAMPLE_FORMAT,
58        flags: format_flag,
59        channels: 2,
60    };
61
62    println!("input={:#?}", &in_stream_format);
63    println!("output={:#?}", &out_stream_format);
64    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
65    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
66
67    let id = kAudioUnitProperty_StreamFormat;
68    let asbd = in_stream_format.to_asbd();
69    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
70
71    let asbd = out_stream_format.to_asbd();
72    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
73
74    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
75    let producer_left = buffer_left.clone();
76    let consumer_left = buffer_left.clone();
77    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
78    let producer_right = buffer_right.clone();
79    let consumer_right = buffer_right.clone();
80
81    // Register a rate listener for playback
82    let mut listener_pb = RateListener::new(output_device_id, None);
83    listener_pb.register()?;
84
85    // Register a rate listener for capture
86    let mut listener_cap = RateListener::new(input_device_id, None);
87    listener_cap.register()?;
88
89    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
90    for buffer in vec![buffer_left, buffer_right] {
91        let mut buffer = buffer.lock().unwrap();
92        for _ in 0..(out_stream_format.sample_rate as i32) {
93            buffer.push_back(0 as S);
94        }
95    }
96
97    type Args = render_callback::Args<data::Interleaved<S>>;
98
99    input_audio_unit.set_input_callback(move |args| {
100        let Args {
101            num_frames, data, ..
102        } = args;
103        // Print the number of frames the callback requests.
104        // Included to aid understanding, don't use println and other things
105        // that may block for an unknown amount of time inside the callback
106        // of a real application.
107        println!("input cb {} frames", num_frames);
108        let buffer_left = producer_left.lock().unwrap();
109        let buffer_right = producer_right.lock().unwrap();
110        let mut buffers = vec![buffer_left, buffer_right];
111        for i in 0..num_frames {
112            for channel in 0..2 {
113                let value: S = data.buffer[2 * i + channel];
114                buffers[channel].push_back(value);
115            }
116        }
117        Ok(())
118    })?;
119    input_audio_unit.start()?;
120
121    output_audio_unit.set_render_callback(move |args: Args| {
122        let Args {
123            num_frames, data, ..
124        } = args;
125        // Print the number of frames the callback requests.
126        println!("output cb {} frames", num_frames);
127        let buffer_left = consumer_left.lock().unwrap();
128        let buffer_right = consumer_right.lock().unwrap();
129        let mut buffers = vec![buffer_left, buffer_right];
130        for i in 0..num_frames {
131            // Default other channels to copy value from first channel as a fallback
132            let zero: S = 0 as S;
133            let f: S = *buffers[0].front().unwrap_or(&zero);
134            for channel in 0..2 {
135                let sample: S = buffers[channel].pop_front().unwrap_or(f);
136                data.buffer[2 * i + channel] = sample;
137            }
138        }
139        Ok(())
140    })?;
141    output_audio_unit.start()?;
142    for _ in 0..1000 {
143        std::thread::sleep(std::time::Duration::from_millis(100));
144        if listener_cap.get_nbr_values() > 0 {
145            println!("capture rate change: {:?}", listener_cap.drain_values());
146        }
147        if listener_pb.get_nbr_values() > 0 {
148            println!("playback rate change: {:?}", listener_pb.drain_values());
149        }
150    }
151    Ok(())
152}
Source

pub fn free_render_callback(&mut self) -> Option<Box<InputProcFnWrapper>>

Retrieves ownership over the render callback and returns it where it can be re-used or safely dropped.

Source

pub fn free_input_callback(&mut self) -> Option<Box<InputProcFnWrapper>>

Retrieves ownership over the input callback and returns it where it can be re-used or safely dropped.

Source§

impl AudioUnit

Source

pub fn new<T>(ty: T) -> Result<AudioUnit, Error>
where T: Into<Type>,

Construct a new AudioUnit with any type that may be automatically converted into Type.

Here is a list of compatible types:

To construct the AudioUnit with some component flags, see AudioUnit::new_with_flags.

Note: the AudioUnit is constructed with the kAudioUnitManufacturer_Apple Manufacturer Identifier, as this is the only Audio Unit Manufacturer Identifier documented by Apple in the AudioUnit reference (see here).

Examples found in repository?
examples/sine.rs (line 42)
36fn main() -> Result<(), coreaudio::Error> {
37    let frequency_hz = 440.;
38    let volume = 0.15;
39    let mut samples = SineWaveGenerator::new(frequency_hz, volume);
40
41    // Construct an Output audio unit that delivers audio to the default output device.
42    let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?;
43
44    // Read the input format. This is counterintuitive, but it's the format used when sending
45    // audio data to the AudioUnit representing the output device. This is separate from the
46    // format the AudioUnit later uses to send the data to the hardware device.
47    let stream_format = audio_unit.output_stream_format()?;
48    println!("{:#?}", &stream_format);
49
50    // For this example, our sine wave expects `f32` data.
51    assert!(SampleFormat::F32 == stream_format.sample_format);
52
53    type Args = render_callback::Args<data::NonInterleaved<f32>>;
54    audio_unit.set_render_callback(move |args| {
55        let Args {
56            num_frames,
57            mut data,
58            ..
59        } = args;
60        for i in 0..num_frames {
61            let sample = samples.next().unwrap();
62            for channel in data.channels_mut() {
63                channel[i] = sample;
64            }
65        }
66        Ok(())
67    })?;
68    audio_unit.start()?;
69
70    std::thread::sleep(std::time::Duration::from_millis(3000));
71
72    Ok(())
73}
Source

pub fn new_with_flags<T>( ty: T, flags: u32, mask: u32, ) -> Result<AudioUnit, Error>
where T: Into<Type>,

The same as AudioUnit::new but with the given component flags and mask.

Source

pub fn initialize(&mut self) -> Result<(), Error>

On successful initialization, the audio formats for input and output are valid and the audio unit is ready to render. During initialization, an audio unit allocates memory according to the maximum number of audio frames it can produce in response to a single render call.

Usually, the state of an audio unit (such as its I/O formats and memory allocations) cannot be changed while an audio unit is initialized.

Source

pub fn uninitialize(&mut self) -> Result<(), Error>

Before you change an initialize audio unit’s processing characteristics, such as its input or output audio data format or its sample rate, you must first uninitialize it. Calling this function deallocates the audio unit’s resources.

After calling this function, you can reconfigure the audio unit and then call AudioUnitInitialize to reinitialize it.

Source

pub fn set_property<T>( &mut self, id: u32, scope: Scope, elem: Element, maybe_data: Option<&T>, ) -> Result<(), Error>

Sets the value for some property of the AudioUnit.

To clear an audio unit property value, set the data parameter with None::<()>.

Clearing properties only works for those properties that do not have a default value.

For more on “properties” see the reference.

Available in iOS 2.0 and later.

§Parameters
  • id: The identifier of the property.
  • scope: The audio unit scope for the property.
  • elem: The audio unit element for the property.
  • maybe_data: The value that you want to apply to the property.
Examples found in repository?
examples/feedback.rs (line 63)
22fn main() -> Result<(), coreaudio::Error> {
23    let mut input_audio_unit =
24        audio_unit_from_device_id(get_default_device_id(true).unwrap(), true)?;
25    let mut output_audio_unit =
26        audio_unit_from_device_id(get_default_device_id(false).unwrap(), false)?;
27
28    let format_flag = match SAMPLE_FORMAT {
29        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT,
30        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
31            LinearPcmFlags::IS_SIGNED_INTEGER
32        }
33        _ => {
34            unimplemented!("Other formats are not implemented for this example.");
35        }
36    };
37
38    // Using IS_NON_INTERLEAVED everywhere because data::Interleaved is commented out / not implemented
39    let in_stream_format = StreamFormat {
40        sample_rate: SAMPLE_RATE,
41        sample_format: SAMPLE_FORMAT,
42        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
43        // audio_unit.set_input_callback is hardcoded to 1 buffer, and when using non_interleaved
44        // we are forced to 1 channel
45        channels: 1,
46    };
47
48    let out_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
52        // you can change this to 1
53        channels: 2,
54    };
55
56    println!("input={:#?}", &in_stream_format);
57    println!("output={:#?}", &out_stream_format);
58    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
59    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
60
61    let id = kAudioUnitProperty_StreamFormat;
62    let asbd = in_stream_format.to_asbd();
63    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
64
65    let asbd = out_stream_format.to_asbd();
66    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
67
68    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
69    let producer_left = buffer_left.clone();
70    let consumer_left = buffer_left.clone();
71    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
72    let producer_right = buffer_right.clone();
73    let consumer_right = buffer_right.clone();
74
75    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
76    for buffer in vec![buffer_left, buffer_right] {
77        let mut buffer = buffer.lock().unwrap();
78        for _ in 0..(out_stream_format.sample_rate as i32) {
79            buffer.push_back(0 as S);
80        }
81    }
82
83    type Args = render_callback::Args<data::NonInterleaved<S>>;
84
85    input_audio_unit.set_input_callback(move |args| {
86        let Args {
87            num_frames,
88            mut data,
89            ..
90        } = args;
91        // Print the number of frames the callback provides.
92        // Included to aid understanding, don't use println and other things
93        // that may block for an unknown amount of time inside the callback
94        // of a real application.
95        println!("input cb {} frames", num_frames);
96        let buffer_left = producer_left.lock().unwrap();
97        let buffer_right = producer_right.lock().unwrap();
98        let mut buffers = vec![buffer_left, buffer_right];
99        for i in 0..num_frames {
100            for (ch, channel) in data.channels_mut().enumerate() {
101                let value: S = channel[i];
102                buffers[ch].push_back(value);
103            }
104        }
105        Ok(())
106    })?;
107    input_audio_unit.start()?;
108
109    output_audio_unit.set_render_callback(move |args: Args| {
110        let Args {
111            num_frames,
112            mut data,
113            ..
114        } = args;
115        // Print the number of frames the callback requests.
116        // Included to aid understanding, don't use println and other things
117        // that may block for an unknown amount of time inside the callback
118        // of a real application.
119        println!("output cb {} frames", num_frames);
120        let buffer_left = consumer_left.lock().unwrap();
121        let buffer_right = consumer_right.lock().unwrap();
122        let mut buffers = vec![buffer_left, buffer_right];
123        for i in 0..num_frames {
124            // Default other channels to copy value from first channel as a fallback
125            let zero: S = 0 as S;
126            let f: S = *buffers[0].front().unwrap_or(&zero);
127            for (ch, channel) in data.channels_mut().enumerate() {
128                let sample: S = buffers[ch].pop_front().unwrap_or(f);
129                channel[i] = sample;
130            }
131        }
132        Ok(())
133    })?;
134    output_audio_unit.start()?;
135
136    std::thread::sleep(std::time::Duration::from_millis(100000));
137
138    Ok(())
139}
More examples
Hide additional examples
examples/feedback_interleaved.rs (line 69)
24fn main() -> Result<(), coreaudio::Error> {
25    let input_device_id = get_default_device_id(true).unwrap();
26    let output_device_id = get_default_device_id(false).unwrap();
27    println!(
28        "Input device: {}",
29        get_device_name(input_device_id).unwrap()
30    );
31    println!(
32        "Output device: {}",
33        get_device_name(output_device_id).unwrap()
34    );
35    let mut input_audio_unit = audio_unit_from_device_id(input_device_id, true)?;
36    let mut output_audio_unit = audio_unit_from_device_id(output_device_id, false)?;
37
38    let format_flag = match SAMPLE_FORMAT {
39        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
40        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
41            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
42        }
43        _ => {
44            unimplemented!("Please use one of the packed formats");
45        }
46    };
47
48    let in_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag,
52        channels: 2,
53    };
54
55    let out_stream_format = StreamFormat {
56        sample_rate: SAMPLE_RATE,
57        sample_format: SAMPLE_FORMAT,
58        flags: format_flag,
59        channels: 2,
60    };
61
62    println!("input={:#?}", &in_stream_format);
63    println!("output={:#?}", &out_stream_format);
64    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
65    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
66
67    let id = kAudioUnitProperty_StreamFormat;
68    let asbd = in_stream_format.to_asbd();
69    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
70
71    let asbd = out_stream_format.to_asbd();
72    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
73
74    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
75    let producer_left = buffer_left.clone();
76    let consumer_left = buffer_left.clone();
77    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
78    let producer_right = buffer_right.clone();
79    let consumer_right = buffer_right.clone();
80
81    // Register a rate listener for playback
82    let mut listener_pb = RateListener::new(output_device_id, None);
83    listener_pb.register()?;
84
85    // Register a rate listener for capture
86    let mut listener_cap = RateListener::new(input_device_id, None);
87    listener_cap.register()?;
88
89    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
90    for buffer in vec![buffer_left, buffer_right] {
91        let mut buffer = buffer.lock().unwrap();
92        for _ in 0..(out_stream_format.sample_rate as i32) {
93            buffer.push_back(0 as S);
94        }
95    }
96
97    type Args = render_callback::Args<data::Interleaved<S>>;
98
99    input_audio_unit.set_input_callback(move |args| {
100        let Args {
101            num_frames, data, ..
102        } = args;
103        // Print the number of frames the callback requests.
104        // Included to aid understanding, don't use println and other things
105        // that may block for an unknown amount of time inside the callback
106        // of a real application.
107        println!("input cb {} frames", num_frames);
108        let buffer_left = producer_left.lock().unwrap();
109        let buffer_right = producer_right.lock().unwrap();
110        let mut buffers = vec![buffer_left, buffer_right];
111        for i in 0..num_frames {
112            for channel in 0..2 {
113                let value: S = data.buffer[2 * i + channel];
114                buffers[channel].push_back(value);
115            }
116        }
117        Ok(())
118    })?;
119    input_audio_unit.start()?;
120
121    output_audio_unit.set_render_callback(move |args: Args| {
122        let Args {
123            num_frames, data, ..
124        } = args;
125        // Print the number of frames the callback requests.
126        println!("output cb {} frames", num_frames);
127        let buffer_left = consumer_left.lock().unwrap();
128        let buffer_right = consumer_right.lock().unwrap();
129        let mut buffers = vec![buffer_left, buffer_right];
130        for i in 0..num_frames {
131            // Default other channels to copy value from first channel as a fallback
132            let zero: S = 0 as S;
133            let f: S = *buffers[0].front().unwrap_or(&zero);
134            for channel in 0..2 {
135                let sample: S = buffers[channel].pop_front().unwrap_or(f);
136                data.buffer[2 * i + channel] = sample;
137            }
138        }
139        Ok(())
140    })?;
141    output_audio_unit.start()?;
142    for _ in 0..1000 {
143        std::thread::sleep(std::time::Duration::from_millis(100));
144        if listener_cap.get_nbr_values() > 0 {
145            println!("capture rate change: {:?}", listener_cap.drain_values());
146        }
147        if listener_pb.get_nbr_values() > 0 {
148            println!("playback rate change: {:?}", listener_pb.drain_values());
149        }
150    }
151    Ok(())
152}
examples/sine_advanced.rs (line 140)
54fn main() -> Result<(), coreaudio::Error> {
55    let frequency_hz_l = 1000.;
56    let frequency_hz_r = 1200.;
57    let volume = 0.95;
58    let mut samples_l = SineWaveGenerator::new(frequency_hz_l, volume);
59    let mut samples_r = SineWaveGenerator::new(frequency_hz_r, volume);
60
61    // Construct an Output audio unit that delivers audio to the default output device.
62    let audio_unit_id = get_default_device_id(false).unwrap();
63    let mut audio_unit = audio_unit_from_device_id(audio_unit_id, false)?;
64
65    let pid = get_hogging_pid(audio_unit_id)?;
66    if pid != -1 {
67        println!("Device is owned by another process with pid {}!", pid);
68    } else {
69        println!("Device is free, trying to get exclusive access..");
70        let new_pid = toggle_hog_mode(audio_unit_id)?;
71        let process_id = process::id();
72        if new_pid == process_id as i32 {
73            println!("We have exclusive access.");
74        } else {
75            println!(
76                "Could not get exclusive access. Process pid: {}, new pid value: {}",
77                process_id, new_pid
78            );
79        }
80    }
81
82    let mut format_flag = match SAMPLE_FORMAT {
83        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
84        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
85            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
86        }
87        _ => {
88            unimplemented!("Please use one of the packed formats");
89        }
90    };
91
92    if !INTERLEAVED {
93        format_flag = format_flag | LinearPcmFlags::IS_NON_INTERLEAVED;
94    }
95
96    let stream_format = StreamFormat {
97        sample_rate: SAMPLE_RATE,
98        sample_format: SAMPLE_FORMAT,
99        flags: format_flag,
100        // you can change this to 1
101        channels: 2,
102    };
103
104    println!("stream format={:#?}", &stream_format);
105    println!("asbd={:#?}", &stream_format.to_asbd());
106
107    // Lets print all supported formats, disabled for now since it often crashes.
108    println!("All supported formats");
109    let formats = get_supported_physical_stream_formats(audio_unit_id)?;
110    for fmt in formats {
111        println!("{:?}", &fmt);
112    }
113
114    // set the sample rate. This isn't actually needed since the sample rate
115    // will anyway be changed when setting the sample format later.
116    // Keeping it here as an example.
117    //println!("set device sample rate");
118    //set_device_sample_rate(audio_unit_id, SAMPLE_RATE)?;
119
120    println!("setting hardware (physical) format");
121    let hw_stream_format = StreamFormat {
122        sample_rate: SAMPLE_RATE,
123        sample_format: SampleFormat::I16,
124        flags: LinearPcmFlags::empty(),
125        channels: 2,
126    };
127
128    let hw_asbd = find_matching_physical_format(audio_unit_id, hw_stream_format)
129        .ok_or(coreaudio::Error::UnsupportedStreamFormat)?;
130
131    println!("asbd: {:?}", hw_asbd);
132
133    // Note that using a StreamFormat here is convenient, but it only supports a few sample formats.
134    // Setting the format to for example 24 bit integers requires using an ASBD.
135    set_device_physical_stream_format(audio_unit_id, hw_asbd)?;
136
137    println!("write audio unit StreamFormat property");
138    let id = kAudioUnitProperty_StreamFormat;
139    let asbd = stream_format.to_asbd();
140    audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
141
142    // For this example, our sine wave expects `f32` data.
143    assert!(SampleFormat::F32 == stream_format.sample_format);
144
145    // Register rate and alive listeners
146    let mut rate_listener = RateListener::new(audio_unit_id, None);
147    rate_listener.register()?;
148    let mut alive_listener = AliveListener::new(audio_unit_id);
149    alive_listener.register()?;
150
151    if INTERLEAVED {
152        println!("Register interleaved callback");
153        type Args = render_callback::Args<data::Interleaved<f32>>;
154        audio_unit.set_render_callback(move |args| {
155            let Args {
156                num_frames, data, ..
157            } = args;
158            // Print the number of frames the callback requests.
159            // Included to aid understanding, don't use println and other things
160            // that may block for an unknown amount of time inside the callback
161            // of a real application.
162            println!("frames: {}", num_frames);
163            for i in 0..num_frames {
164                let sample_l = samples_l.next().unwrap();
165                let sample_r = samples_r.next().unwrap();
166                data.buffer[2 * i] = sample_l;
167                data.buffer[2 * i + 1] = sample_r;
168            }
169            Ok(())
170        })?;
171    } else {
172        println!("Register non-interleaved callback");
173        type Args = render_callback::Args<data::NonInterleaved<f32>>;
174        audio_unit.set_render_callback(move |args| {
175            let Args {
176                num_frames,
177                mut data,
178                ..
179            } = args;
180            for i in 0..num_frames {
181                let sample_l = samples_l.next().unwrap();
182                let sample_r = samples_r.next().unwrap();
183                let mut channels = data.channels_mut();
184                let left = channels.next().unwrap();
185                left[i] = sample_l;
186                let right = channels.next().unwrap();
187                right[i] = sample_r;
188            }
189            Ok(())
190        })?;
191    }
192    audio_unit.start()?;
193
194    for _ in 0..100 {
195        std::thread::sleep(std::time::Duration::from_millis(100));
196        // print all sample change events
197        println!("rate events: {:?}", rate_listener.copy_values());
198        println!("alive state: {}", alive_listener.is_alive());
199    }
200
201    // Release exclusive access, not really needed as the process exits anyway after this.
202    let owner_pid = get_hogging_pid(audio_unit_id)?;
203    let process_id = process::id();
204    if owner_pid == process_id as i32 {
205        println!("Releasing exclusive access");
206        let new_pid = toggle_hog_mode(audio_unit_id)?;
207        if new_pid == -1 {
208            println!("Exclusive access released.");
209        } else {
210            println!(
211                "Could not release exclusive access. Process pid: {}, new pid value: {}",
212                process_id, new_pid
213            );
214        }
215    }
216    Ok(())
217}
Source

pub fn get_property<T>( &self, id: u32, scope: Scope, elem: Element, ) -> Result<T, Error>

Gets the value of an AudioUnit property.

Available in iOS 2.0 and later.

§Parameters
  • id: The identifier of the property.
  • scope: The audio unit scope for the property.
  • elem: The audio unit element for the property.
Source

pub fn start(&mut self) -> Result<(), Error>

Starts an I/O AudioUnit, which in turn starts the audio unit processing graph that it is connected to.

Available in OS X v10.0 and later.

Examples found in repository?
examples/sine.rs (line 68)
36fn main() -> Result<(), coreaudio::Error> {
37    let frequency_hz = 440.;
38    let volume = 0.15;
39    let mut samples = SineWaveGenerator::new(frequency_hz, volume);
40
41    // Construct an Output audio unit that delivers audio to the default output device.
42    let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?;
43
44    // Read the input format. This is counterintuitive, but it's the format used when sending
45    // audio data to the AudioUnit representing the output device. This is separate from the
46    // format the AudioUnit later uses to send the data to the hardware device.
47    let stream_format = audio_unit.output_stream_format()?;
48    println!("{:#?}", &stream_format);
49
50    // For this example, our sine wave expects `f32` data.
51    assert!(SampleFormat::F32 == stream_format.sample_format);
52
53    type Args = render_callback::Args<data::NonInterleaved<f32>>;
54    audio_unit.set_render_callback(move |args| {
55        let Args {
56            num_frames,
57            mut data,
58            ..
59        } = args;
60        for i in 0..num_frames {
61            let sample = samples.next().unwrap();
62            for channel in data.channels_mut() {
63                channel[i] = sample;
64            }
65        }
66        Ok(())
67    })?;
68    audio_unit.start()?;
69
70    std::thread::sleep(std::time::Duration::from_millis(3000));
71
72    Ok(())
73}
More examples
Hide additional examples
examples/feedback.rs (line 107)
22fn main() -> Result<(), coreaudio::Error> {
23    let mut input_audio_unit =
24        audio_unit_from_device_id(get_default_device_id(true).unwrap(), true)?;
25    let mut output_audio_unit =
26        audio_unit_from_device_id(get_default_device_id(false).unwrap(), false)?;
27
28    let format_flag = match SAMPLE_FORMAT {
29        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT,
30        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
31            LinearPcmFlags::IS_SIGNED_INTEGER
32        }
33        _ => {
34            unimplemented!("Other formats are not implemented for this example.");
35        }
36    };
37
38    // Using IS_NON_INTERLEAVED everywhere because data::Interleaved is commented out / not implemented
39    let in_stream_format = StreamFormat {
40        sample_rate: SAMPLE_RATE,
41        sample_format: SAMPLE_FORMAT,
42        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
43        // audio_unit.set_input_callback is hardcoded to 1 buffer, and when using non_interleaved
44        // we are forced to 1 channel
45        channels: 1,
46    };
47
48    let out_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag | LinearPcmFlags::IS_PACKED | LinearPcmFlags::IS_NON_INTERLEAVED,
52        // you can change this to 1
53        channels: 2,
54    };
55
56    println!("input={:#?}", &in_stream_format);
57    println!("output={:#?}", &out_stream_format);
58    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
59    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
60
61    let id = kAudioUnitProperty_StreamFormat;
62    let asbd = in_stream_format.to_asbd();
63    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
64
65    let asbd = out_stream_format.to_asbd();
66    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
67
68    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
69    let producer_left = buffer_left.clone();
70    let consumer_left = buffer_left.clone();
71    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
72    let producer_right = buffer_right.clone();
73    let consumer_right = buffer_right.clone();
74
75    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
76    for buffer in vec![buffer_left, buffer_right] {
77        let mut buffer = buffer.lock().unwrap();
78        for _ in 0..(out_stream_format.sample_rate as i32) {
79            buffer.push_back(0 as S);
80        }
81    }
82
83    type Args = render_callback::Args<data::NonInterleaved<S>>;
84
85    input_audio_unit.set_input_callback(move |args| {
86        let Args {
87            num_frames,
88            mut data,
89            ..
90        } = args;
91        // Print the number of frames the callback provides.
92        // Included to aid understanding, don't use println and other things
93        // that may block for an unknown amount of time inside the callback
94        // of a real application.
95        println!("input cb {} frames", num_frames);
96        let buffer_left = producer_left.lock().unwrap();
97        let buffer_right = producer_right.lock().unwrap();
98        let mut buffers = vec![buffer_left, buffer_right];
99        for i in 0..num_frames {
100            for (ch, channel) in data.channels_mut().enumerate() {
101                let value: S = channel[i];
102                buffers[ch].push_back(value);
103            }
104        }
105        Ok(())
106    })?;
107    input_audio_unit.start()?;
108
109    output_audio_unit.set_render_callback(move |args: Args| {
110        let Args {
111            num_frames,
112            mut data,
113            ..
114        } = args;
115        // Print the number of frames the callback requests.
116        // Included to aid understanding, don't use println and other things
117        // that may block for an unknown amount of time inside the callback
118        // of a real application.
119        println!("output cb {} frames", num_frames);
120        let buffer_left = consumer_left.lock().unwrap();
121        let buffer_right = consumer_right.lock().unwrap();
122        let mut buffers = vec![buffer_left, buffer_right];
123        for i in 0..num_frames {
124            // Default other channels to copy value from first channel as a fallback
125            let zero: S = 0 as S;
126            let f: S = *buffers[0].front().unwrap_or(&zero);
127            for (ch, channel) in data.channels_mut().enumerate() {
128                let sample: S = buffers[ch].pop_front().unwrap_or(f);
129                channel[i] = sample;
130            }
131        }
132        Ok(())
133    })?;
134    output_audio_unit.start()?;
135
136    std::thread::sleep(std::time::Duration::from_millis(100000));
137
138    Ok(())
139}
examples/feedback_interleaved.rs (line 119)
24fn main() -> Result<(), coreaudio::Error> {
25    let input_device_id = get_default_device_id(true).unwrap();
26    let output_device_id = get_default_device_id(false).unwrap();
27    println!(
28        "Input device: {}",
29        get_device_name(input_device_id).unwrap()
30    );
31    println!(
32        "Output device: {}",
33        get_device_name(output_device_id).unwrap()
34    );
35    let mut input_audio_unit = audio_unit_from_device_id(input_device_id, true)?;
36    let mut output_audio_unit = audio_unit_from_device_id(output_device_id, false)?;
37
38    let format_flag = match SAMPLE_FORMAT {
39        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
40        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
41            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
42        }
43        _ => {
44            unimplemented!("Please use one of the packed formats");
45        }
46    };
47
48    let in_stream_format = StreamFormat {
49        sample_rate: SAMPLE_RATE,
50        sample_format: SAMPLE_FORMAT,
51        flags: format_flag,
52        channels: 2,
53    };
54
55    let out_stream_format = StreamFormat {
56        sample_rate: SAMPLE_RATE,
57        sample_format: SAMPLE_FORMAT,
58        flags: format_flag,
59        channels: 2,
60    };
61
62    println!("input={:#?}", &in_stream_format);
63    println!("output={:#?}", &out_stream_format);
64    println!("input_asbd={:#?}", &in_stream_format.to_asbd());
65    println!("output_asbd={:#?}", &out_stream_format.to_asbd());
66
67    let id = kAudioUnitProperty_StreamFormat;
68    let asbd = in_stream_format.to_asbd();
69    input_audio_unit.set_property(id, Scope::Output, Element::Input, Some(&asbd))?;
70
71    let asbd = out_stream_format.to_asbd();
72    output_audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
73
74    let buffer_left = Arc::new(Mutex::new(VecDeque::<S>::new()));
75    let producer_left = buffer_left.clone();
76    let consumer_left = buffer_left.clone();
77    let buffer_right = Arc::new(Mutex::new(VecDeque::<S>::new()));
78    let producer_right = buffer_right.clone();
79    let consumer_right = buffer_right.clone();
80
81    // Register a rate listener for playback
82    let mut listener_pb = RateListener::new(output_device_id, None);
83    listener_pb.register()?;
84
85    // Register a rate listener for capture
86    let mut listener_cap = RateListener::new(input_device_id, None);
87    listener_cap.register()?;
88
89    // seed roughly 1 second of data to create a delay in the feedback loop for easier testing
90    for buffer in vec![buffer_left, buffer_right] {
91        let mut buffer = buffer.lock().unwrap();
92        for _ in 0..(out_stream_format.sample_rate as i32) {
93            buffer.push_back(0 as S);
94        }
95    }
96
97    type Args = render_callback::Args<data::Interleaved<S>>;
98
99    input_audio_unit.set_input_callback(move |args| {
100        let Args {
101            num_frames, data, ..
102        } = args;
103        // Print the number of frames the callback requests.
104        // Included to aid understanding, don't use println and other things
105        // that may block for an unknown amount of time inside the callback
106        // of a real application.
107        println!("input cb {} frames", num_frames);
108        let buffer_left = producer_left.lock().unwrap();
109        let buffer_right = producer_right.lock().unwrap();
110        let mut buffers = vec![buffer_left, buffer_right];
111        for i in 0..num_frames {
112            for channel in 0..2 {
113                let value: S = data.buffer[2 * i + channel];
114                buffers[channel].push_back(value);
115            }
116        }
117        Ok(())
118    })?;
119    input_audio_unit.start()?;
120
121    output_audio_unit.set_render_callback(move |args: Args| {
122        let Args {
123            num_frames, data, ..
124        } = args;
125        // Print the number of frames the callback requests.
126        println!("output cb {} frames", num_frames);
127        let buffer_left = consumer_left.lock().unwrap();
128        let buffer_right = consumer_right.lock().unwrap();
129        let mut buffers = vec![buffer_left, buffer_right];
130        for i in 0..num_frames {
131            // Default other channels to copy value from first channel as a fallback
132            let zero: S = 0 as S;
133            let f: S = *buffers[0].front().unwrap_or(&zero);
134            for channel in 0..2 {
135                let sample: S = buffers[channel].pop_front().unwrap_or(f);
136                data.buffer[2 * i + channel] = sample;
137            }
138        }
139        Ok(())
140    })?;
141    output_audio_unit.start()?;
142    for _ in 0..1000 {
143        std::thread::sleep(std::time::Duration::from_millis(100));
144        if listener_cap.get_nbr_values() > 0 {
145            println!("capture rate change: {:?}", listener_cap.drain_values());
146        }
147        if listener_pb.get_nbr_values() > 0 {
148            println!("playback rate change: {:?}", listener_pb.drain_values());
149        }
150    }
151    Ok(())
152}
examples/sine_advanced.rs (line 192)
54fn main() -> Result<(), coreaudio::Error> {
55    let frequency_hz_l = 1000.;
56    let frequency_hz_r = 1200.;
57    let volume = 0.95;
58    let mut samples_l = SineWaveGenerator::new(frequency_hz_l, volume);
59    let mut samples_r = SineWaveGenerator::new(frequency_hz_r, volume);
60
61    // Construct an Output audio unit that delivers audio to the default output device.
62    let audio_unit_id = get_default_device_id(false).unwrap();
63    let mut audio_unit = audio_unit_from_device_id(audio_unit_id, false)?;
64
65    let pid = get_hogging_pid(audio_unit_id)?;
66    if pid != -1 {
67        println!("Device is owned by another process with pid {}!", pid);
68    } else {
69        println!("Device is free, trying to get exclusive access..");
70        let new_pid = toggle_hog_mode(audio_unit_id)?;
71        let process_id = process::id();
72        if new_pid == process_id as i32 {
73            println!("We have exclusive access.");
74        } else {
75            println!(
76                "Could not get exclusive access. Process pid: {}, new pid value: {}",
77                process_id, new_pid
78            );
79        }
80    }
81
82    let mut format_flag = match SAMPLE_FORMAT {
83        SampleFormat::F32 => LinearPcmFlags::IS_FLOAT | LinearPcmFlags::IS_PACKED,
84        SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
85            LinearPcmFlags::IS_SIGNED_INTEGER | LinearPcmFlags::IS_PACKED
86        }
87        _ => {
88            unimplemented!("Please use one of the packed formats");
89        }
90    };
91
92    if !INTERLEAVED {
93        format_flag = format_flag | LinearPcmFlags::IS_NON_INTERLEAVED;
94    }
95
96    let stream_format = StreamFormat {
97        sample_rate: SAMPLE_RATE,
98        sample_format: SAMPLE_FORMAT,
99        flags: format_flag,
100        // you can change this to 1
101        channels: 2,
102    };
103
104    println!("stream format={:#?}", &stream_format);
105    println!("asbd={:#?}", &stream_format.to_asbd());
106
107    // Lets print all supported formats, disabled for now since it often crashes.
108    println!("All supported formats");
109    let formats = get_supported_physical_stream_formats(audio_unit_id)?;
110    for fmt in formats {
111        println!("{:?}", &fmt);
112    }
113
114    // set the sample rate. This isn't actually needed since the sample rate
115    // will anyway be changed when setting the sample format later.
116    // Keeping it here as an example.
117    //println!("set device sample rate");
118    //set_device_sample_rate(audio_unit_id, SAMPLE_RATE)?;
119
120    println!("setting hardware (physical) format");
121    let hw_stream_format = StreamFormat {
122        sample_rate: SAMPLE_RATE,
123        sample_format: SampleFormat::I16,
124        flags: LinearPcmFlags::empty(),
125        channels: 2,
126    };
127
128    let hw_asbd = find_matching_physical_format(audio_unit_id, hw_stream_format)
129        .ok_or(coreaudio::Error::UnsupportedStreamFormat)?;
130
131    println!("asbd: {:?}", hw_asbd);
132
133    // Note that using a StreamFormat here is convenient, but it only supports a few sample formats.
134    // Setting the format to for example 24 bit integers requires using an ASBD.
135    set_device_physical_stream_format(audio_unit_id, hw_asbd)?;
136
137    println!("write audio unit StreamFormat property");
138    let id = kAudioUnitProperty_StreamFormat;
139    let asbd = stream_format.to_asbd();
140    audio_unit.set_property(id, Scope::Input, Element::Output, Some(&asbd))?;
141
142    // For this example, our sine wave expects `f32` data.
143    assert!(SampleFormat::F32 == stream_format.sample_format);
144
145    // Register rate and alive listeners
146    let mut rate_listener = RateListener::new(audio_unit_id, None);
147    rate_listener.register()?;
148    let mut alive_listener = AliveListener::new(audio_unit_id);
149    alive_listener.register()?;
150
151    if INTERLEAVED {
152        println!("Register interleaved callback");
153        type Args = render_callback::Args<data::Interleaved<f32>>;
154        audio_unit.set_render_callback(move |args| {
155            let Args {
156                num_frames, data, ..
157            } = args;
158            // Print the number of frames the callback requests.
159            // Included to aid understanding, don't use println and other things
160            // that may block for an unknown amount of time inside the callback
161            // of a real application.
162            println!("frames: {}", num_frames);
163            for i in 0..num_frames {
164                let sample_l = samples_l.next().unwrap();
165                let sample_r = samples_r.next().unwrap();
166                data.buffer[2 * i] = sample_l;
167                data.buffer[2 * i + 1] = sample_r;
168            }
169            Ok(())
170        })?;
171    } else {
172        println!("Register non-interleaved callback");
173        type Args = render_callback::Args<data::NonInterleaved<f32>>;
174        audio_unit.set_render_callback(move |args| {
175            let Args {
176                num_frames,
177                mut data,
178                ..
179            } = args;
180            for i in 0..num_frames {
181                let sample_l = samples_l.next().unwrap();
182                let sample_r = samples_r.next().unwrap();
183                let mut channels = data.channels_mut();
184                let left = channels.next().unwrap();
185                left[i] = sample_l;
186                let right = channels.next().unwrap();
187                right[i] = sample_r;
188            }
189            Ok(())
190        })?;
191    }
192    audio_unit.start()?;
193
194    for _ in 0..100 {
195        std::thread::sleep(std::time::Duration::from_millis(100));
196        // print all sample change events
197        println!("rate events: {:?}", rate_listener.copy_values());
198        println!("alive state: {}", alive_listener.is_alive());
199    }
200
201    // Release exclusive access, not really needed as the process exits anyway after this.
202    let owner_pid = get_hogging_pid(audio_unit_id)?;
203    let process_id = process::id();
204    if owner_pid == process_id as i32 {
205        println!("Releasing exclusive access");
206        let new_pid = toggle_hog_mode(audio_unit_id)?;
207        if new_pid == -1 {
208            println!("Exclusive access released.");
209        } else {
210            println!(
211                "Could not release exclusive access. Process pid: {}, new pid value: {}",
212                process_id, new_pid
213            );
214        }
215    }
216    Ok(())
217}
Source

pub fn stop(&mut self) -> Result<(), Error>

Stops an I/O AudioUnit, which in turn stops the audio unit processing graph that it is connected to.

Available in OS X v10.0 and later.

Source

pub fn set_sample_rate(&mut self, sample_rate: f64) -> Result<(), Error>

Set the AudioUnit’s sample rate.

Available in iOS 2.0 and later.

Source

pub fn sample_rate(&self) -> Result<f64, Error>

Get the AudioUnit’s sample rate.

Source

pub fn set_stream_format( &mut self, stream_format: StreamFormat, scope: Scope, element: Element, ) -> Result<(), Error>

Sets the current StreamFormat for the AudioUnit.

Core Audio uses slightly different defaults depending on the platform.

From the Core Audio Overview:

The canonical formats in Core Audio are as follows:

  • iOS input and output: Linear PCM with 16-bit integer samples.
  • iOS audio units and other audio processing: Noninterleaved linear PCM with 8.24-bit fixed-point samples
  • Mac input and output: Linear PCM with 32-bit floating point samples.
  • Mac audio units and other audio processing: Noninterleaved linear PCM with 32-bit floating-point
Source

pub fn stream_format( &self, scope: Scope, element: Element, ) -> Result<StreamFormat, Error>

Return the current Stream Format for the AudioUnit.

Source

pub fn output_stream_format(&self) -> Result<StreamFormat, Error>

Return the current output Stream Format for the AudioUnit.

Examples found in repository?
examples/sine.rs (line 47)
36fn main() -> Result<(), coreaudio::Error> {
37    let frequency_hz = 440.;
38    let volume = 0.15;
39    let mut samples = SineWaveGenerator::new(frequency_hz, volume);
40
41    // Construct an Output audio unit that delivers audio to the default output device.
42    let mut audio_unit = AudioUnit::new(IOType::DefaultOutput)?;
43
44    // Read the input format. This is counterintuitive, but it's the format used when sending
45    // audio data to the AudioUnit representing the output device. This is separate from the
46    // format the AudioUnit later uses to send the data to the hardware device.
47    let stream_format = audio_unit.output_stream_format()?;
48    println!("{:#?}", &stream_format);
49
50    // For this example, our sine wave expects `f32` data.
51    assert!(SampleFormat::F32 == stream_format.sample_format);
52
53    type Args = render_callback::Args<data::NonInterleaved<f32>>;
54    audio_unit.set_render_callback(move |args| {
55        let Args {
56            num_frames,
57            mut data,
58            ..
59        } = args;
60        for i in 0..num_frames {
61            let sample = samples.next().unwrap();
62            for channel in data.channels_mut() {
63                channel[i] = sample;
64            }
65        }
66        Ok(())
67    })?;
68    audio_unit.start()?;
69
70    std::thread::sleep(std::time::Duration::from_millis(3000));
71
72    Ok(())
73}
Source

pub fn input_stream_format(&self) -> Result<StreamFormat, Error>

Return the current input Stream Format for the AudioUnit.

Trait Implementations§

Source§

impl AsMut<*mut OpaqueAudioComponentInstance> for AudioUnit

Source§

fn as_mut(&mut self) -> &mut InnerAudioUnit

Converts this type into a mutable reference of the (usually inferred) input type.
Source§

impl AsRef<*mut OpaqueAudioComponentInstance> for AudioUnit

Source§

fn as_ref(&self) -> &InnerAudioUnit

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Drop for AudioUnit

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for AudioUnit

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,