blob: e91610f3aaa1a8df16856f6b60e9575f7a775946 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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.
4
5// Software adjust volume of samples, allows each audio stream its own
6// volume without impacting master volume for chrome and other applications.
7
8// Implemented as templates to allow 8, 16 and 32 bit implementations.
9// 8 bit is unsigned and biased by 128.
10
11// TODO(vrk): This file has been running pretty wild and free, and it's likely
12// that a lot of the functions can be simplified and made more elegant. Revisit
13// after other audio cleanup is done. (crbug.com/120319)
14
15#include "media/audio/audio_util.h"
16
17#include <algorithm>
18#include <limits>
19
20#include "base/basictypes.h"
21#include "base/command_line.h"
22#include "base/logging.h"
23#include "base/string_number_conversions.h"
24#include "base/time.h"
25#include "media/audio/audio_parameters.h"
26#include "media/base/audio_bus.h"
27#include "media/base/media_switches.h"
28
29#if defined(OS_MACOSX)
30#include "media/audio/mac/audio_low_latency_input_mac.h"
31#include "media/audio/mac/audio_low_latency_output_mac.h"
32#elif defined(OS_WIN)
33#include "base/win/windows_version.h"
34#include "media/audio/audio_manager_base.h"
35#include "media/audio/win/audio_low_latency_input_win.h"
36#include "media/audio/win/audio_low_latency_output_win.h"
37#include "media/audio/win/core_audio_util_win.h"
38#include "media/base/limits.h"
39#endif
40
41namespace media {
42
43// Returns user buffer size as specified on the command line or 0 if no buffer
44// size has been specified.
45static int GetUserBufferSize() {
46 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
47 int buffer_size = 0;
48 std::string buffer_size_str(cmd_line->GetSwitchValueASCII(
49 switches::kAudioBufferSize));
50 if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0) {
51 return buffer_size;
52 }
53
54 return 0;
55}
56
57// TODO(fbarchard): Convert to intrinsics for better efficiency.
58template<class Fixed>
59static int ScaleChannel(int channel, int volume) {
60 return static_cast<int>((static_cast<Fixed>(channel) * volume) >> 16);
61}
62
63template<class Format, class Fixed, int bias>
64static void AdjustVolume(Format* buf_out,
65 int sample_count,
66 int fixed_volume) {
67 for (int i = 0; i < sample_count; ++i) {
68 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias,
69 fixed_volume) + bias);
70 }
71}
72
73template<class Fixed, int min_value, int max_value>
74static int AddSaturated(int val, int adder) {
75 Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder);
76 if (sum > max_value)
77 return max_value;
78 if (sum < min_value)
79 return min_value;
80 return static_cast<int>(sum);
81}
82
83// AdjustVolume() does an in place audio sample change.
84bool AdjustVolume(void* buf,
85 size_t buflen,
86 int channels,
87 int bytes_per_sample,
88 float volume) {
89 DCHECK(buf);
90 if (volume < 0.0f || volume > 1.0f)
91 return false;
92 if (volume == 1.0f) {
93 return true;
94 } else if (volume == 0.0f) {
95 memset(buf, 0, buflen);
96 return true;
97 }
98 if (channels > 0 && channels <= 8 && bytes_per_sample > 0) {
99 int sample_count = buflen / bytes_per_sample;
100 const int fixed_volume = static_cast<int>(volume * 65536);
101 if (bytes_per_sample == 1) {
102 AdjustVolume<uint8, int32, 128>(reinterpret_cast<uint8*>(buf),
103 sample_count,
104 fixed_volume);
105 return true;
106 } else if (bytes_per_sample == 2) {
107 AdjustVolume<int16, int32, 0>(reinterpret_cast<int16*>(buf),
108 sample_count,
109 fixed_volume);
110 return true;
111 } else if (bytes_per_sample == 4) {
112 AdjustVolume<int32, int64, 0>(reinterpret_cast<int32*>(buf),
113 sample_count,
114 fixed_volume);
115 return true;
116 }
117 }
118 return false;
119}
120
121// TODO(enal): use template specialization and size-specific intrinsics.
122// Call is on the time-critical path, and by using SSE/AVX
123// instructions we can speed things up by ~4-8x, more for the case
124// when we have to adjust volume as well.
125template<class Format, class Fixed, int min_value, int max_value, int bias>
126static void MixStreams(Format* dst, Format* src, int count, float volume) {
127 if (volume == 0.0f)
128 return;
129 if (volume == 1.0f) {
130 // Most common case -- no need to adjust volume.
131 for (int i = 0; i < count; ++i) {
132 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias,
133 src[i] - bias);
134 dst[i] = static_cast<Format>(value + bias);
135 }
136 } else {
137 // General case -- have to adjust volume before mixing.
138 const int fixed_volume = static_cast<int>(volume * 65536);
139 for (int i = 0; i < count; ++i) {
140 Fixed adjusted_src = ScaleChannel<Fixed>(src[i] - bias, fixed_volume);
141 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias,
142 adjusted_src);
143 dst[i] = static_cast<Format>(value + bias);
144 }
145 }
146}
147
148void MixStreams(void* dst,
149 void* src,
150 size_t buflen,
151 int bytes_per_sample,
152 float volume) {
153 DCHECK(dst);
154 DCHECK(src);
155 DCHECK_GE(volume, 0.0f);
156 DCHECK_LE(volume, 1.0f);
157 switch (bytes_per_sample) {
158 case 1:
159 MixStreams<uint8, int32, kint8min, kint8max, 128>(
160 static_cast<uint8*>(dst),
161 static_cast<uint8*>(src),
162 buflen,
163 volume);
164 break;
165 case 2:
166 DCHECK_EQ(0u, buflen % 2);
167 MixStreams<int16, int32, kint16min, kint16max, 0>(
168 static_cast<int16*>(dst),
169 static_cast<int16*>(src),
170 buflen / 2,
171 volume);
172 break;
173 case 4:
174 DCHECK_EQ(0u, buflen % 4);
175 MixStreams<int32, int64, kint32min, kint32max, 0>(
176 static_cast<int32*>(dst),
177 static_cast<int32*>(src),
178 buflen / 4,
179 volume);
180 break;
181 default:
182 NOTREACHED() << "Illegal bytes per sample";
183 break;
184 }
185}
186
187int GetAudioHardwareSampleRate() {
188#if defined(OS_MACOSX)
189 // Hardware sample-rate on the Mac can be configured, so we must query.
190 return AUAudioOutputStream::HardwareSampleRate();
191#elif defined(OS_WIN)
192 if (!CoreAudioUtil::IsSupported()) {
193 // Fall back to Windows Wave implementation on Windows XP or lower
194 // and use 48kHz as default input sample rate.
195 return 48000;
196 }
197
198 // TODO(crogers): tune this rate for best possible WebAudio performance.
199 // WebRTC works well at 48kHz and a buffer size of 480 samples will be used
200 // for this case. Note that exclusive mode is experimental.
201 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
202 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
203 // This sample rate will be combined with a buffer size of 256 samples
204 // (see GetAudioHardwareBufferSize()), which corresponds to an output
205 // delay of ~5.33ms.
206 return 48000;
207 }
208
209 // Hardware sample-rate on Windows can be configured, so we must query.
210 // TODO(henrika): improve possibility to specify an audio endpoint.
211 // Use the default device (same as for Wave) for now to be compatible
212 // or possibly remove the ERole argument completely until it is in use.
213 return WASAPIAudioOutputStream::HardwareSampleRate(eConsole);
214#elif defined(OS_ANDROID)
215 return 16000;
216#else
217 // Hardware for Linux is nearly always 48KHz.
218 // TODO(crogers) : return correct value in rare non-48KHz cases.
219 return 48000;
220#endif
221}
222
223int GetAudioInputHardwareSampleRate(const std::string& device_id) {
224 // TODO(henrika): add support for device selection on all platforms.
225 // Only exists on Windows today.
226#if defined(OS_MACOSX)
227 return AUAudioInputStream::HardwareSampleRate();
228#elif defined(OS_WIN)
229 if (!CoreAudioUtil::IsSupported()) {
230 return 48000;
231 }
232 return WASAPIAudioInputStream::HardwareSampleRate(device_id);
233#elif defined(OS_ANDROID)
234 return 16000;
235#else
236 return 48000;
237#endif
238}
239
240size_t GetAudioHardwareBufferSize() {
241 int user_buffer_size = GetUserBufferSize();
242 if (user_buffer_size)
243 return user_buffer_size;
244
245 // The sizes here were determined by experimentation and are roughly
246 // the lowest value (for low latency) that still allowed glitch-free
247 // audio under high loads.
248 //
249 // For Mac OS X and Windows the chromium audio backend uses a low-latency
250 // Core Audio API, so a low buffer size is possible. For Linux, further
251 // tuning may be needed.
252#if defined(OS_MACOSX)
253 return 128;
254#elif defined(OS_WIN)
255 // Buffer size to use when a proper size can't be determined from the system.
256 static const int kFallbackBufferSize = 4096;
257
258 if (!CoreAudioUtil::IsSupported()) {
259 // Fall back to Windows Wave implementation on Windows XP or lower
260 // and assume 48kHz as default sample rate.
261 return kFallbackBufferSize;
262 }
263
264 // TODO(crogers): tune this size to best possible WebAudio performance.
265 // WebRTC always uses 10ms for Windows and does not call this method.
266 // Note that exclusive mode is experimental.
267 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
268 if (cmd_line->HasSwitch(switches::kEnableExclusiveAudio)) {
269 return 256;
270 }
271
272 // TODO(henrika): remove when the --enable-webaudio-input flag is no longer
273 // utilized.
274 if (cmd_line->HasSwitch(switches::kEnableWebAudioInput)) {
275 AudioParameters params;
276 HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(eRender, eConsole,
277 &params);
278 return FAILED(hr) ? kFallbackBufferSize : params.frames_per_buffer();
279 }
280
281 // This call must be done on a COM thread configured as MTA.
282 // TODO(tommi): http://code.google.com/p/chromium/issues/detail?id=103835.
283 int mixing_sample_rate =
284 WASAPIAudioOutputStream::HardwareSampleRate(eConsole);
285
286 // Windows will return a sample rate of 0 when no audio output is available
287 // (i.e. via RemoteDesktop with remote audio disabled), but we should never
288 // return a buffer size of zero.
289 if (mixing_sample_rate == 0)
290 return kFallbackBufferSize;
291
292 // Use different buffer sizes depening on the sample rate . The existing
293 // WASAPI implementation is tuned to provide the most stable callback
294 // sequence using these combinations.
295 if (mixing_sample_rate % 11025 == 0)
296 // Use buffer size of ~10.15873 ms.
297 return (112 * (mixing_sample_rate / 11025));
298
299 if (mixing_sample_rate % 8000 == 0)
300 // Use buffer size of 10ms.
301 return (80 * (mixing_sample_rate / 8000));
302
303 // Ensure we always return a buffer size which is somewhat appropriate.
304 LOG(ERROR) << "Unknown sample rate " << mixing_sample_rate << " detected.";
305 if (mixing_sample_rate > limits::kMinSampleRate)
306 return (mixing_sample_rate / 100);
307 return kFallbackBufferSize;
308#else
309 return 2048;
310#endif
311}
312
313ChannelLayout GetAudioInputHardwareChannelLayout(const std::string& device_id) {
314 // TODO(henrika): add support for device selection on all platforms.
315 // Only exists on Windows today.
316#if defined(OS_MACOSX)
317 return CHANNEL_LAYOUT_MONO;
318#elif defined(OS_WIN)
319 if (!CoreAudioUtil::IsSupported()) {
320 // Fall back to Windows Wave implementation on Windows XP or lower and
321 // use stereo by default.
322 return CHANNEL_LAYOUT_STEREO;
323 }
324 return WASAPIAudioInputStream::HardwareChannelCount(device_id) == 1 ?
325 CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO;
326#else
327 return CHANNEL_LAYOUT_STEREO;
328#endif
329}
330
331// Computes a buffer size based on the given |sample_rate|. Must be used in
332// conjunction with AUDIO_PCM_LINEAR.
333size_t GetHighLatencyOutputBufferSize(int sample_rate) {
334 int user_buffer_size = GetUserBufferSize();
335 if (user_buffer_size)
336 return user_buffer_size;
337
338 // TODO(vrk/crogers): The buffer sizes that this function computes is probably
339 // overly conservative. However, reducing the buffer size to 2048-8192 bytes
340 // caused crbug.com/108396. This computation should be revisited while making
341 // sure crbug.com/108396 doesn't happen again.
342
343 // The minimum number of samples in a hardware packet.
344 // This value is selected so that we can handle down to 5khz sample rate.
345 static const size_t kMinSamplesPerHardwarePacket = 1024;
346
347 // The maximum number of samples in a hardware packet.
348 // This value is selected so that we can handle up to 192khz sample rate.
349 static const size_t kMaxSamplesPerHardwarePacket = 64 * 1024;
350
351 // This constant governs the hardware audio buffer size, this value should be
352 // chosen carefully.
353 // This value is selected so that we have 8192 samples for 48khz streams.
354 static const size_t kMillisecondsPerHardwarePacket = 170;
355
356 // Select the number of samples that can provide at least
357 // |kMillisecondsPerHardwarePacket| worth of audio data.
358 size_t samples = kMinSamplesPerHardwarePacket;
359 while (samples <= kMaxSamplesPerHardwarePacket &&
360 samples * base::Time::kMillisecondsPerSecond <
361 sample_rate * kMillisecondsPerHardwarePacket) {
362 samples *= 2;
363 }
364 return samples;
365}
366
367#if defined(OS_WIN)
368
369int NumberOfWaveOutBuffers() {
370 // Use 4 buffers for Vista, 3 for everyone else:
371 // - The entire Windows audio stack was rewritten for Windows Vista and wave
372 // out performance was degraded compared to XP.
373 // - The regression was fixed in Windows 7 and most configurations will work
374 // with 2, but some (e.g., some Sound Blasters) still need 3.
375 // - Some XP configurations (even multi-processor ones) also need 3.
376 return (base::win::GetVersion() == base::win::VERSION_VISTA) ? 4 : 3;
377}
378
379#endif
380
381} // namespace media