| 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 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 // VerifyAudioParametersForActiveAudioSession() for a mismatch between the | 79 // VerifyAudioParametersForActiveAudioSession() for a mismatch between the |
| 80 // preferred number of channels and the actual number of channels. | 80 // preferred number of channels and the actual number of channels. |
| 81 const int kPreferredNumberOfChannels = 1; | 81 const int kPreferredNumberOfChannels = 1; |
| 82 // Number of bytes per audio sample for 16-bit signed integer representation. | 82 // Number of bytes per audio sample for 16-bit signed integer representation. |
| 83 const UInt32 kBytesPerSample = 2; | 83 const UInt32 kBytesPerSample = 2; |
| 84 // Hardcoded delay estimates based on real measurements. | 84 // Hardcoded delay estimates based on real measurements. |
| 85 // TODO(henrika): these value is not used in combination with built-in AEC. | 85 // TODO(henrika): these value is not used in combination with built-in AEC. |
| 86 // Can most likely be removed. | 86 // Can most likely be removed. |
| 87 const UInt16 kFixedPlayoutDelayEstimate = 30; | 87 const UInt16 kFixedPlayoutDelayEstimate = 30; |
| 88 const UInt16 kFixedRecordDelayEstimate = 30; | 88 const UInt16 kFixedRecordDelayEstimate = 30; |
| 89 // Calls to AudioUnitInitialize() can fail if called back-to-back on different |
| 90 // ADM instances. A fall-back solution is to allow multiple sequential calls |
| 91 // with as small delay between each. This factor sets the max number of allowed |
| 92 // initialization attempts. |
| 93 const int kMaxNumberOfAudioUnitInitializeAttempts = 5; |
| 94 |
| 89 | 95 |
| 90 using ios::CheckAndLogError; | 96 using ios::CheckAndLogError; |
| 91 | 97 |
| 92 // Verifies that the current audio session supports input audio and that the | 98 // Verifies that the current audio session supports input audio and that the |
| 93 // required category and mode are enabled. | 99 // required category and mode are enabled. |
| 94 static bool VerifyAudioSession(AVAudioSession* session) { | 100 static bool VerifyAudioSession(AVAudioSession* session) { |
| 95 LOG(LS_INFO) << "VerifyAudioSession"; | 101 LOG(LS_INFO) << "VerifyAudioSession"; |
| 96 // Ensure that the device currently supports audio input. | 102 // Ensure that the device currently supports audio input. |
| 97 if (!session.isInputAvailable) { | 103 if (!session.isInputAvailable) { |
| 98 LOG(LS_ERROR) << "No audio input path is available!"; | 104 LOG(LS_ERROR) << "No audio input path is available!"; |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 LOGI() << "SetupAndInitializeVoiceProcessingAudioUnit"; | 740 LOGI() << "SetupAndInitializeVoiceProcessingAudioUnit"; |
| 735 RTC_DCHECK(!vpio_unit_) << "VoiceProcessingIO audio unit already exists"; | 741 RTC_DCHECK(!vpio_unit_) << "VoiceProcessingIO audio unit already exists"; |
| 736 // Create an audio component description to identify the Voice-Processing | 742 // Create an audio component description to identify the Voice-Processing |
| 737 // I/O audio unit. | 743 // I/O audio unit. |
| 738 AudioComponentDescription vpio_unit_description; | 744 AudioComponentDescription vpio_unit_description; |
| 739 vpio_unit_description.componentType = kAudioUnitType_Output; | 745 vpio_unit_description.componentType = kAudioUnitType_Output; |
| 740 vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO; | 746 vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO; |
| 741 vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple; | 747 vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple; |
| 742 vpio_unit_description.componentFlags = 0; | 748 vpio_unit_description.componentFlags = 0; |
| 743 vpio_unit_description.componentFlagsMask = 0; | 749 vpio_unit_description.componentFlagsMask = 0; |
| 750 |
| 744 // Obtain an audio unit instance given the description. | 751 // Obtain an audio unit instance given the description. |
| 745 AudioComponent found_vpio_unit_ref = | 752 AudioComponent found_vpio_unit_ref = |
| 746 AudioComponentFindNext(nullptr, &vpio_unit_description); | 753 AudioComponentFindNext(nullptr, &vpio_unit_description); |
| 747 | 754 |
| 748 // Create a Voice-Processing IO audio unit. | 755 // Create a Voice-Processing IO audio unit. |
| 749 OSStatus result = noErr; | 756 OSStatus result = noErr; |
| 750 result = AudioComponentInstanceNew(found_vpio_unit_ref, &vpio_unit_); | 757 result = AudioComponentInstanceNew(found_vpio_unit_ref, &vpio_unit_); |
| 751 if (result != noErr) { | 758 if (result != noErr) { |
| 752 vpio_unit_ = nullptr; | 759 vpio_unit_ = nullptr; |
| 753 LOG(LS_ERROR) << "AudioComponentInstanceNew failed: " << result; | 760 LOG(LS_ERROR) << "AudioComponentInstanceNew failed: " << result; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 kAudioOutputUnitProperty_SetInputCallback, | 876 kAudioOutputUnitProperty_SetInputCallback, |
| 870 kAudioUnitScope_Global, input_bus, | 877 kAudioUnitScope_Global, input_bus, |
| 871 &input_callback, sizeof(input_callback)); | 878 &input_callback, sizeof(input_callback)); |
| 872 if (result != noErr) { | 879 if (result != noErr) { |
| 873 DisposeAudioUnit(); | 880 DisposeAudioUnit(); |
| 874 LOG(LS_ERROR) << "Failed to specify the input callback on the input bus: " | 881 LOG(LS_ERROR) << "Failed to specify the input callback on the input bus: " |
| 875 << result; | 882 << result; |
| 876 } | 883 } |
| 877 | 884 |
| 878 // Initialize the Voice-Processing I/O unit instance. | 885 // Initialize the Voice-Processing I/O unit instance. |
| 886 // Calls to AudioUnitInitialize() can fail if called back-to-back on |
| 887 // different ADM instances. The error message in this case is -66635 which is |
| 888 // undocumented. Tests have shown that calling AudioUnitInitialize a second |
| 889 // time, after a short sleep, avoids this issue. |
| 890 // See webrtc:5166 for details. |
| 891 int failed_initalize_attempts = 0; |
| 879 result = AudioUnitInitialize(vpio_unit_); | 892 result = AudioUnitInitialize(vpio_unit_); |
| 880 if (result != noErr) { | 893 while (result != noErr) { |
| 881 result = AudioUnitUninitialize(vpio_unit_); | |
| 882 if (result != noErr) { | |
| 883 LOG_F(LS_ERROR) << "AudioUnitUninitialize failed: " << result; | |
| 884 } | |
| 885 DisposeAudioUnit(); | |
| 886 LOG(LS_ERROR) << "Failed to initialize the Voice-Processing I/O unit: " | 894 LOG(LS_ERROR) << "Failed to initialize the Voice-Processing I/O unit: " |
| 887 << result; | 895 << result; |
| 888 return false; | 896 ++failed_initalize_attempts; |
| 897 if (failed_initalize_attempts == kMaxNumberOfAudioUnitInitializeAttempts) { |
| 898 // Max number of initialization attempts exceeded, hence abort. |
| 899 LOG(LS_WARNING) << "Too many initialization attempts"; |
| 900 DisposeAudioUnit(); |
| 901 return false; |
| 902 } |
| 903 LOG(LS_INFO) << "pause 100ms and try audio unit initialization again..."; |
| 904 [NSThread sleepForTimeInterval:0.1f]; |
| 905 result = AudioUnitInitialize(vpio_unit_); |
| 889 } | 906 } |
| 907 LOG(LS_INFO) << "Voice-Processing I/O unit is now initialized"; |
| 890 return true; | 908 return true; |
| 891 } | 909 } |
| 892 | 910 |
| 893 bool AudioDeviceIOS::RestartAudioUnitWithNewFormat(float sample_rate) { | 911 bool AudioDeviceIOS::RestartAudioUnitWithNewFormat(float sample_rate) { |
| 894 LOGI() << "RestartAudioUnitWithNewFormat(sample_rate=" << sample_rate << ")"; | 912 LOGI() << "RestartAudioUnitWithNewFormat(sample_rate=" << sample_rate << ")"; |
| 895 // Stop the active audio unit. | 913 // Stop the active audio unit. |
| 896 LOG_AND_RETURN_IF_ERROR(AudioOutputUnitStop(vpio_unit_), | 914 LOG_AND_RETURN_IF_ERROR(AudioOutputUnitStop(vpio_unit_), |
| 897 "Failed to stop the the Voice-Processing I/O unit"); | 915 "Failed to stop the the Voice-Processing I/O unit"); |
| 898 | 916 |
| 899 // The stream format is about to be changed and it requires that we first | 917 // The stream format is about to be changed and it requires that we first |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches | 1095 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches |
| 1078 // the native I/O audio unit) to a preallocated intermediate buffer and | 1096 // the native I/O audio unit) to a preallocated intermediate buffer and |
| 1079 // copy the result to the audio buffer in the |io_data| destination. | 1097 // copy the result to the audio buffer in the |io_data| destination. |
| 1080 SInt8* source = playout_audio_buffer_.get(); | 1098 SInt8* source = playout_audio_buffer_.get(); |
| 1081 fine_audio_buffer_->GetPlayoutData(source); | 1099 fine_audio_buffer_->GetPlayoutData(source); |
| 1082 memcpy(destination, source, dataSizeInBytes); | 1100 memcpy(destination, source, dataSizeInBytes); |
| 1083 return noErr; | 1101 return noErr; |
| 1084 } | 1102 } |
| 1085 | 1103 |
| 1086 } // namespace webrtc | 1104 } // namespace webrtc |
| OLD | NEW |