OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H | 11 #ifndef WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_ |
12 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H | 12 #define WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_ |
13 | 13 |
14 #include <AudioUnit/AudioUnit.h> | 14 #include <AudioUnit/AudioUnit.h> |
15 | 15 |
16 #include "webrtc/base/scoped_ptr.h" | |
16 #include "webrtc/base/thread_checker.h" | 17 #include "webrtc/base/thread_checker.h" |
17 #include "webrtc/modules/audio_device/audio_device_generic.h" | 18 #include "webrtc/modules/audio_device/audio_device_generic.h" |
18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | |
19 #include "webrtc/system_wrappers/interface/thread_wrapper.h" | |
20 | 19 |
21 namespace webrtc { | 20 namespace webrtc { |
22 const uint32_t N_REC_SAMPLES_PER_SEC = 44100; | |
23 const uint32_t N_PLAY_SAMPLES_PER_SEC = 44100; | |
24 | 21 |
25 const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC / 100); | 22 class FineAudioBuffer; |
26 const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC / 100); | |
27 | 23 |
28 // Number of 10 ms recording blocks in recording buffer | 24 // Implements full duplex 16-bit mono PCM audio support for iOS using a |
29 const uint16_t N_REC_BUFFERS = 20; | 25 // Voice-Processing (VP) I/O audio unit in Core Audio. The VP I/O audio unit |
30 | 26 // supports audio echo cancellation. It also adds automatic gain control, |
27 // adjustment of voice-processing quality and muting. | |
28 // | |
29 // An instance must be created and destroyed on one and the same thread. | |
30 // All supported public methods must also be called on the same thread. | |
31 // A thread checker will DCHECK if any supported method is called on an invalid | |
32 // thread. | |
33 // | |
34 // Recorded audio will be delivered on a real-time internal I/O thread in the | |
35 // audio unit. The audio unit will also ask for audio data to play out on this | |
36 // same thread. | |
31 class AudioDeviceIOS : public AudioDeviceGeneric { | 37 class AudioDeviceIOS : public AudioDeviceGeneric { |
32 public: | 38 public: |
33 AudioDeviceIOS(); | 39 AudioDeviceIOS(); |
34 ~AudioDeviceIOS(); | 40 ~AudioDeviceIOS(); |
35 | 41 |
36 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; | 42 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; |
37 | 43 |
38 int32_t Init() override; | 44 int32_t Init() override; |
39 int32_t Terminate() override; | 45 int32_t Terminate() override; |
40 bool Initialized() const override { return _initialized; } | 46 bool Initialized() const override { return _initialized; } |
41 | 47 |
42 int32_t InitPlayout() override; | 48 int32_t InitPlayout() override; |
43 bool PlayoutIsInitialized() const override { return _playIsInitialized; } | 49 bool PlayoutIsInitialized() const override { return _playIsInitialized; } |
44 | 50 |
45 int32_t InitRecording() override; | 51 int32_t InitRecording() override; |
46 bool RecordingIsInitialized() const override { return _recIsInitialized; } | 52 bool RecordingIsInitialized() const override { return _recIsInitialized; } |
47 | 53 |
48 int32_t StartPlayout() override; | 54 int32_t StartPlayout() override; |
49 int32_t StopPlayout() override; | 55 int32_t StopPlayout() override; |
50 bool Playing() const override { return _playing; } | 56 bool Playing() const override { return _playing; } |
51 | 57 |
52 int32_t StartRecording() override; | 58 int32_t StartRecording() override; |
53 int32_t StopRecording() override; | 59 int32_t StopRecording() override; |
54 bool Recording() const override { return _recording; } | 60 bool Recording() const override { return _recording; } |
55 | 61 |
56 int32_t SetLoudspeakerStatus(bool enable) override; | 62 int32_t SetLoudspeakerStatus(bool enable) override; |
57 int32_t GetLoudspeakerStatus(bool& enabled) const override; | 63 int32_t GetLoudspeakerStatus(bool& enabled) const override; |
58 | 64 |
59 // TODO(henrika): investigate if we can reduce the complexity here. | 65 // Currently using hard-coded delay values and not dynamic delay estimates. |
60 // Do we even need delay estimates? | 66 // Given that a built-in AEC is available on iOS, it saves resources to |
67 // return fixed (reasonable) values here instead. Any AEC in WebRTC will then | |
tkchin_webrtc
2015/09/01 20:54:50
ooc, what happens if two aec passes occur? Does it
henrika_webrtc
2015/09/03 13:44:41
Extended the comments. Today we always disable all
| |
68 // work as well. | |
61 int32_t PlayoutDelay(uint16_t& delayMS) const override; | 69 int32_t PlayoutDelay(uint16_t& delayMS) const override; |
62 int32_t RecordingDelay(uint16_t& delayMS) const override; | 70 int32_t RecordingDelay(uint16_t& delayMS) const override; |
63 | 71 |
64 int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, | 72 // Native audio parameters stored during construction. |
65 uint16_t& sizeMS) const override; | |
66 | |
67 // These methods are unique for the iOS implementation. | 73 // These methods are unique for the iOS implementation. |
68 | |
69 // Native audio parameters stored during construction. | |
70 int GetPlayoutAudioParameters(AudioParameters* params) const override; | 74 int GetPlayoutAudioParameters(AudioParameters* params) const override; |
71 int GetRecordAudioParameters(AudioParameters* params) const override; | 75 int GetRecordAudioParameters(AudioParameters* params) const override; |
72 | 76 |
73 // These methods are currently not implemented on iOS. | 77 // These methods are currently not fully implemented on iOS: |
74 // See audio_device_not_implemented_ios.mm for dummy implementations. | |
75 | 78 |
79 // See audio_device_not_implemented.cc for trivial implementations. | |
80 int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, | |
81 uint16_t& sizeMS) const override; | |
76 int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; | 82 int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; |
77 int32_t ResetAudioDevice() override; | 83 int32_t ResetAudioDevice() override; |
78 int32_t PlayoutIsAvailable(bool& available) override; | 84 int32_t PlayoutIsAvailable(bool& available) override; |
79 int32_t RecordingIsAvailable(bool& available) override; | 85 int32_t RecordingIsAvailable(bool& available) override; |
80 int32_t SetAGC(bool enable) override; | 86 int32_t SetAGC(bool enable) override; |
81 bool AGC() const override; | 87 bool AGC() const override; |
82 int16_t PlayoutDevices() override; | 88 int16_t PlayoutDevices() override; |
83 int16_t RecordingDevices() override; | 89 int16_t RecordingDevices() override; |
84 int32_t PlayoutDeviceName(uint16_t index, | 90 int32_t PlayoutDeviceName(uint16_t index, |
85 char name[kAdmMaxDeviceNameSize], | 91 char name[kAdmMaxDeviceNameSize], |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 bool PlayoutWarning() const override; | 139 bool PlayoutWarning() const override; |
134 bool PlayoutError() const override; | 140 bool PlayoutError() const override; |
135 bool RecordingWarning() const override; | 141 bool RecordingWarning() const override; |
136 bool RecordingError() const override; | 142 bool RecordingError() const override; |
137 void ClearPlayoutWarning() override{}; | 143 void ClearPlayoutWarning() override{}; |
138 void ClearPlayoutError() override{}; | 144 void ClearPlayoutError() override{}; |
139 void ClearRecordingWarning() override{}; | 145 void ClearRecordingWarning() override{}; |
140 void ClearRecordingError() override{}; | 146 void ClearRecordingError() override{}; |
141 | 147 |
142 private: | 148 private: |
143 // TODO(henrika): try to remove these. | 149 // Uses current |_playoutParameters| and |_recordParameters| to inform the |
144 void Lock() { | 150 // audio device buffer (ADB) about our internal audio parameters. |
145 _critSect.Enter(); | 151 void UpdateAudioDeviceBuffer(); |
146 } | |
147 | 152 |
148 void UnLock() { | 153 // Since the preferred audio parameters are only hints to the OS, the actual |
149 _critSect.Leave(); | 154 // values may be different once the AVAudioSession has been activated. |
150 } | 155 // This method asks for the current hardware parameters and takes actions |
156 // if they should differ from what we have asked for initially. | |
157 void VerifyAudioParametersForActiveAudioSession(); | |
151 | 158 |
152 // Init and shutdown | 159 // Creates a Voice-Processing I/O unit and configures it for full-duplex |
153 int32_t InitPlayOrRecord(); | 160 // audio. The selected stream format is selected to avoid internal resampling |
154 int32_t ShutdownPlayOrRecord(); | 161 // and to match the 10ms callback rate for WebRTC as well as possible. |
162 // This method also initializes the created audio unit. | |
163 void SetupAndInitializeVoiceProcessingAudioUnit(); | |
155 | 164 |
156 void UpdateRecordingDelay(); | 165 // Activates our audio session, creates and initilizes the voice-processing |
157 void UpdatePlayoutDelay(); | 166 // audio unit and verifies that we got the preferred native audio parameters. |
167 bool InitPlayOrRecord(); | |
158 | 168 |
159 static OSStatus RecordProcess(void *inRefCon, | 169 // Closes and deletes the voice-processing I/O unit. |
160 AudioUnitRenderActionFlags *ioActionFlags, | 170 bool ShutdownPlayOrRecord(); |
161 const AudioTimeStamp *timeStamp, | |
162 UInt32 inBusNumber, | |
163 UInt32 inNumberFrames, | |
164 AudioBufferList *ioData); | |
165 | 171 |
166 static OSStatus PlayoutProcess(void *inRefCon, | 172 // Callback function called on a real-time priority I/O thread from the audio |
167 AudioUnitRenderActionFlags *ioActionFlags, | 173 // unit. This method is used to signal that recorded audio is available. |
168 const AudioTimeStamp *timeStamp, | 174 static OSStatus RecordedDataIsAvailable( |
tkchin_webrtc
2015/09/01 20:54:50
nit: Style guide is to use C++ syntax/style in C++
henrika_webrtc
2015/09/03 13:44:41
ooh nooo, I was not sure if one could use objc not
tkchin_webrtc
2015/09/04 05:29:16
I'm ok with changing old stuff separately not part
henrika_webrtc
2015/09/04 09:51:18
Agree. And thanks for letting me do this in a sepa
| |
175 void* inRefCon, | |
176 AudioUnitRenderActionFlags* ioActionFlags, | |
177 const AudioTimeStamp* timeStamp, | |
178 UInt32 inBusNumber, | |
179 UInt32 inNumberFrames, | |
180 AudioBufferList* ioData); | |
181 OSStatus OnRecordedDataIsAvailable(AudioUnitRenderActionFlags* ioActionFlags, | |
182 const AudioTimeStamp* timeStamp, | |
183 UInt32 inBusNumber, | |
184 UInt32 inNumberFrames); | |
185 | |
186 // Callback function called on a real-time priority I/O thread from the audio | |
187 // unit. This method is used to provide audio samples to the audio unit. | |
188 static OSStatus GetPlayoutData(void* inRefCon, | |
189 AudioUnitRenderActionFlags* ioActionFlags, | |
190 const AudioTimeStamp* timeStamp, | |
169 UInt32 inBusNumber, | 191 UInt32 inBusNumber, |
170 UInt32 inNumberFrames, | 192 UInt32 inNumberFrames, |
171 AudioBufferList *ioData); | 193 AudioBufferList* ioData); |
172 | 194 OSStatus OnGetPlayoutData(AudioUnitRenderActionFlags* ioActionFlags, |
173 OSStatus RecordProcessImpl(AudioUnitRenderActionFlags *ioActionFlags, | 195 UInt32 inNumberFrames, |
174 const AudioTimeStamp *timeStamp, | 196 AudioBufferList* ioData); |
175 uint32_t inBusNumber, | |
176 uint32_t inNumberFrames); | |
177 | |
178 OSStatus PlayoutProcessImpl(uint32_t inNumberFrames, | |
179 AudioBufferList *ioData); | |
180 | |
181 static bool RunCapture(void* ptrThis); | |
182 bool CaptureWorkerThread(); | |
183 | 197 |
184 private: | 198 private: |
185 rtc::ThreadChecker thread_checker_; | 199 // Ensures that methods are called from the same thread as this object is |
200 // created on. | |
201 rtc::ThreadChecker _threadChecker; | |
tkchin_webrtc
2015/09/01 20:54:50
nit: Style guide is to use C++ syntax/style in C++
henrika_webrtc
2015/09/03 13:44:41
Acknowledged.
| |
186 | 202 |
187 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the | 203 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the |
188 // AudioDeviceModuleImpl class and called by AudioDeviceModuleImpl::Create(). | 204 // AudioDeviceModuleImpl class and called by AudioDeviceModuleImpl::Create(). |
189 // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance | 205 // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance |
190 // and therefore outlives this object. | 206 // and therefore outlives this object. |
191 AudioDeviceBuffer* audio_device_buffer_; | 207 AudioDeviceBuffer* _audioDeviceBuffer; |
192 | 208 |
193 CriticalSectionWrapper& _critSect; | 209 // Contains audio parameters (sample rate, #channels, buffer size etc.) for |
210 // the playout and recording sides. These structure is set in two steps: | |
211 // first, native sample rate and #channels are defined in Init(). Next, the | |
212 // audio session is activated and we verify that the preferred parameters | |
213 // were granted by the OS. At this stage it is also possible to add a third | |
214 // component to the parameters; the native I/O buffer duration. | |
215 // A CHECK will be hit if we for some reason fail to open an audio session | |
216 // using the specified parameters. | |
217 AudioParameters _playoutParameters; | |
218 AudioParameters _recordParameters; | |
194 | 219 |
195 AudioParameters playout_parameters_; | 220 // The Voice-Processing I/O unit has the same characteristics as the |
196 AudioParameters record_parameters_; | 221 // Remote I/O unit (supports full duplex low-latency audio input and output) |
222 // and adds AEC for for two-way duplex communication. It also adds AGC, | |
223 // adjustment of voice-processing quality, and muting. Hence, ideal for | |
224 // VoIP applications. | |
225 AudioUnit _vpioUnit; | |
197 | 226 |
198 rtc::scoped_ptr<ThreadWrapper> _captureWorkerThread; | 227 // FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data |
228 // in chunks of 10ms. It then allows for this data to be pulled in | |
229 // a finer or coarser granularity. I.e. interacting with this class instead | |
230 // of directly with the AudioDeviceBuffer one can ask for any number of | |
231 // audio data samples. | |
232 // Example: native buffer size can be 128 audio frames at 16kHz sample rate. | |
233 // WebRTC will provide 480 audio frames per 10ms but iOS asks for 128 | |
234 // in each callback (one every 8ms). This class can then ask for 128 and the | |
235 // FineAudioBuffer will ask WebRTC for new data only when needed and also | |
236 // cach non-utilized audio between callbacks. | |
tkchin_webrtc
2015/09/01 20:54:50
Thanks for this comment - it was helpful.
tkchin_webrtc
2015/09/01 20:54:50
nit: cache non-utilized
henrika_webrtc
2015/09/03 13:44:41
Done.
henrika_webrtc
2015/09/03 13:44:41
Thanks. Added comments for the recording side as w
| |
237 rtc::scoped_ptr<FineAudioBuffer> _fineAudioBuffer; | |
199 | 238 |
200 AudioUnit _auVoiceProcessing; | 239 // Extra audio buffer to be used by the playout side for rendering audio. |
201 void* _audioInterruptionObserver; | 240 // The buffer size is given by FineAudioBuffer::RequiredBufferSizeBytes(). |
241 rtc::scoped_ptr<SInt8[]> _playoutAudioBuffer; | |
202 | 242 |
243 // Provides a mechanism for encapsulating one or more buffers of audio data. | |
244 // Only used on the recording side. | |
245 AudioBufferList _audioRecordBufferList; | |
246 | |
247 // Temporary storage for recorded data. AudioUnitRender() renders into this | |
248 // array as soon as a frame of the desired buffer size has been recorded. | |
249 rtc::scoped_ptr<SInt8[]> _recordAudioBuffer; | |
250 | |
251 // Set to 1 when recording is active and 0 otherwise. | |
252 volatile int _recording; | |
253 | |
254 // Set to 1 when playout is active and 0 otherwise. | |
255 volatile int _playing; | |
256 | |
257 // Set to true after successful call to Init(), false otherwise. | |
203 bool _initialized; | 258 bool _initialized; |
204 bool _isShutDown; | 259 |
205 bool _recording; | 260 // Set to true after successful call to InitRecording(), false otherwise. |
206 bool _playing; | |
207 bool _recIsInitialized; | 261 bool _recIsInitialized; |
262 | |
263 // Set to true after successful call to InitPlayout(), false otherwise. | |
208 bool _playIsInitialized; | 264 bool _playIsInitialized; |
209 | 265 |
210 // The sampling rate to use with Audio Device Buffer | 266 // Audio interruption observer instance. |
211 int _adbSampFreq; | 267 void* _audioInterruptionObserver; |
212 | |
213 // Delay calculation | |
214 uint32_t _recordingDelay; | |
215 uint32_t _playoutDelay; | |
216 uint32_t _playoutDelayMeasurementCounter; | |
217 uint32_t _recordingDelayHWAndOS; | |
218 uint32_t _recordingDelayMeasurementCounter; | |
219 | |
220 // Playout buffer, needed for 44.0 / 44.1 kHz mismatch | |
221 int16_t _playoutBuffer[ENGINE_PLAY_BUF_SIZE_IN_SAMPLES]; | |
222 uint32_t _playoutBufferUsed; // How much is filled | |
223 | |
224 // Recording buffers | |
225 int16_t _recordingBuffer[N_REC_BUFFERS][ENGINE_REC_BUF_SIZE_IN_SAMPLES]; | |
226 uint32_t _recordingLength[N_REC_BUFFERS]; | |
227 uint32_t _recordingSeqNumber[N_REC_BUFFERS]; | |
228 uint32_t _recordingCurrentSeq; | |
229 | |
230 // Current total size all data in buffers, used for delay estimate | |
231 uint32_t _recordingBufferTotalSize; | |
232 }; | 268 }; |
233 | 269 |
234 } // namespace webrtc | 270 } // namespace webrtc |
235 | 271 |
236 #endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H | 272 #endif // WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_ |
OLD | NEW |