summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorvrk@google.com <vrk@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-02 21:48:58 +0000
committervrk@google.com <vrk@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-02 21:48:58 +0000
commitdba3b696014a982e3886ef1c4a3be8164f5ce989 (patch)
treee2024bb98f4f384eaed53e52c773ca647ce25254 /media
parent089aabb81fbca67252fd49526f67174ac2e95b8c (diff)
downloadchromium_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')
-rw-r--r--media/audio/audio_util.cc60
-rw-r--r--media/audio/audio_util.h11
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();