Index: media/base/audio_sample_conversion.h |
diff --git a/media/base/audio_sample_conversion.h b/media/base/audio_sample_conversion.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..836120b6edd232ae3c64ea66a55a38125867b3fa |
--- /dev/null |
+++ b/media/base/audio_sample_conversion.h |
@@ -0,0 +1,163 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |
+#define MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |
+ |
+#include <limits> |
+ |
+namespace media { |
+ |
+namespace internal { |
+ |
+template <typename T> |
+struct IntegerSampleTraits { |
+ typedef T promoted_type; |
+ static const T bias = 0; |
+ static promoted_type min() { return std::numeric_limits<T>::min(); } |
+ static promoted_type max() { return std::numeric_limits<T>::max(); } |
+}; |
+ |
+template <> |
+struct IntegerSampleTraits<uint8_t> { |
+ typedef int16_t promoted_type; |
+ static const uint8_t bias = 128; |
+ static promoted_type min() { return std::numeric_limits<int8_t>::min(); } |
+ static promoted_type max() { return std::numeric_limits<int8_t>::max(); } |
+}; |
+ |
+struct FloatToIntRounded { |
+ template <class T> |
+ static T FromPositive(float x) { |
+ return static_cast<T>(x + 0.5f); |
+ } |
+ |
+ template <class T> |
+ static T FromNegative(float x) { |
+ return static_cast<T>(x - 0.5f); |
+ } |
+}; |
+ |
+struct FloatToIntTruncated { |
+ template <class T> |
+ static T FromPositive(float x) { |
+ return static_cast<T>(x); |
+ } |
+ |
+ template <class T> |
+ static T FromNegative(float x) { |
+ return static_cast<T>(x); |
+ } |
+}; |
+ |
+template <typename Format, typename Rounding> |
+struct InterleaveOneChannelHelper { |
+ static void process(const float* channel_data, |
+ int start_frame, |
+ int frames, |
+ Format* dest, |
+ int channel_count, |
+ int ch) { |
+ using Traits = internal::IntegerSampleTraits<Format>; |
+ using Promoted = typename Traits::promoted_type; |
+ |
+ const Promoted min = Traits::min(); |
+ const Promoted max = Traits::max(); |
+ |
+ for (int i = start_frame, offset = ch; i < start_frame + frames; |
+ ++i, offset += channel_count) { |
+ const float v = channel_data[i]; |
+ |
+ Promoted sample; |
+ if (v < 0) |
+ sample = |
+ v <= -1 ? min : Rounding::template FromNegative<Promoted>(-v * min); |
+ else |
+ sample = |
+ v >= 1 ? max : Rounding::template FromPositive<Promoted>(v * max); |
+ |
+ dest[offset] = static_cast<Format>(sample) + Traits::bias; |
+ } |
+ } |
+}; |
+ |
+template <typename Rounding> |
+struct InterleaveOneChannelHelper<float, Rounding> { |
+ static void process(const float* channel_data, |
+ int start_frame, |
+ int frames, |
+ float* dest, |
+ int channel_count, |
+ int ch) { |
+ for (int i = start_frame, offset = ch; i < start_frame + frames; |
+ ++i, offset += channel_count) { |
+ dest[offset] = channel_data[i]; |
+ } |
+ } |
+}; |
+ |
+} // namespace internal |
+ |
+template <typename Format> |
+void DeinterleaveOneChannel(const Format* source, |
+ int start_frame, |
+ int frames, |
+ float* channel_data, |
+ int channel_count, |
+ int ch) { |
+ using Traits = internal::IntegerSampleTraits<Format>; |
+ using Promoted = typename Traits::promoted_type; |
+ |
+ const float min = 1.0f / Traits::min(); |
+ const float max = 1.0f / Traits::max(); |
+ |
+ for (int i = start_frame, offset = ch; i < start_frame + frames; |
+ ++i, offset += channel_count) { |
+ const Promoted v = static_cast<Promoted>(source[offset]) - Traits::bias; |
+ channel_data[i] = v * (v < 0 ? -min : max); |
+ } |
+} |
+ |
+template <> |
+inline void DeinterleaveOneChannel<float>(const float* source, |
+ int start_frame, |
+ int frames, |
+ float* channel_data, |
+ int channel_count, |
+ int ch) { |
+ for (int i = start_frame, offset = ch; i < start_frame + frames; |
+ ++i, offset += channel_count) { |
+ channel_data[i] = source[offset]; |
+ } |
+} |
+ |
+template <typename Format> |
+void InterleaveOneChannel(const float* channel_data, |
+ int start_frame, |
+ int frames, |
+ Format* dest, |
+ int channel_count, |
+ int ch) { |
+ internal::InterleaveOneChannelHelper< |
+ Format, internal::FloatToIntTruncated>::process(channel_data, start_frame, |
+ frames, dest, |
+ channel_count, ch); |
+} |
+ |
+template <typename Format> |
+void InterleaveOneChannelRounded(const float* channel_data, |
+ int start_frame, |
+ int frames, |
+ Format* dest, |
+ int channel_count, |
+ int ch) { |
+ internal::InterleaveOneChannelHelper< |
+ Format, internal::FloatToIntRounded>::process(channel_data, start_frame, |
+ frames, dest, channel_count, |
+ ch); |
+} |
+ |
+} // namespace media |
+ |
+#endif // MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |