/
EZMicrophone.h
381 lines (304 loc) · 20.9 KB
/
EZMicrophone.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
//
// EZMicrophone.h
// EZAudio
//
// Created by Syed Haris Ali on 9/2/13.
// Copyright (c) 2015 Syed Haris Ali. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import "TargetConditionals.h"
#import "EZAudioDevice.h"
#import "EZOutput.h"
@class EZMicrophone;
//------------------------------------------------------------------------------
#pragma mark - EZMicrophoneDelegate
//------------------------------------------------------------------------------
/**
The EZMicrophoneDelegate for the EZMicrophone provides a receiver for the incoming audio data events. When the microphone has been successfully internally configured it will try to send its delegate an AudioStreamBasicDescription describing the format of the incoming audio data.
The audio data itself is sent back to the delegate in various forms:
-`microphone:hasAudioReceived:withBufferSize:withNumberOfChannels:`
Provides float arrays instead of the AudioBufferList structure to hold the audio data. There could be a number of float arrays depending on the number of channels (see the function description below). These are useful for doing any visualizations that would like to make use of the raw audio data.
-`microphone:hasBufferList:withBufferSize:withNumberOfChannels:`
Provides the AudioBufferList structures holding the audio data. These are the native structures Core Audio uses to hold the buffer information and useful for piping out directly to an output (see EZOutput).
*/
@protocol EZMicrophoneDelegate <NSObject>
@optional
///-----------------------------------------------------------
/// @name Audio Data Description
///-----------------------------------------------------------
/**
Called anytime the EZMicrophone starts or stops.
@param output The instance of the EZMicrophone that triggered the event.
@param isPlaying A BOOL indicating whether the EZMicrophone instance is playing or not.
*/
- (void)microphone:(EZMicrophone *)microphone changedPlayingState:(BOOL)isPlaying;
//------------------------------------------------------------------------------
/**
Called anytime the input device changes on an `EZMicrophone` instance.
@param microphone The instance of the EZMicrophone that triggered the event.
@param device The instance of the new EZAudioDevice the microphone is using to pull input.
*/
- (void)microphone:(EZMicrophone *)microphone changedDevice:(EZAudioDevice *)device;
//------------------------------------------------------------------------------
/**
Returns back the audio stream basic description as soon as it has been initialized. This is guaranteed to occur before the stream callbacks, `microphone:hasBufferList:withBufferSize:withNumberOfChannels:` or `microphone:hasAudioReceived:withBufferSize:withNumberOfChannels:`
@param microphone The instance of the EZMicrophone that triggered the event.
@param audioStreamBasicDescription The AudioStreamBasicDescription that was created for the microphone instance.
*/
- (void) microphone:(EZMicrophone *)microphone
hasAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
///-----------------------------------------------------------
/// @name Audio Data Callbacks
///-----------------------------------------------------------
/**
This method provides an array of float arrays of the audio received, each float array representing a channel of audio data This occurs on the background thread so any drawing code must explicity perform its functions on the main thread.
@param microphone The instance of the EZMicrophone that triggered the event.
@param buffer The audio data as an array of float arrays. In a stereo signal buffer[0] represents the left channel while buffer[1] would represent the right channel.
@param bufferSize The size of each of the buffers (the length of each float array).
@param numberOfChannels The number of channels for the incoming audio.
@warning This function executes on a background thread to avoid blocking any audio operations. If operations should be performed on any other thread (like the main thread) it should be performed within a dispatch block like so: dispatch_async(dispatch_get_main_queue(), ^{ ...Your Code... })
*/
- (void) microphone:(EZMicrophone *)microphone
hasAudioReceived:(float **)buffer
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels;
//------------------------------------------------------------------------------
/**
Returns back the buffer list containing the audio received. This occurs on the background thread so any drawing code must explicity perform its functions on the main thread.
@param microphone The instance of the EZMicrophone that triggered the event.
@param bufferList The AudioBufferList holding the audio data.
@param bufferSize The size of each of the buffers of the AudioBufferList.
@param numberOfChannels The number of channels for the incoming audio.
@warning This function executes on a background thread to avoid blocking any audio operations. If operations should be performed on any other thread (like the main thread) it should be performed within a dispatch block like so: dispatch_async(dispatch_get_main_queue(), ^{ ...Your Code... })
*/
- (void) microphone:(EZMicrophone *)microphone
hasBufferList:(AudioBufferList *)bufferList
withBufferSize:(UInt32)bufferSize
withNumberOfChannels:(UInt32)numberOfChannels;
@end
//------------------------------------------------------------------------------
#pragma mark - EZMicrophone
//------------------------------------------------------------------------------
/**
The EZMicrophone provides a component to get audio data from the default device microphone. On OSX this is the default selected input device in the system preferences while on iOS this defaults to use the default RemoteIO audio unit. The microphone data is converted to a float buffer array and returned back to the caller via the EZMicrophoneDelegate protocol.
*/
@interface EZMicrophone : NSObject <EZOutputDataSource>
//------------------------------------------------------------------------------
/**
The EZMicrophoneDelegate for which to handle the microphone callbacks
*/
@property (nonatomic, weak) id<EZMicrophoneDelegate> delegate;
//------------------------------------------------------------------------------
/**
The EZAudioDevice being used to pull the microphone data.
- On iOS this can be any of the available microphones on the iPhone/iPad devices (usually there are 3). Defaults to the first microphone found (bottom mic)
- On OSX this can be any of the plugged in devices that Core Audio can detect (see kAudioUnitSubType_HALOutput for more information)
System Preferences -> Sound for the available inputs)
*/
@property (nonatomic, strong) EZAudioDevice *device;
//------------------------------------------------------------------------------
/**
A BOOL describing whether the microphone is on and passing back audio data to its delegate.
*/
@property (nonatomic, assign) BOOL microphoneOn;
//------------------------------------------------------------------------------
/**
An EZOutput to use for porting the microphone input out (passthrough).
*/
@property (nonatomic, strong) EZOutput *output;
//------------------------------------------------------------------------------
#pragma mark - Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Initializers
///-----------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use initWithMicrophoneDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param delegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
- (EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a custom AudioStreamBasicDescription and provides the caller to specify a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use initWithMicrophoneDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
-(EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)delegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param delegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
- (EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)delegate
startsImmediately:(BOOL)startsImmediately;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a custom AudioStreamBasicDescription and provides the caller with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param delegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
- (EZMicrophone *)initWithMicrophoneDelegate:(id<EZMicrophoneDelegate>)delegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately;
//------------------------------------------------------------------------------
#pragma mark - Class Initializers
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Class Initializers
///-----------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use microphoneWithDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param delegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@return An instance of the EZMicrophone class. This should be declared as a strong property!
*/
+ (EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)delegate;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback. This will not start fetching the audio until startFetchingAudio has been called. Use microphoneWithDelegate:startsImmediately: to instantiate this class and immediately start fetching audio data.
@param delegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@return An instance of the EZMicrophone class. This should be declared as a strong property!
*/
+ (EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)delegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
+ (EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)delegate
startsImmediately:(BOOL)startsImmediately;
//------------------------------------------------------------------------------
/**
Creates an instance of the EZMicrophone with a delegate to respond to the audioReceived callback and allows the caller to specify whether they'd immediately like to start fetching the audio data.
@param microphoneDelegate A EZMicrophoneDelegate delegate that will receive the audioReceived callback.
@param audioStreamBasicDescription A custom AudioStreamBasicFormat for the microphone input.
@param startsImmediately A boolean indicating whether to start fetching the data immediately. IF YES, the delegate's audioReceived callback will immediately start getting called.
@return An instance of the EZMicrophone class. This should be strongly retained.
*/
+ (EZMicrophone *)microphoneWithDelegate:(id<EZMicrophoneDelegate>)delegate
withAudioStreamBasicDescription:(AudioStreamBasicDescription)audioStreamBasicDescription
startsImmediately:(BOOL)startsImmediately;
//------------------------------------------------------------------------------
#pragma mark - Shared Instance
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Shared Instance
///-----------------------------------------------------------
/**
A shared instance of the microphone component. Most applications will only need to use one instance of the microphone component across multiple views. Make sure to call the `startFetchingAudio` method to receive the audio data in the microphone delegate.
@return A shared instance of the `EZAudioMicrophone` component.
*/
+ (EZMicrophone *)sharedMicrophone;
//------------------------------------------------------------------------------
#pragma mark - Events
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Starting/Stopping The Microphone
///-----------------------------------------------------------
/**
Starts fetching audio from the default microphone. Will notify delegate with audioReceived callback.
*/
- (void)startFetchingAudio;
//------------------------------------------------------------------------------
/**
Stops fetching audio. Will stop notifying the delegate's audioReceived callback.
*/
- (void)stopFetchingAudio;
//------------------------------------------------------------------------------
#pragma mark - Getters
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Getting The Microphone's Audio Format
///-----------------------------------------------------------
/**
Provides the AudioStreamBasicDescription structure containing the format of the microphone's audio.
@return An AudioStreamBasicDescription structure describing the format of the microphone's audio.
*/
- (AudioStreamBasicDescription)audioStreamBasicDescription;
//------------------------------------------------------------------------------
/**
Provides the underlying Audio Unit that is being used to fetch the audio.
@return The AudioUnit used for the microphone
*/
- (AudioUnit *)audioUnit;
//------------------------------------------------------------------------------
#pragma mark - Setters
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Customizing The Microphone Stream Format
///-----------------------------------------------------------
/**
Sets the AudioStreamBasicDescription on the microphone input. Must be linear PCM and must be the same sample rate as the stream format coming in (check the current `audioStreamBasicDescription` before setting).
@warning Do not set this while fetching audio (startFetchingAudio)
@param asbd The new AudioStreamBasicDescription to use in place of the current audio format description.
*/
- (void)setAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd;
///-----------------------------------------------------------
/// @name Setting The Microphone's Hardware Device
///-----------------------------------------------------------
/**
Sets the EZAudioDevice being used to pull the microphone data.
- On iOS this can be any of the available microphones on the iPhone/iPad devices (usually there are 3). Defaults to the first microphone found (bottom mic)
- On OSX this can be any of the plugged in devices that Core Audio can detect (see kAudioUnitSubType_HALOutput for more information)
System Preferences -> Sound for the available inputs)
@param device An EZAudioDevice instance that should be used to fetch the microphone data.
*/
- (void)setDevice:(EZAudioDevice *)device;
//------------------------------------------------------------------------------
#pragma mark - Direct Output
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Setting The Microphone's Output (Direct Out)
///-----------------------------------------------------------
/**
When set this will pipe out the contents of the microphone into an EZOutput. This is known as a passthrough or direct out that will simply pipe the microphone input to an output.
@param output An EZOutput instance that the microphone will use to output its audio data to the speaker.
*/
- (void)setOutput:(EZOutput *)output;
//------------------------------------------------------------------------------
#pragma mark - Subclass Methods
//------------------------------------------------------------------------------
///-----------------------------------------------------------
/// @name Subclass
///-----------------------------------------------------------
/**
The default AudioStreamBasicDescription set as the stream format of the microphone if no custom description is set. Defaults to a non-interleaved float format with the number of channels specified by the `numberOfChannels` method.
@return An AudioStreamBasicDescription that will be used as the default stream format.
*/
- (AudioStreamBasicDescription)defaultStreamFormat;
//------------------------------------------------------------------------------
/**
The number of channels the input microphone is expected to have. Defaults to 1 (assumes microphone is mono).
@return A UInt32 representing the number of channels expected for the microphone.
*/
- (UInt32)numberOfChannels;
//------------------------------------------------------------------------------
@end