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
3 // found in the LICENSE file.
5 #include "build/build_config.h"
6 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
7 #include "ppapi/thunk/enter.h"
8 #include "ppapi/thunk/ppb_instance_api.h"
12 // Rounds up requested_size to the nearest multiple of minimum_size.
13 static uint32_t CalculateMultipleOfSampleFrameCount(uint32_t minimum_size
,
14 uint32_t requested_size
) {
15 const uint32_t multiple
= (requested_size
+ minimum_size
- 1) / minimum_size
;
16 return std::min(minimum_size
* multiple
,
17 static_cast<uint32_t>(PP_AUDIOMAXSAMPLEFRAMECOUNT
));
20 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type
,
22 : Resource(type
, instance
),
23 sample_rate_(PP_AUDIOSAMPLERATE_NONE
),
24 sample_frame_count_(0) {}
26 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() {}
28 PP_Resource
PPB_AudioConfig_Shared::Create(ResourceObjectType type
,
30 PP_AudioSampleRate sample_rate
,
31 uint32_t sample_frame_count
) {
32 scoped_refptr
<PPB_AudioConfig_Shared
> object(
33 new PPB_AudioConfig_Shared(type
, instance
));
34 if (!object
->Init(sample_rate
, sample_frame_count
))
36 return object
->GetReference();
40 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_0(
41 PP_AudioSampleRate sample_rate
,
42 uint32_t requested_sample_frame_count
) {
43 // Version 1.0: Don't actually query to get a value from the
44 // hardware; instead return the input for in-range values.
45 if (requested_sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
46 return PP_AUDIOMINSAMPLEFRAMECOUNT
;
47 if (requested_sample_frame_count
> PP_AUDIOMAXSAMPLEFRAMECOUNT
)
48 return PP_AUDIOMAXSAMPLEFRAMECOUNT
;
49 return requested_sample_frame_count
;
53 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_1(
55 PP_AudioSampleRate sample_rate
,
56 uint32_t sample_frame_count
) {
57 // Version 1.1: Query the back-end hardware for sample rate and buffer size,
58 // and recommend a best fit based on request.
59 thunk::EnterInstanceNoLock
enter(instance
);
63 // Get the hardware config.
64 PP_AudioSampleRate hardware_sample_rate
= static_cast<PP_AudioSampleRate
>(
65 enter
.functions()->GetAudioHardwareOutputSampleRate(instance
));
66 uint32_t hardware_sample_frame_count
=
67 enter
.functions()->GetAudioHardwareOutputBufferSize(instance
);
68 if (sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
69 sample_frame_count
= PP_AUDIOMINSAMPLEFRAMECOUNT
;
71 // If hardware information isn't available we're connected to a fake audio
72 // output stream on the browser side, so we can use whatever sample count the
74 if (!hardware_sample_frame_count
|| !hardware_sample_rate
)
75 return sample_frame_count
;
77 // Note: All the values below were determined through experimentation to
78 // minimize jitter and back-to-back callbacks from the browser. Please take
79 // care when modifying these values as they impact a large number of users.
80 // TODO(dalecurtis): Land jitter test and add documentation for updating this.
82 // Should track the value reported by XP and ALSA backends.
83 const uint32_t kHighLatencySampleFrameCount
= 2048;
84 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
85 // TODO(ihf): Remove this once ARM Chromebooks support low latency audio. For
86 // now we classify them as high latency. See crbug.com/289770. Note that
87 // Adobe Flash is affected but not HTML5, WebRTC and WebAudio (they are using
88 // real time threads).
89 const bool kHighLatencyDevice
= true;
91 const bool kHighLatencyDevice
= false;
94 // If client is using same sample rate as audio hardware, then recommend a
95 // multiple of the audio hardware's sample frame count.
96 if (!kHighLatencyDevice
&& hardware_sample_rate
== sample_rate
) {
97 return CalculateMultipleOfSampleFrameCount(hardware_sample_frame_count
,
101 // If the hardware requires a high latency buffer or we're at a low sample
102 // rate w/ a buffer that's larger than 10ms, choose the nearest multiple of
103 // the high latency sample frame count. An example of too low and too large
104 // is 16kHz and a sample frame count greater than 160 frames.
105 if (kHighLatencyDevice
||
106 hardware_sample_frame_count
>= kHighLatencySampleFrameCount
||
107 (hardware_sample_rate
< 44100 &&
108 hardware_sample_frame_count
> hardware_sample_rate
/ 100u)) {
109 return CalculateMultipleOfSampleFrameCount(
111 std::max(kHighLatencySampleFrameCount
, hardware_sample_frame_count
));
114 // All low latency clients should be able to handle a 512 frame buffer with
115 // resampling from 44.1kHz and 48kHz to higher sample rates.
116 // TODO(dalecurtis): We may need to investigate making the callback thread
117 // high priority to handle buffers at the absolute minimum w/o glitching.
118 const uint32_t kLowLatencySampleFrameCount
= 512;
120 // Special case for 48kHz -> 44.1kHz and buffer sizes greater than 10ms. In
121 // testing most buffer sizes > 10ms led to glitching, so we choose a size we
122 // know won't cause jitter.
123 int min_sample_frame_count
= kLowLatencySampleFrameCount
;
124 if (hardware_sample_rate
== 44100 && sample_rate
== 48000 &&
125 hardware_sample_frame_count
> hardware_sample_rate
/ 100u) {
126 min_sample_frame_count
=
127 std::max(2 * kLowLatencySampleFrameCount
, hardware_sample_frame_count
);
130 return CalculateMultipleOfSampleFrameCount(min_sample_frame_count
,
135 PP_AudioSampleRate
PPB_AudioConfig_Shared::RecommendSampleRate(
136 PP_Instance instance
) {
137 thunk::EnterInstanceNoLock
enter(instance
);
139 return PP_AUDIOSAMPLERATE_NONE
;
140 PP_AudioSampleRate hardware_sample_rate
= static_cast<PP_AudioSampleRate
>(
141 enter
.functions()->GetAudioHardwareOutputSampleRate(instance
));
142 return hardware_sample_rate
;
145 thunk::PPB_AudioConfig_API
* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() {
149 PP_AudioSampleRate
PPB_AudioConfig_Shared::GetSampleRate() {
153 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() {
154 return sample_frame_count_
;
157 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate
,
158 uint32_t sample_frame_count
) {
159 // TODO(brettw): Currently we don't actually check what the hardware
160 // supports, so just allow sample rates of the "guaranteed working" ones.
161 // TODO(dalecurtis): If sample rates are added RecommendSampleFrameCount_1_1()
162 // must be updated to account for the new rates.
163 if (sample_rate
!= PP_AUDIOSAMPLERATE_44100
&&
164 sample_rate
!= PP_AUDIOSAMPLERATE_48000
)
167 // TODO(brettw): Currently we don't actually query to get a value from the
168 // hardware, so just validate the range.
169 if (sample_frame_count
> PP_AUDIOMAXSAMPLEFRAMECOUNT
||
170 sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
173 sample_rate_
= sample_rate
;
174 sample_frame_count_
= sample_frame_count
;