Chromium Code Reviews| Index: media/audio/audio_util.cc |
| =================================================================== |
| --- media/audio/audio_util.cc (revision 125439) |
| +++ media/audio/audio_util.cc (working copy) |
| @@ -57,7 +57,7 @@ |
| static const int kChannel_C = 2; |
| template<class Fixed, int min_value, int max_value> |
| -static int AddChannel(int val, int adder) { |
| +static int AddSaturated(int val, int adder) { |
| Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder); |
| if (sum > max_value) |
| return max_value; |
| @@ -93,9 +93,9 @@ |
| right = ScaleChannel<Fixed>(right, fixed_volume); |
| buf_out[0] = static_cast<Format>( |
| - AddChannel<Fixed, min_value, max_value>(left, center) + bias); |
| + AddSaturated<Fixed, min_value, max_value>(left, center) + bias); |
| buf_out[1] = static_cast<Format>( |
| - AddChannel<Fixed, min_value, max_value>(right, center) + bias); |
| + AddSaturated<Fixed, min_value, max_value>(right, center) + bias); |
| buf_out += 2; |
| buf_in += channels; |
| @@ -241,6 +241,67 @@ |
| } |
| } |
| +// TODO(enal): use template specialization and size-specific intrinsics. |
| +// Call is on the time-critical path, and by using SSE/AVX |
| +// instructions we can speed things up by ~4-8x, more for the case |
| +// when we have to adjust volume as well. |
| +template<class Format, class Fixed, int min_value, int max_value, int bias> |
| +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)
|
| + if (volume == 1.0f) { |
|
vrk (LEFT CHROMIUM)
2012/03/20 00:27:54
nit: It's cleaner/more concise if you push the if
|
| + // Most common case -- no need to adjust volume. |
| + for (int i = 0; i < count; ++i) { |
| + Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, |
| + src[i] - bias); |
| + dst[i] = static_cast<Format>(value + bias); |
| + } |
| + } else { |
| + // General case -- have to adjust volume before mixing. |
| + const int fixed_volume = static_cast<int>(volume * 65536); |
| + for (int i = 0; i < count; ++i) { |
| + Fixed adjusted_src = ScaleChannel<Fixed>(src[i] - bias, fixed_volume); |
| + Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, |
| + adjusted_src); |
| + dst[i] = static_cast<Format>(value + bias); |
| + } |
| + } |
| +} |
| + |
| +void MixStreams(void* dst, |
| + void* src, |
| + size_t buflen, |
| + int bytes_per_sample, |
| + float volume) { |
| + DCHECK(dst); |
| + DCHECK(src); |
| + 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)
|
| + switch (bytes_per_sample) { |
| + case 1: |
| + MixStreams<uint8, int32, -128, 127, 128>(static_cast<uint8*>(dst), |
| + static_cast<uint8*>(src), |
| + buflen, |
| + volume); |
| + break; |
| + case 2: |
| + DCHECK_EQ(0u, buflen % 2); |
| + MixStreams<int16, int32, -32768, 32767, 0>(static_cast<int16*>(dst), |
| + static_cast<int16*>(src), |
| + buflen / 2, |
| + volume); |
| + break; |
| + case 4: |
| + DCHECK_EQ(0u, buflen % 4); |
| + MixStreams<int32, int64, 0x80000000, 0x7fffffff, 0>( |
| + static_cast<int32*>(dst), |
| + static_cast<int32*>(src), |
| + buflen / 4, |
| + volume); |
| + break; |
| + default: |
| + NOTREACHED() << "Illegal bytes per sample"; |
| + break; |
| + } |
| +} |
| + |
| double GetAudioHardwareSampleRate() { |
| #if defined(OS_MACOSX) |
| // Hardware sample-rate on the Mac can be configured, so we must query. |