| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/audio/mac/audio_manager_mac.h" | 5 #include "media/audio/mac/audio_manager_mac.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 // Maximum number of output streams that can be open simultaneously. | 34 // Maximum number of output streams that can be open simultaneously. |
| 35 static const int kMaxOutputStreams = 50; | 35 static const int kMaxOutputStreams = 50; |
| 36 | 36 |
| 37 // Define bounds for for low-latency input and output streams. | 37 // Define bounds for for low-latency input and output streams. |
| 38 static const int kMinimumInputOutputBufferSize = 128; | 38 static const int kMinimumInputOutputBufferSize = 128; |
| 39 static const int kMaximumInputOutputBufferSize = 4096; | 39 static const int kMaximumInputOutputBufferSize = 4096; |
| 40 | 40 |
| 41 // Default sample-rate on most Apple hardware. | 41 // Default sample-rate on most Apple hardware. |
| 42 static const int kFallbackSampleRate = 44100; | 42 static const int kFallbackSampleRate = 44100; |
| 43 | 43 |
| 44 static int GetDefaultBufferSize(bool is_input, int sample_rate) { |
| 45 // kMinimumInputOutputBufferSize is too small for the output side because |
| 46 // CoreAudio can get into under-run if the renderer fails delivering data |
| 47 // to the browser within the allowed time by the OS. The workaround is to |
| 48 // use 256 samples as the default output buffer size for sample rates |
| 49 // smaller than 96KHz. |
| 50 // TODO(xians): Remove this workaround after WebAudio supports user defined |
| 51 // buffer size. See https://github.com/WebAudio/web-audio-api/issues/348 |
| 52 // for details. |
| 53 int buffer_size = is_input ? kMinimumInputOutputBufferSize |
| 54 : 2 * kMinimumInputOutputBufferSize; |
| 55 if (sample_rate > 48000) { |
| 56 // The default buffer size is too small for higher sample rates and may lead |
| 57 // to glitching. Adjust upwards by multiples of the default size. |
| 58 if (sample_rate <= 96000) |
| 59 buffer_size = 2 * kMinimumInputOutputBufferSize; |
| 60 else if (sample_rate <= 192000) |
| 61 buffer_size = 4 * kMinimumInputOutputBufferSize; |
| 62 } |
| 63 return buffer_size; |
| 64 } |
| 65 |
| 44 // Helper method to construct AudioObjectPropertyAddress structure given | 66 // Helper method to construct AudioObjectPropertyAddress structure given |
| 45 // property selector and scope. The property element is always set to | 67 // property selector and scope. The property element is always set to |
| 46 // kAudioObjectPropertyElementMaster. | 68 // kAudioObjectPropertyElementMaster. |
| 47 static AudioObjectPropertyAddress GetAudioObjectPropertyAddress( | 69 static AudioObjectPropertyAddress GetAudioObjectPropertyAddress( |
| 48 AudioObjectPropertySelector selector, | 70 AudioObjectPropertySelector selector, |
| 49 bool is_input) { | 71 bool is_input) { |
| 50 AudioObjectPropertyScope scope = is_input ? kAudioObjectPropertyScopeInput | 72 AudioObjectPropertyScope scope = is_input ? kAudioObjectPropertyScopeInput |
| 51 : kAudioObjectPropertyScopeOutput; | 73 : kAudioObjectPropertyScopeOutput; |
| 52 AudioObjectPropertyAddress property_address = { | 74 AudioObjectPropertyAddress property_address = { |
| 53 selector, scope, kAudioObjectPropertyElementMaster}; | 75 selector, scope, kAudioObjectPropertyElementMaster}; |
| (...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 const bool has_valid_input_params = input_params.IsValid(); | 855 const bool has_valid_input_params = input_params.IsValid(); |
| 834 const int hardware_sample_rate = HardwareSampleRateForDevice(device); | 856 const int hardware_sample_rate = HardwareSampleRateForDevice(device); |
| 835 | 857 |
| 836 // Allow pass through buffer sizes. If concurrent input and output streams | 858 // Allow pass through buffer sizes. If concurrent input and output streams |
| 837 // exist, they will use the smallest buffer size amongst them. As such, each | 859 // exist, they will use the smallest buffer size amongst them. As such, each |
| 838 // stream must be able to FIFO requests appropriately when this happens. | 860 // stream must be able to FIFO requests appropriately when this happens. |
| 839 int buffer_size = ChooseBufferSize(false, hardware_sample_rate); | 861 int buffer_size = ChooseBufferSize(false, hardware_sample_rate); |
| 840 if (has_valid_input_params) { | 862 if (has_valid_input_params) { |
| 841 buffer_size = | 863 buffer_size = |
| 842 std::min(kMaximumInputOutputBufferSize, | 864 std::min(kMaximumInputOutputBufferSize, |
| 843 std::max(input_params.frames_per_buffer(), buffer_size)); | 865 std::max(input_params.frames_per_buffer(), |
| 866 GetMinimumAudioBufferSize(hardware_sample_rate))); |
| 844 } | 867 } |
| 845 | 868 |
| 846 int hardware_channels; | 869 int hardware_channels; |
| 847 if (!GetDeviceChannels(device, AUElement::OUTPUT, &hardware_channels)) | 870 if (!GetDeviceChannels(device, AUElement::OUTPUT, &hardware_channels)) |
| 848 hardware_channels = 2; | 871 hardware_channels = 2; |
| 849 | 872 |
| 850 // Use the input channel count and channel layout if possible. Let OSX take | 873 // Use the input channel count and channel layout if possible. Let OSX take |
| 851 // care of remapping the channels; this lets user specified channel layouts | 874 // care of remapping the channels; this lets user specified channel layouts |
| 852 // work correctly. | 875 // work correctly. |
| 853 int output_channels = input_params.channels(); | 876 int output_channels = input_params.channels(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 880 current_output_device_ == new_output_device) { | 903 current_output_device_ == new_output_device) { |
| 881 return; | 904 return; |
| 882 } | 905 } |
| 883 | 906 |
| 884 current_sample_rate_ = new_sample_rate; | 907 current_sample_rate_ = new_sample_rate; |
| 885 current_output_device_ = new_output_device; | 908 current_output_device_ = new_output_device; |
| 886 NotifyAllOutputDeviceChangeListeners(); | 909 NotifyAllOutputDeviceChangeListeners(); |
| 887 } | 910 } |
| 888 | 911 |
| 889 int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) { | 912 int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) { |
| 890 // kMinimumInputOutputBufferSize is too small for the output side because | |
| 891 // CoreAudio can get into under-run if the renderer fails delivering data | |
| 892 // to the browser within the allowed time by the OS. The workaround is to | |
| 893 // use 256 samples as the default output buffer size for sample rates | |
| 894 // smaller than 96KHz. | |
| 895 // TODO(xians): Remove this workaround after WebAudio supports user defined | |
| 896 // buffer size. See https://github.com/WebAudio/web-audio-api/issues/348 | |
| 897 // for details. | |
| 898 int buffer_size = is_input ? | |
| 899 kMinimumInputOutputBufferSize : 2 * kMinimumInputOutputBufferSize; | |
| 900 const int user_buffer_size = GetUserBufferSize(); | 913 const int user_buffer_size = GetUserBufferSize(); |
| 901 if (user_buffer_size) { | 914 if (user_buffer_size) |
| 902 buffer_size = user_buffer_size; | 915 return user_buffer_size; |
| 903 } else if (sample_rate > 48000) { | 916 return GetDefaultBufferSize(is_input, sample_rate); |
| 904 // The default buffer size is too small for higher sample rates and may lead | |
| 905 // to glitching. Adjust upwards by multiples of the default size. | |
| 906 if (sample_rate <= 96000) | |
| 907 buffer_size = 2 * kMinimumInputOutputBufferSize; | |
| 908 else if (sample_rate <= 192000) | |
| 909 buffer_size = 4 * kMinimumInputOutputBufferSize; | |
| 910 } | |
| 911 | |
| 912 return buffer_size; | |
| 913 } | 917 } |
| 914 | 918 |
| 915 bool AudioManagerMac::IsSuspending() const { | 919 bool AudioManagerMac::IsSuspending() const { |
| 916 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 920 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 917 return power_observer_->IsSuspending(); | 921 return power_observer_->IsSuspending(); |
| 918 } | 922 } |
| 919 | 923 |
| 920 bool AudioManagerMac::ShouldDeferStreamStart() const { | 924 bool AudioManagerMac::ShouldDeferStreamStart() const { |
| 921 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 925 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 922 return power_observer_->ShouldDeferStreamStart(); | 926 return power_observer_->ShouldDeferStreamStart(); |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 AudioManagerBase::ReleaseInputStream(stream); | 1186 AudioManagerBase::ReleaseInputStream(stream); |
| 1183 } | 1187 } |
| 1184 | 1188 |
| 1185 std::unique_ptr<AudioManager> CreateAudioManager( | 1189 std::unique_ptr<AudioManager> CreateAudioManager( |
| 1186 std::unique_ptr<AudioThread> audio_thread, | 1190 std::unique_ptr<AudioThread> audio_thread, |
| 1187 AudioLogFactory* audio_log_factory) { | 1191 AudioLogFactory* audio_log_factory) { |
| 1188 return base::MakeUnique<AudioManagerMac>(std::move(audio_thread), | 1192 return base::MakeUnique<AudioManagerMac>(std::move(audio_thread), |
| 1189 audio_log_factory); | 1193 audio_log_factory); |
| 1190 } | 1194 } |
| 1191 | 1195 |
| 1196 int AudioManager::GetMinimumAudioBufferSize(int sample_rate) { |
| 1197 return GetDefaultBufferSize(false, sample_rate); |
| 1198 } |
| 1199 |
| 1200 int AudioManager::GetMaximumAudioBufferSize(int sample_rate) { |
| 1201 return kMaximumInputOutputBufferSize; |
| 1202 } |
| 1203 |
| 1192 } // namespace media | 1204 } // namespace media |
| OLD | NEW |