diff options
author | vrk@google.com <vrk@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-02 21:48:58 +0000 |
---|---|---|
committer | vrk@google.com <vrk@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-02 21:48:58 +0000 |
commit | dba3b696014a982e3886ef1c4a3be8164f5ce989 (patch) | |
tree | e2024bb98f4f384eaed53e52c773ca647ce25254 /media/audio | |
parent | 089aabb81fbca67252fd49526f67174ac2e95b8c (diff) | |
download | chromium_src-dba3b696014a982e3886ef1c4a3be8164f5ce989.zip chromium_src-dba3b696014a982e3886ef1c4a3be8164f5ce989.tar.gz chromium_src-dba3b696014a982e3886ef1c4a3be8164f5ce989.tar.bz2 |
Change InterleaveFloatToInt16() to work with uint8 and int32
Parts of the AudioDevice code assumed 16-bit audio, which broke the 8-bit
audio case. This CL gets rid of that assumption.
BUG=120168
TEST=8-bit audio streams play correctly
Review URL: https://chromiumcodereview.appspot.com/9864016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio')
-rw-r--r-- | media/audio/audio_util.cc | 60 | ||||
-rw-r--r-- | media/audio/audio_util.h | 11 |
2 files changed, 53 insertions, 18 deletions
diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc index 5f490af..c15e845 100644 --- a/media/audio/audio_util.cc +++ b/media/audio/audio_util.cc @@ -8,7 +8,12 @@ // Implemented as templates to allow 8, 16 and 32 bit implementations. // 8 bit is unsigned and biased by 128. +// TODO(vrk): This file has been running pretty wild and free, and it's likely +// that a lot of the functions can be simplified and made more elegant. Revisit +// after other audio cleanup is done. (crbug.com/120319) + #include <algorithm> +#include <limits> #include "base/atomicops.h" #include "base/basictypes.h" @@ -185,7 +190,7 @@ bool DeinterleaveAudioChannel(void* source, switch (bytes_per_sample) { case 1: { - uint8* source8 = static_cast<uint8*>(source) + channel_index; + uint8* source8 = reinterpret_cast<uint8*>(source) + channel_index; const float kScale = 1.0f / 128.0f; for (unsigned i = 0; i < number_of_frames; ++i) { destination[i] = kScale * (static_cast<int>(*source8) - 128); @@ -196,7 +201,7 @@ bool DeinterleaveAudioChannel(void* source, case 2: { - int16* source16 = static_cast<int16*>(source) + channel_index; + int16* source16 = reinterpret_cast<int16*>(source) + channel_index; const float kScale = 1.0f / 32768.0f; for (unsigned i = 0; i < number_of_frames; ++i) { destination[i] = kScale * *source16; @@ -207,7 +212,7 @@ bool DeinterleaveAudioChannel(void* source, case 4: { - int32* source32 = static_cast<int32*>(source) + channel_index; + int32* source32 = reinterpret_cast<int32*>(source) + channel_index; const float kScale = 1.0f / (1L << 31); for (unsigned i = 0; i < number_of_frames; ++i) { destination[i] = kScale * *source32; @@ -222,25 +227,54 @@ bool DeinterleaveAudioChannel(void* source, return false; } -void InterleaveFloatToInt16(const std::vector<float*>& source, - int16* destination, - size_t number_of_frames) { - const float kScale = 32768.0f; +// |Format| is the destination type, |Fixed| is a type larger than |Format| +// such that operations can be made without overflowing. +template<class Format, class Fixed> +static void InterleaveFloatToInt(const std::vector<float*>& source, + void* dst_bytes, size_t number_of_frames) { + Format* destination = reinterpret_cast<Format*>(dst_bytes); + Fixed max_value = std::numeric_limits<Format>::max(); + Fixed min_value = std::numeric_limits<Format>::min(); + + Format bias = 0; + if (!std::numeric_limits<Format>::is_signed) { + bias = max_value / 2; + max_value = bias; + min_value = -(bias - 1); + } + int channels = source.size(); for (int i = 0; i < channels; ++i) { float* channel_data = source[i]; for (size_t j = 0; j < number_of_frames; ++j) { - float sample = kScale * channel_data[j]; - if (sample < -32768.0) - sample = -32768.0; - else if (sample > 32767.0) - sample = 32767.0; + Fixed sample = max_value * channel_data[j]; + if (sample > max_value) + sample = max_value; + else if (sample < min_value) + sample = min_value; - destination[j * channels + i] = static_cast<int16>(sample); + destination[j * channels + i] = static_cast<Format>(sample) + bias; } } } +void InterleaveFloatToInt(const std::vector<float*>& source, void* dst, + size_t number_of_frames, int bytes_per_sample) { + switch(bytes_per_sample) { + case 1: + InterleaveFloatToInt<uint8, int32>(source, dst, number_of_frames); + break; + case 2: + InterleaveFloatToInt<int16, int32>(source, dst, number_of_frames); + break; + case 4: + InterleaveFloatToInt<int32, int64>(source, dst, number_of_frames); + break; + default: + break; + } +} + // 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 diff --git a/media/audio/audio_util.h b/media/audio/audio_util.h index 11ee38e..2fccc1e 100644 --- a/media/audio/audio_util.h +++ b/media/audio/audio_util.h @@ -80,15 +80,16 @@ MEDIA_EXPORT bool DeinterleaveAudioChannel(void* source, int bytes_per_sample, size_t number_of_frames); -// InterleaveFloatToInt16 scales, clips, and interleaves the planar -// floating-point audio contained in |source| to the int16 |destination|. +// InterleaveFloatToInt scales, clips, and interleaves the planar +// floating-point audio contained in |source| to the |destination|. // The floating-point data is in a canonical range of -1.0 -> +1.0. // The size of the |source| vector determines the number of channels. // The |destination| buffer is assumed to be large enough to hold the // result. Thus it must be at least size: number_of_frames * source.size() -MEDIA_EXPORT void InterleaveFloatToInt16(const std::vector<float*>& source, - int16* destination, - size_t number_of_frames); +MEDIA_EXPORT void InterleaveFloatToInt(const std::vector<float*>& source, + void* destination, + size_t number_of_frames, + int bytes_per_sample); // Returns the default audio output hardware sample-rate. MEDIA_EXPORT int GetAudioHardwareSampleRate(); |