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 "ppapi/shared_impl/ppb_audio_config_shared.h"
6 #include "ppapi/thunk/enter.h"
7 #include "ppapi/thunk/ppb_instance_api.h"
11 // Rounds up requested_size to the nearest multiple of minimum_size.
12 static uint32_t CalculateMultipleOfSampleFrameCount(uint32_t minimum_size
,
13 uint32_t requested_size
) {
14 const uint32_t multiple
= (requested_size
+ minimum_size
- 1) / minimum_size
;
15 return std::min(minimum_size
* multiple
,
16 static_cast<uint32_t>(PP_AUDIOMAXSAMPLEFRAMECOUNT
));
19 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type
,
21 : Resource(type
, instance
),
22 sample_rate_(PP_AUDIOSAMPLERATE_NONE
),
23 sample_frame_count_(0) {
26 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() {
29 PP_Resource
PPB_AudioConfig_Shared::Create(
30 ResourceObjectType type
,
32 PP_AudioSampleRate sample_rate
,
33 uint32_t sample_frame_count
) {
34 scoped_refptr
<PPB_AudioConfig_Shared
> object(
35 new PPB_AudioConfig_Shared(type
, instance
));
36 if (!object
->Init(sample_rate
, sample_frame_count
))
38 return object
->GetReference();
42 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_0(
43 PP_AudioSampleRate sample_rate
,
44 uint32_t requested_sample_frame_count
) {
45 // Version 1.0: Don't actually query to get a value from the
46 // hardware; instead return the input for in-range values.
47 if (requested_sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
48 return PP_AUDIOMINSAMPLEFRAMECOUNT
;
49 if (requested_sample_frame_count
> PP_AUDIOMAXSAMPLEFRAMECOUNT
)
50 return PP_AUDIOMAXSAMPLEFRAMECOUNT
;
51 return requested_sample_frame_count
;
55 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_1(
57 PP_AudioSampleRate sample_rate
,
58 uint32_t sample_frame_count
) {
59 // Version 1.1: Query the back-end hardware for sample rate and buffer size,
60 // and recommend a best fit based on request.
61 thunk::EnterInstanceNoLock
enter(instance
);
65 // Get the hardware config.
66 PP_AudioSampleRate hardware_sample_rate
= static_cast<PP_AudioSampleRate
>(
67 enter
.functions()->GetAudioHardwareOutputSampleRate(instance
));
68 uint32_t hardware_sample_frame_count
=
69 enter
.functions()->GetAudioHardwareOutputBufferSize(instance
);
70 if (sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
71 sample_frame_count
= PP_AUDIOMINSAMPLEFRAMECOUNT
;
73 // If hardware information isn't available we're connected to a fake audio
74 // output stream on the browser side, so we can use whatever sample count the
76 if (!hardware_sample_frame_count
|| !hardware_sample_rate
)
77 return sample_frame_count
;
79 // Note: All the values below were determined through experimentation to
80 // minimize jitter and back-to-back callbacks from the browser. Please take
81 // care when modifying these values as they impact a large number of users.
82 // TODO(dalecurtis): Land jitter test and add documentation for updating this.
84 // If client is using same sample rate as audio hardware, then recommend a
85 // multiple of the audio hardware's sample frame count.
86 if (hardware_sample_rate
== sample_rate
) {
87 return CalculateMultipleOfSampleFrameCount(
88 hardware_sample_frame_count
, sample_frame_count
);
91 // Should track the value reported by XP and ALSA backends.
92 const uint32_t kHighLatencySampleFrameCount
= 2048;
94 // If the hardware requires a high latency buffer or we're at a low sample
95 // rate w/ a buffer that's larger than 10ms, choose the nearest multiple of
96 // the high latency sample frame count. An example of too low and too large
97 // is 16kHz and a sample frame count greater than 160 frames.
98 if (hardware_sample_frame_count
>= kHighLatencySampleFrameCount
||
99 (hardware_sample_rate
< 44100 &&
100 hardware_sample_frame_count
> hardware_sample_rate
/ 100u)) {
101 return CalculateMultipleOfSampleFrameCount(
103 std::max(kHighLatencySampleFrameCount
, hardware_sample_frame_count
));
106 // All low latency clients should be able to handle a 512 frame buffer with
107 // resampling from 44.1kHz and 48kHz to higher sample rates.
108 // TODO(dalecurtis): We may need to investigate making the callback thread
109 // high priority to handle buffers at the absolute minimum w/o glitching.
110 const uint32_t kLowLatencySampleFrameCount
= 512;
112 // Special case for 48kHz -> 44.1kHz and buffer sizes greater than 10ms. In
113 // testing most buffer sizes > 10ms led to glitching, so we choose a size we
114 // know won't cause jitter.
115 int min_sample_frame_count
= kLowLatencySampleFrameCount
;
116 if (hardware_sample_rate
== 44100 && sample_rate
== 48000 &&
117 hardware_sample_frame_count
> hardware_sample_rate
/ 100u) {
118 min_sample_frame_count
= std::max(
119 2 * kLowLatencySampleFrameCount
, hardware_sample_frame_count
);
122 return CalculateMultipleOfSampleFrameCount(
123 min_sample_frame_count
, sample_frame_count
);
127 PP_AudioSampleRate
PPB_AudioConfig_Shared::RecommendSampleRate(
128 PP_Instance instance
) {
129 thunk::EnterInstanceNoLock
enter(instance
);
131 return PP_AUDIOSAMPLERATE_NONE
;
132 PP_AudioSampleRate hardware_sample_rate
= static_cast<PP_AudioSampleRate
>(
133 enter
.functions()->GetAudioHardwareOutputSampleRate(instance
));
134 return hardware_sample_rate
;
137 thunk::PPB_AudioConfig_API
* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() {
141 PP_AudioSampleRate
PPB_AudioConfig_Shared::GetSampleRate() {
145 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() {
146 return sample_frame_count_
;
149 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate
,
150 uint32_t sample_frame_count
) {
151 // TODO(brettw): Currently we don't actually check what the hardware
152 // supports, so just allow sample rates of the "guaranteed working" ones.
153 // TODO(dalecurtis): If sample rates are added RecommendSampleFrameCount_1_1()
154 // must be updated to account for the new rates.
155 if (sample_rate
!= PP_AUDIOSAMPLERATE_44100
&&
156 sample_rate
!= PP_AUDIOSAMPLERATE_48000
)
159 // TODO(brettw): Currently we don't actually query to get a value from the
160 // hardware, so just validate the range.
161 if (sample_frame_count
> PP_AUDIOMAXSAMPLEFRAMECOUNT
||
162 sample_frame_count
< PP_AUDIOMINSAMPLEFRAMECOUNT
)
165 sample_rate_
= sample_rate
;
166 sample_frame_count_
= sample_frame_count
;