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
impl AudioUnit
Sourcepub fn set_render_callback<F, D>(&mut self, f: F) -> Result<(), Error>
pub fn set_render_callback<F, D>(&mut self, f: F) -> Result<(), Error>
Pass a render callback (aka “Input Procedure”) to the AudioUnit.
Examples found in repository?
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
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}
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}
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}
Sourcepub fn set_input_callback<F, D>(&mut self, f: F) -> Result<(), Error>
pub fn set_input_callback<F, D>(&mut self, f: F) -> Result<(), Error>
Pass an input callback (aka “Input Procedure”) to the AudioUnit.
Examples found in repository?
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
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}
Sourcepub fn free_render_callback(&mut self) -> Option<Box<InputProcFnWrapper>>
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.
Sourcepub fn free_input_callback(&mut self) -> Option<Box<InputProcFnWrapper>>
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
impl AudioUnit
Sourcepub fn new<T>(ty: T) -> Result<AudioUnit, Error>
pub fn new<T>(ty: T) -> Result<AudioUnit, Error>
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?
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}
Sourcepub fn new_with_flags<T>(
ty: T,
flags: u32,
mask: u32,
) -> Result<AudioUnit, Error>
pub fn new_with_flags<T>( ty: T, flags: u32, mask: u32, ) -> Result<AudioUnit, Error>
The same as AudioUnit::new but with the given component flags and mask.
Sourcepub fn initialize(&mut self) -> Result<(), Error>
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.
Sourcepub fn uninitialize(&mut self) -> Result<(), Error>
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.
Sourcepub fn set_property<T>(
&mut self,
id: u32,
scope: Scope,
elem: Element,
maybe_data: Option<&T>,
) -> Result<(), Error>
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?
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
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}
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}
Sourcepub fn get_property<T>(
&self,
id: u32,
scope: Scope,
elem: Element,
) -> Result<T, Error>
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.
Sourcepub fn start(&mut self) -> Result<(), Error>
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?
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
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}
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}
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}
Sourcepub fn stop(&mut self) -> Result<(), Error>
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.
Sourcepub fn set_sample_rate(&mut self, sample_rate: f64) -> Result<(), Error>
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.
Sourcepub fn sample_rate(&self) -> Result<f64, Error>
pub fn sample_rate(&self) -> Result<f64, Error>
Get the AudioUnit’s sample rate.
Sourcepub fn set_stream_format(
&mut self,
stream_format: StreamFormat,
scope: Scope,
element: Element,
) -> Result<(), Error>
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
Sourcepub fn stream_format(
&self,
scope: Scope,
element: Element,
) -> Result<StreamFormat, Error>
pub fn stream_format( &self, scope: Scope, element: Element, ) -> Result<StreamFormat, Error>
Return the current Stream Format for the AudioUnit.
Sourcepub fn output_stream_format(&self) -> Result<StreamFormat, Error>
pub fn output_stream_format(&self) -> Result<StreamFormat, Error>
Return the current output Stream Format for the AudioUnit.
Examples found in repository?
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}
Sourcepub fn input_stream_format(&self) -> Result<StreamFormat, Error>
pub fn input_stream_format(&self) -> Result<StreamFormat, Error>
Return the current input Stream Format for the AudioUnit.