OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 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 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // with as small delay between each. This factor sets the max number of allowed | 49 // with as small delay between each. This factor sets the max number of allowed |
50 // initialization attempts. | 50 // initialization attempts. |
51 static const int kMaxNumberOfAudioUnitInitializeAttempts = 5; | 51 static const int kMaxNumberOfAudioUnitInitializeAttempts = 5; |
52 // A VP I/O unit's bus 1 connects to input hardware (microphone). | 52 // A VP I/O unit's bus 1 connects to input hardware (microphone). |
53 static const AudioUnitElement kInputBus = 1; | 53 static const AudioUnitElement kInputBus = 1; |
54 // A VP I/O unit's bus 0 connects to output hardware (speaker). | 54 // A VP I/O unit's bus 0 connects to output hardware (speaker). |
55 static const AudioUnitElement kOutputBus = 0; | 55 static const AudioUnitElement kOutputBus = 0; |
56 | 56 |
57 VoiceProcessingAudioUnit::VoiceProcessingAudioUnit( | 57 VoiceProcessingAudioUnit::VoiceProcessingAudioUnit( |
58 VoiceProcessingAudioUnitObserver* observer) | 58 VoiceProcessingAudioUnitObserver* observer) |
59 : observer_(observer), vpio_unit_(nullptr) { | 59 : observer_(observer), vpio_unit_(nullptr), state_(kInitRequired) { |
60 RTC_DCHECK(observer); | 60 RTC_DCHECK(observer); |
61 } | 61 } |
62 | 62 |
63 VoiceProcessingAudioUnit::~VoiceProcessingAudioUnit() { | 63 VoiceProcessingAudioUnit::~VoiceProcessingAudioUnit() { |
64 DisposeAudioUnit(); | 64 DisposeAudioUnit(); |
65 } | 65 } |
66 | 66 |
67 const UInt32 VoiceProcessingAudioUnit::kBytesPerSample = 2; | 67 const UInt32 VoiceProcessingAudioUnit::kBytesPerSample = 2; |
68 | 68 |
69 bool VoiceProcessingAudioUnit::Init() { | 69 bool VoiceProcessingAudioUnit::Init() { |
70 RTC_DCHECK(!vpio_unit_) << "Already called Init()."; | 70 RTC_DCHECK_EQ(state_, kInitRequired); |
71 | 71 |
72 // Create an audio component description to identify the Voice Processing | 72 // Create an audio component description to identify the Voice Processing |
73 // I/O audio unit. | 73 // I/O audio unit. |
74 AudioComponentDescription vpio_unit_description; | 74 AudioComponentDescription vpio_unit_description; |
75 vpio_unit_description.componentType = kAudioUnitType_Output; | 75 vpio_unit_description.componentType = kAudioUnitType_Output; |
76 vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO; | 76 vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO; |
77 vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple; | 77 vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple; |
78 vpio_unit_description.componentFlags = 0; | 78 vpio_unit_description.componentFlags = 0; |
79 vpio_unit_description.componentFlagsMask = 0; | 79 vpio_unit_description.componentFlagsMask = 0; |
80 | 80 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 kAudioUnitScope_Global, kInputBus, | 158 kAudioUnitScope_Global, kInputBus, |
159 &input_callback, sizeof(input_callback)); | 159 &input_callback, sizeof(input_callback)); |
160 if (result != noErr) { | 160 if (result != noErr) { |
161 DisposeAudioUnit(); | 161 DisposeAudioUnit(); |
162 RTCLogError(@"Failed to specify the input callback on the input bus. " | 162 RTCLogError(@"Failed to specify the input callback on the input bus. " |
163 "Error=%ld.", | 163 "Error=%ld.", |
164 (long)result); | 164 (long)result); |
165 return false; | 165 return false; |
166 } | 166 } |
167 | 167 |
| 168 state_ = kUninitialized; |
168 return true; | 169 return true; |
169 } | 170 } |
170 | 171 |
| 172 VoiceProcessingAudioUnit::State VoiceProcessingAudioUnit::GetState() const { |
| 173 return state_; |
| 174 } |
| 175 |
171 bool VoiceProcessingAudioUnit::Initialize(Float64 sample_rate) { | 176 bool VoiceProcessingAudioUnit::Initialize(Float64 sample_rate) { |
172 RTC_DCHECK(vpio_unit_) << "Init() not called."; | 177 RTC_DCHECK_GE(state_, kUninitialized); |
173 RTCLog(@"Initializing audio unit."); | 178 RTCLog(@"Initializing audio unit."); |
174 | 179 |
175 OSStatus result = noErr; | 180 OSStatus result = noErr; |
176 AudioStreamBasicDescription format = GetFormat(sample_rate); | 181 AudioStreamBasicDescription format = GetFormat(sample_rate); |
177 UInt32 size = sizeof(format); | 182 UInt32 size = sizeof(format); |
178 #if !defined(NDEBUG) | 183 #if !defined(NDEBUG) |
179 LogStreamDescription(format); | 184 LogStreamDescription(format); |
180 #endif | 185 #endif |
181 | 186 |
182 // Set the format on the output scope of the input element/bus. | 187 // Set the format on the output scope of the input element/bus. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 if (failed_initalize_attempts == kMaxNumberOfAudioUnitInitializeAttempts) { | 222 if (failed_initalize_attempts == kMaxNumberOfAudioUnitInitializeAttempts) { |
218 // Max number of initialization attempts exceeded, hence abort. | 223 // Max number of initialization attempts exceeded, hence abort. |
219 RTCLogError(@"Too many initialization attempts."); | 224 RTCLogError(@"Too many initialization attempts."); |
220 return false; | 225 return false; |
221 } | 226 } |
222 RTCLog(@"Pause 100ms and try audio unit initialization again..."); | 227 RTCLog(@"Pause 100ms and try audio unit initialization again..."); |
223 [NSThread sleepForTimeInterval:0.1f]; | 228 [NSThread sleepForTimeInterval:0.1f]; |
224 result = AudioUnitInitialize(vpio_unit_); | 229 result = AudioUnitInitialize(vpio_unit_); |
225 } | 230 } |
226 RTCLog(@"Voice Processing I/O unit is now initialized."); | 231 RTCLog(@"Voice Processing I/O unit is now initialized."); |
| 232 state_ = kInitialized; |
227 return true; | 233 return true; |
228 } | 234 } |
229 | 235 |
230 bool VoiceProcessingAudioUnit::Start() { | 236 bool VoiceProcessingAudioUnit::Start() { |
231 RTC_DCHECK(vpio_unit_) << "Init() not called."; | 237 RTC_DCHECK_GE(state_, kUninitialized); |
232 RTCLog(@"Starting audio unit."); | 238 RTCLog(@"Starting audio unit."); |
233 | 239 |
234 OSStatus result = AudioOutputUnitStart(vpio_unit_); | 240 OSStatus result = AudioOutputUnitStart(vpio_unit_); |
235 if (result != noErr) { | 241 if (result != noErr) { |
236 RTCLogError(@"Failed to start audio unit. Error=%ld", (long)result); | 242 RTCLogError(@"Failed to start audio unit. Error=%ld", (long)result); |
237 return false; | 243 return false; |
238 } | 244 } |
| 245 state_ = kStarted; |
239 return true; | 246 return true; |
240 } | 247 } |
241 | 248 |
242 bool VoiceProcessingAudioUnit::Stop() { | 249 bool VoiceProcessingAudioUnit::Stop() { |
243 RTC_DCHECK(vpio_unit_) << "Init() not called."; | 250 RTC_DCHECK_GE(state_, kUninitialized); |
244 RTCLog(@"Stopping audio unit."); | 251 RTCLog(@"Stopping audio unit."); |
245 | 252 |
246 OSStatus result = AudioOutputUnitStop(vpio_unit_); | 253 OSStatus result = AudioOutputUnitStop(vpio_unit_); |
247 if (result != noErr) { | 254 if (result != noErr) { |
248 RTCLogError(@"Failed to stop audio unit. Error=%ld", (long)result); | 255 RTCLogError(@"Failed to stop audio unit. Error=%ld", (long)result); |
249 return false; | 256 return false; |
250 } | 257 } |
| 258 state_ = kInitialized; |
251 return true; | 259 return true; |
252 } | 260 } |
253 | 261 |
254 bool VoiceProcessingAudioUnit::Uninitialize() { | 262 bool VoiceProcessingAudioUnit::Uninitialize() { |
255 RTC_DCHECK(vpio_unit_) << "Init() not called."; | 263 RTC_DCHECK_GE(state_, kUninitialized); |
256 RTCLog(@"Unintializing audio unit."); | 264 RTCLog(@"Unintializing audio unit."); |
257 | 265 |
258 OSStatus result = AudioUnitUninitialize(vpio_unit_); | 266 OSStatus result = AudioUnitUninitialize(vpio_unit_); |
259 if (result != noErr) { | 267 if (result != noErr) { |
260 RTCLogError(@"Failed to uninitialize audio unit. Error=%ld", (long)result); | 268 RTCLogError(@"Failed to uninitialize audio unit. Error=%ld", (long)result); |
261 return false; | 269 return false; |
262 } | 270 } |
263 return true; | 271 return true; |
264 } | 272 } |
265 | 273 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 format.mBytesPerPacket = kBytesPerSample; | 348 format.mBytesPerPacket = kBytesPerSample; |
341 format.mFramesPerPacket = 1; // uncompressed. | 349 format.mFramesPerPacket = 1; // uncompressed. |
342 format.mBytesPerFrame = kBytesPerSample; | 350 format.mBytesPerFrame = kBytesPerSample; |
343 format.mChannelsPerFrame = kRTCAudioSessionPreferredNumberOfChannels; | 351 format.mChannelsPerFrame = kRTCAudioSessionPreferredNumberOfChannels; |
344 format.mBitsPerChannel = 8 * kBytesPerSample; | 352 format.mBitsPerChannel = 8 * kBytesPerSample; |
345 return format; | 353 return format; |
346 } | 354 } |
347 | 355 |
348 void VoiceProcessingAudioUnit::DisposeAudioUnit() { | 356 void VoiceProcessingAudioUnit::DisposeAudioUnit() { |
349 if (vpio_unit_) { | 357 if (vpio_unit_) { |
| 358 switch (state_) { |
| 359 case kStarted: |
| 360 Stop(); |
| 361 // Fall through. |
| 362 case kInitialized: |
| 363 Uninitialize(); |
| 364 break; |
| 365 case kUninitialized: |
| 366 case kInitRequired: |
| 367 break; |
| 368 } |
| 369 |
350 OSStatus result = AudioComponentInstanceDispose(vpio_unit_); | 370 OSStatus result = AudioComponentInstanceDispose(vpio_unit_); |
351 if (result != noErr) { | 371 if (result != noErr) { |
352 RTCLogError(@"AudioComponentInstanceDispose failed. Error=%ld.", | 372 RTCLogError(@"AudioComponentInstanceDispose failed. Error=%ld.", |
353 (long)result); | 373 (long)result); |
354 } | 374 } |
355 vpio_unit_ = nullptr; | 375 vpio_unit_ = nullptr; |
356 } | 376 } |
357 } | 377 } |
358 | 378 |
359 } // namespace webrtc | 379 } // namespace webrtc |
OLD | NEW |