Chromium Code Reviews| 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 // Software adjust volume of samples, allows each audio stream its own | 5 // Software adjust volume of samples, allows each audio stream its own |
| 6 // volume without impacting master volume for chrome and other applications. | 6 // volume without impacting master volume for chrome and other applications. |
| 7 | 7 |
| 8 // Implemented as templates to allow 8, 16 and 32 bit implementations. | 8 // Implemented as templates to allow 8, 16 and 32 bit implementations. |
| 9 // 8 bit is unsigned and biased by 128. | 9 // 8 bit is unsigned and biased by 128. |
| 10 | 10 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias, | 50 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias, |
| 51 fixed_volume) + bias); | 51 fixed_volume) + bias); |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 | 54 |
| 55 static const int kChannel_L = 0; | 55 static const int kChannel_L = 0; |
| 56 static const int kChannel_R = 1; | 56 static const int kChannel_R = 1; |
| 57 static const int kChannel_C = 2; | 57 static const int kChannel_C = 2; |
| 58 | 58 |
| 59 template<class Fixed, int min_value, int max_value> | 59 template<class Fixed, int min_value, int max_value> |
| 60 static int AddChannel(int val, int adder) { | 60 static int AddSaturated(int val, int adder) { |
| 61 Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder); | 61 Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder); |
| 62 if (sum > max_value) | 62 if (sum > max_value) |
| 63 return max_value; | 63 return max_value; |
| 64 if (sum < min_value) | 64 if (sum < min_value) |
| 65 return min_value; | 65 return min_value; |
| 66 return static_cast<int>(sum); | 66 return static_cast<int>(sum); |
| 67 } | 67 } |
| 68 | 68 |
| 69 // FoldChannels() downmixes multichannel (ie 5.1 Surround Sound) to Stereo. | 69 // FoldChannels() downmixes multichannel (ie 5.1 Surround Sound) to Stereo. |
| 70 // Left and Right channels are preserved asis, and Center channel is | 70 // Left and Right channels are preserved asis, and Center channel is |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 86 for (int i = 0; i < sample_count; ++i) { | 86 for (int i = 0; i < sample_count; ++i) { |
| 87 int center = static_cast<int>(buf_in[kChannel_C] - bias); | 87 int center = static_cast<int>(buf_in[kChannel_C] - bias); |
| 88 int left = static_cast<int>(buf_in[kChannel_L] - bias); | 88 int left = static_cast<int>(buf_in[kChannel_L] - bias); |
| 89 int right = static_cast<int>(buf_in[kChannel_R] - bias); | 89 int right = static_cast<int>(buf_in[kChannel_R] - bias); |
| 90 | 90 |
| 91 center = ScaleChannel<Fixed>(center, center_volume); | 91 center = ScaleChannel<Fixed>(center, center_volume); |
| 92 left = ScaleChannel<Fixed>(left, fixed_volume); | 92 left = ScaleChannel<Fixed>(left, fixed_volume); |
| 93 right = ScaleChannel<Fixed>(right, fixed_volume); | 93 right = ScaleChannel<Fixed>(right, fixed_volume); |
| 94 | 94 |
| 95 buf_out[0] = static_cast<Format>( | 95 buf_out[0] = static_cast<Format>( |
| 96 AddChannel<Fixed, min_value, max_value>(left, center) + bias); | 96 AddSaturated<Fixed, min_value, max_value>(left, center) + bias); |
| 97 buf_out[1] = static_cast<Format>( | 97 buf_out[1] = static_cast<Format>( |
| 98 AddChannel<Fixed, min_value, max_value>(right, center) + bias); | 98 AddSaturated<Fixed, min_value, max_value>(right, center) + bias); |
| 99 | 99 |
| 100 buf_out += 2; | 100 buf_out += 2; |
| 101 buf_in += channels; | 101 buf_in += channels; |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 // AdjustVolume() does an in place audio sample change. | 105 // AdjustVolume() does an in place audio sample change. |
| 106 bool AdjustVolume(void* buf, | 106 bool AdjustVolume(void* buf, |
| 107 size_t buflen, | 107 size_t buflen, |
| 108 int channels, | 108 int channels, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 if (sample < -32768.0) | 234 if (sample < -32768.0) |
| 235 sample = -32768.0; | 235 sample = -32768.0; |
| 236 else if (sample > 32767.0) | 236 else if (sample > 32767.0) |
| 237 sample = 32767.0; | 237 sample = 32767.0; |
| 238 | 238 |
| 239 destination[j * channels + i] = static_cast<int16>(sample); | 239 destination[j * channels + i] = static_cast<int16>(sample); |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 | 243 |
| 244 // TODO(enal): use specialization and intrinsics. | |
|
vrk (LEFT CHROMIUM)
2012/03/12 18:40:24
What sort of specialization? Are intrinsics really
enal1
2012/03/12 21:20:53
Updated comment.
| |
| 245 template<class Format, class Fixed, int min_value, int max_value, int bias> | |
| 246 static void MixStreams(Format* dst, Format* src, int count, float volume) { | |
| 247 if (volume == 1.0f) { | |
| 248 // Most common case -- no need to adjust volume. | |
| 249 for (int i = 0; i < count; ++i) { | |
| 250 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
| 251 src[i] - bias); | |
| 252 dst[i] = static_cast<Format>(value + bias); | |
| 253 } | |
| 254 } else { | |
| 255 // General case -- have to adjust volume before mixing. | |
| 256 const int fixed_volume = static_cast<int>(volume * 65536); | |
|
vrk (LEFT CHROMIUM)
2012/03/12 18:40:24
why 65536/maxval of uint16?
enal1
2012/03/12 21:20:53
We are replacing FP multiplication by integer one.
vrk (LEFT CHROMIUM)
2012/03/20 00:27:53
OK... well, it's not code that you wrote, but it'd
| |
| 257 for (int i = 0; i < count; ++i) { | |
| 258 Fixed adjusted_src = ScaleChannel<Fixed>(src[i] - bias, fixed_volume); | |
| 259 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
| 260 adjusted_src); | |
| 261 dst[i] = static_cast<Format>(value + bias); | |
| 262 } | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 void MixStreams(void* dst, | |
| 267 void* src, | |
| 268 size_t buflen, | |
| 269 int bytes_per_sample, | |
| 270 float volume) { | |
| 271 DCHECK(dst); | |
| 272 DCHECK(src); | |
| 273 DCHECK(volume >= 0.0f && volume <= 1.0f); | |
| 274 switch (bytes_per_sample) { | |
| 275 case 1: | |
| 276 MixStreams<uint8, int32, -128, 127, 128>(static_cast<uint8*>(dst), | |
|
vrk (LEFT CHROMIUM)
2012/03/12 18:40:24
Why is the bias 128 here and 0 elsewhere?
enal1
2012/03/12 21:20:53
Because we have "unsigned char" for 8 bits and "si
enal1
2012/03/12 21:20:53
Because we have "unsigned char" for 8 bits and "si
| |
| 277 static_cast<uint8*>(src), | |
| 278 buflen, | |
| 279 volume); | |
| 280 break; | |
| 281 case 2: | |
| 282 DCHECK_EQ(0u, buflen % 2); | |
| 283 MixStreams<int16, int32, -32768, 32767, 0>(static_cast<int16*>(dst), | |
| 284 static_cast<int16*>(src), | |
| 285 buflen / 2, | |
| 286 volume); | |
| 287 break; | |
| 288 case 4: | |
| 289 DCHECK_EQ(0u, buflen % 4); | |
| 290 MixStreams<int32, int64, 0x80000000, 0x7fffffff, 0>( | |
| 291 static_cast<int32*>(dst), | |
| 292 static_cast<int32*>(src), | |
| 293 buflen / 4, | |
| 294 volume); | |
| 295 break; | |
| 296 default: | |
| 297 NOTREACHED() << "Illegal bytes per sample"; | |
| 298 break; | |
| 299 } | |
| 300 } | |
| 301 | |
| 244 double GetAudioHardwareSampleRate() { | 302 double GetAudioHardwareSampleRate() { |
| 245 #if defined(OS_MACOSX) | 303 #if defined(OS_MACOSX) |
| 246 // Hardware sample-rate on the Mac can be configured, so we must query. | 304 // Hardware sample-rate on the Mac can be configured, so we must query. |
| 247 return AUAudioOutputStream::HardwareSampleRate(); | 305 return AUAudioOutputStream::HardwareSampleRate(); |
| 248 #elif defined(OS_WIN) | 306 #elif defined(OS_WIN) |
| 249 if (!IsWASAPISupported()) { | 307 if (!IsWASAPISupported()) { |
| 250 // Fall back to Windows Wave implementation on Windows XP or lower | 308 // Fall back to Windows Wave implementation on Windows XP or lower |
| 251 // and use 48kHz as default input sample rate. | 309 // and use 48kHz as default input sample rate. |
| 252 return 48000.0; | 310 return 48000.0; |
| 253 } | 311 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 | 439 |
| 382 bool IsWASAPISupported() { | 440 bool IsWASAPISupported() { |
| 383 // Note: that function correctly returns that Windows Server 2003 does not | 441 // Note: that function correctly returns that Windows Server 2003 does not |
| 384 // support WASAPI. | 442 // support WASAPI. |
| 385 return base::win::GetVersion() >= base::win::VERSION_VISTA; | 443 return base::win::GetVersion() >= base::win::VERSION_VISTA; |
| 386 } | 444 } |
| 387 | 445 |
| 388 #endif | 446 #endif |
| 389 | 447 |
| 390 } // namespace media | 448 } // namespace media |
| OLD | NEW |