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 template specialization and size-specific intrinsics. | |
| 245 // Call is on the time-critical path, and by using SSE/AVX | |
| 246 // instructions we can speed things up by ~4-8x, more for the case | |
| 247 // when we have to adjust volume as well. | |
| 248 template<class Format, class Fixed, int min_value, int max_value, int bias> | |
| 249 static void MixStreams(Format* dst, Format* src, int count, float volume) { | |
|
vrk (LEFT CHROMIUM)
2012/03/20 00:27:54
Return early for muted src?
if (volume == 0.0f)
| |
| 250 if (volume == 1.0f) { | |
|
vrk (LEFT CHROMIUM)
2012/03/20 00:27:54
nit: It's cleaner/more concise if you push the if
| |
| 251 // Most common case -- no need to adjust volume. | |
| 252 for (int i = 0; i < count; ++i) { | |
| 253 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
| 254 src[i] - bias); | |
| 255 dst[i] = static_cast<Format>(value + bias); | |
| 256 } | |
| 257 } else { | |
| 258 // General case -- have to adjust volume before mixing. | |
| 259 const int fixed_volume = static_cast<int>(volume * 65536); | |
| 260 for (int i = 0; i < count; ++i) { | |
| 261 Fixed adjusted_src = ScaleChannel<Fixed>(src[i] - bias, fixed_volume); | |
| 262 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
| 263 adjusted_src); | |
| 264 dst[i] = static_cast<Format>(value + bias); | |
| 265 } | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 void MixStreams(void* dst, | |
| 270 void* src, | |
| 271 size_t buflen, | |
| 272 int bytes_per_sample, | |
| 273 float volume) { | |
| 274 DCHECK(dst); | |
| 275 DCHECK(src); | |
| 276 DCHECK(volume >= 0.0f && volume <= 1.0f); | |
|
vrk (LEFT CHROMIUM)
2012/03/20 00:27:54
nit: two separate DCHECKs, DCHECK_GE(volume, 0.0f)
| |
| 277 switch (bytes_per_sample) { | |
| 278 case 1: | |
| 279 MixStreams<uint8, int32, -128, 127, 128>(static_cast<uint8*>(dst), | |
| 280 static_cast<uint8*>(src), | |
| 281 buflen, | |
| 282 volume); | |
| 283 break; | |
| 284 case 2: | |
| 285 DCHECK_EQ(0u, buflen % 2); | |
| 286 MixStreams<int16, int32, -32768, 32767, 0>(static_cast<int16*>(dst), | |
| 287 static_cast<int16*>(src), | |
| 288 buflen / 2, | |
| 289 volume); | |
| 290 break; | |
| 291 case 4: | |
| 292 DCHECK_EQ(0u, buflen % 4); | |
| 293 MixStreams<int32, int64, 0x80000000, 0x7fffffff, 0>( | |
| 294 static_cast<int32*>(dst), | |
| 295 static_cast<int32*>(src), | |
| 296 buflen / 4, | |
| 297 volume); | |
| 298 break; | |
| 299 default: | |
| 300 NOTREACHED() << "Illegal bytes per sample"; | |
| 301 break; | |
| 302 } | |
| 303 } | |
| 304 | |
| 244 double GetAudioHardwareSampleRate() { | 305 double GetAudioHardwareSampleRate() { |
| 245 #if defined(OS_MACOSX) | 306 #if defined(OS_MACOSX) |
| 246 // Hardware sample-rate on the Mac can be configured, so we must query. | 307 // Hardware sample-rate on the Mac can be configured, so we must query. |
| 247 return AUAudioOutputStream::HardwareSampleRate(); | 308 return AUAudioOutputStream::HardwareSampleRate(); |
| 248 #elif defined(OS_WIN) | 309 #elif defined(OS_WIN) |
| 249 if (!IsWASAPISupported()) { | 310 if (!IsWASAPISupported()) { |
| 250 // Fall back to Windows Wave implementation on Windows XP or lower | 311 // Fall back to Windows Wave implementation on Windows XP or lower |
| 251 // and use 48kHz as default input sample rate. | 312 // and use 48kHz as default input sample rate. |
| 252 return 48000.0; | 313 return 48000.0; |
| 253 } | 314 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 | 442 |
| 382 bool IsWASAPISupported() { | 443 bool IsWASAPISupported() { |
| 383 // Note: that function correctly returns that Windows Server 2003 does not | 444 // Note: that function correctly returns that Windows Server 2003 does not |
| 384 // support WASAPI. | 445 // support WASAPI. |
| 385 return base::win::GetVersion() >= base::win::VERSION_VISTA; | 446 return base::win::GetVersion() >= base::win::VERSION_VISTA; |
| 386 } | 447 } |
| 387 | 448 |
| 388 #endif | 449 #endif |
| 389 | 450 |
| 390 } // namespace media | 451 } // namespace media |
| OLD | NEW |