OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |
| 6 #define MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |
| 7 |
| 8 #include <limits> |
| 9 |
| 10 namespace media { |
| 11 |
| 12 namespace internal { |
| 13 |
| 14 template <typename T> |
| 15 struct IntegerSampleTraits { |
| 16 typedef T promoted_type; |
| 17 static const T bias = 0; |
| 18 static promoted_type min() { return std::numeric_limits<T>::min(); } |
| 19 static promoted_type max() { return std::numeric_limits<T>::max(); } |
| 20 }; |
| 21 |
| 22 template <> |
| 23 struct IntegerSampleTraits<uint8_t> { |
| 24 typedef int16_t promoted_type; |
| 25 static const uint8_t bias = 128; |
| 26 static promoted_type min() { return std::numeric_limits<int8_t>::min(); } |
| 27 static promoted_type max() { return std::numeric_limits<int8_t>::max(); } |
| 28 }; |
| 29 |
| 30 struct FloatToIntRounded { |
| 31 template <class T> |
| 32 static T FromPositive(float x) { |
| 33 return static_cast<T>(x + 0.5f); |
| 34 } |
| 35 |
| 36 template <class T> |
| 37 static T FromNegative(float x) { |
| 38 return static_cast<T>(x - 0.5f); |
| 39 } |
| 40 }; |
| 41 |
| 42 struct FloatToIntTruncated { |
| 43 template <class T> |
| 44 static T FromPositive(float x) { |
| 45 return static_cast<T>(x); |
| 46 } |
| 47 |
| 48 template <class T> |
| 49 static T FromNegative(float x) { |
| 50 return static_cast<T>(x); |
| 51 } |
| 52 }; |
| 53 |
| 54 template <typename Format, typename Rounding> |
| 55 struct InterleaveOneChannelHelper { |
| 56 static void process(const float* channel_data, |
| 57 int start_frame, |
| 58 int frames, |
| 59 Format* dest, |
| 60 int channel_count, |
| 61 int ch) { |
| 62 using Traits = internal::IntegerSampleTraits<Format>; |
| 63 using Promoted = typename Traits::promoted_type; |
| 64 |
| 65 const Promoted min = Traits::min(); |
| 66 const Promoted max = Traits::max(); |
| 67 |
| 68 for (int i = start_frame, offset = ch; i < start_frame + frames; |
| 69 ++i, offset += channel_count) { |
| 70 const float v = channel_data[i]; |
| 71 |
| 72 Promoted sample; |
| 73 if (v < 0) |
| 74 sample = |
| 75 v <= -1 ? min : Rounding::template FromNegative<Promoted>(-v * min); |
| 76 else |
| 77 sample = |
| 78 v >= 1 ? max : Rounding::template FromPositive<Promoted>(v * max); |
| 79 |
| 80 dest[offset] = static_cast<Format>(sample) + Traits::bias; |
| 81 } |
| 82 } |
| 83 }; |
| 84 |
| 85 template <typename Rounding> |
| 86 struct InterleaveOneChannelHelper<float, Rounding> { |
| 87 static void process(const float* channel_data, |
| 88 int start_frame, |
| 89 int frames, |
| 90 float* dest, |
| 91 int channel_count, |
| 92 int ch) { |
| 93 for (int i = start_frame, offset = ch; i < start_frame + frames; |
| 94 ++i, offset += channel_count) { |
| 95 dest[offset] = channel_data[i]; |
| 96 } |
| 97 } |
| 98 }; |
| 99 |
| 100 } // namespace internal |
| 101 |
| 102 template <typename Format> |
| 103 void DeinterleaveOneChannel(const Format* source, |
| 104 int start_frame, |
| 105 int frames, |
| 106 float* channel_data, |
| 107 int channel_count, |
| 108 int ch) { |
| 109 using Traits = internal::IntegerSampleTraits<Format>; |
| 110 using Promoted = typename Traits::promoted_type; |
| 111 |
| 112 const float min = 1.0f / Traits::min(); |
| 113 const float max = 1.0f / Traits::max(); |
| 114 |
| 115 for (int i = start_frame, offset = ch; i < start_frame + frames; |
| 116 ++i, offset += channel_count) { |
| 117 const Promoted v = static_cast<Promoted>(source[offset]) - Traits::bias; |
| 118 channel_data[i] = v * (v < 0 ? -min : max); |
| 119 } |
| 120 } |
| 121 |
| 122 template <> |
| 123 inline void DeinterleaveOneChannel<float>(const float* source, |
| 124 int start_frame, |
| 125 int frames, |
| 126 float* channel_data, |
| 127 int channel_count, |
| 128 int ch) { |
| 129 for (int i = start_frame, offset = ch; i < start_frame + frames; |
| 130 ++i, offset += channel_count) { |
| 131 channel_data[i] = source[offset]; |
| 132 } |
| 133 } |
| 134 |
| 135 template <typename Format> |
| 136 void InterleaveOneChannel(const float* channel_data, |
| 137 int start_frame, |
| 138 int frames, |
| 139 Format* dest, |
| 140 int channel_count, |
| 141 int ch) { |
| 142 internal::InterleaveOneChannelHelper< |
| 143 Format, internal::FloatToIntTruncated>::process(channel_data, start_frame, |
| 144 frames, dest, |
| 145 channel_count, ch); |
| 146 } |
| 147 |
| 148 template <typename Format> |
| 149 void InterleaveOneChannelRounded(const float* channel_data, |
| 150 int start_frame, |
| 151 int frames, |
| 152 Format* dest, |
| 153 int channel_count, |
| 154 int ch) { |
| 155 internal::InterleaveOneChannelHelper< |
| 156 Format, internal::FloatToIntRounded>::process(channel_data, start_frame, |
| 157 frames, dest, channel_count, |
| 158 ch); |
| 159 } |
| 160 |
| 161 } // namespace media |
| 162 |
| 163 #endif // MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_ |
OLD | NEW |