1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_ 12 #define WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_ 13 14 #include <limits> 15 #include <cstring> 16 17 #include "webrtc/base/checks.h" 18 #include "webrtc/base/scoped_ptr.h" 19 #include "webrtc/typedefs.h" 20 21 namespace webrtc { 22 23 typedef std::numeric_limits<int16_t> limits_int16; 24 25 // The conversion functions use the following naming convention: 26 // S16: int16_t [-32768, 32767] 27 // Float: float [-1.0, 1.0] 28 // FloatS16: float [-32768.0, 32767.0] 29 static inline int16_t FloatToS16(float v) { 30 if (v > 0) 31 return v >= 1 ? limits_int16::max() 32 : static_cast<int16_t>(v * limits_int16::max() + 0.5f); 33 return v <= -1 ? limits_int16::min() 34 : static_cast<int16_t>(-v * limits_int16::min() - 0.5f); 35 } 36 37 static inline float S16ToFloat(int16_t v) { 38 static const float kMaxInt16Inverse = 1.f / limits_int16::max(); 39 static const float kMinInt16Inverse = 1.f / limits_int16::min(); 40 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse); 41 } 42 43 static inline int16_t FloatS16ToS16(float v) { 44 static const float kMaxRound = limits_int16::max() - 0.5f; 45 static const float kMinRound = limits_int16::min() + 0.5f; 46 if (v > 0) 47 return v >= kMaxRound ? limits_int16::max() 48 : static_cast<int16_t>(v + 0.5f); 49 return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f); 50 } 51 52 static inline float FloatToFloatS16(float v) { 53 return v * (v > 0 ? limits_int16::max() : -limits_int16::min()); 54 } 55 56 static inline float FloatS16ToFloat(float v) { 57 static const float kMaxInt16Inverse = 1.f / limits_int16::max(); 58 static const float kMinInt16Inverse = 1.f / limits_int16::min(); 59 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse); 60 } 61 62 void FloatToS16(const float* src, size_t size, int16_t* dest); 63 void S16ToFloat(const int16_t* src, size_t size, float* dest); 64 void FloatS16ToS16(const float* src, size_t size, int16_t* dest); 65 void FloatToFloatS16(const float* src, size_t size, float* dest); 66 void FloatS16ToFloat(const float* src, size_t size, float* dest); 67 68 // Copy audio from |src| channels to |dest| channels unless |src| and |dest| 69 // point to the same address. |src| and |dest| must have the same number of 70 // channels, and there must be sufficient space allocated in |dest|. 71 template <typename T> 72 void CopyAudioIfNeeded(const T* const* src, 73 int num_frames, 74 int num_channels, 75 T* const* dest) { 76 for (int i = 0; i < num_channels; ++i) { 77 if (src[i] != dest[i]) { 78 std::copy(src[i], src[i] + num_frames, dest[i]); 79 } 80 } 81 } 82 83 // Deinterleave audio from |interleaved| to the channel buffers pointed to 84 // by |deinterleaved|. There must be sufficient space allocated in the 85 // |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel| 86 // per buffer). 87 template <typename T> 88 void Deinterleave(const T* interleaved, 89 size_t samples_per_channel, 90 size_t num_channels, 91 T* const* deinterleaved) { 92 for (size_t i = 0; i < num_channels; ++i) { 93 T* channel = deinterleaved[i]; 94 size_t interleaved_idx = i; 95 for (size_t j = 0; j < samples_per_channel; ++j) { 96 channel[j] = interleaved[interleaved_idx]; 97 interleaved_idx += num_channels; 98 } 99 } 100 } 101 102 // Interleave audio from the channel buffers pointed to by |deinterleaved| to 103 // |interleaved|. There must be sufficient space allocated in |interleaved| 104 // (|samples_per_channel| * |num_channels|). 105 template <typename T> 106 void Interleave(const T* const* deinterleaved, 107 size_t samples_per_channel, 108 size_t num_channels, 109 T* interleaved) { 110 for (size_t i = 0; i < num_channels; ++i) { 111 const T* channel = deinterleaved[i]; 112 size_t interleaved_idx = i; 113 for (size_t j = 0; j < samples_per_channel; ++j) { 114 interleaved[interleaved_idx] = channel[j]; 115 interleaved_idx += num_channels; 116 } 117 } 118 } 119 120 // Copies audio from a single channel buffer pointed to by |mono| to each 121 // channel of |interleaved|. There must be sufficient space allocated in 122 // |interleaved| (|samples_per_channel| * |num_channels|). 123 template <typename T> 124 void UpmixMonoToInterleaved(const T* mono, 125 int num_frames, 126 int num_channels, 127 T* interleaved) { 128 int interleaved_idx = 0; 129 for (int i = 0; i < num_frames; ++i) { 130 for (int j = 0; j < num_channels; ++j) { 131 interleaved[interleaved_idx++] = mono[i]; 132 } 133 } 134 } 135 136 template <typename T, typename Intermediate> 137 void DownmixToMono(const T* const* input_channels, 138 size_t num_frames, 139 int num_channels, 140 T* out) { 141 for (size_t i = 0; i < num_frames; ++i) { 142 Intermediate value = input_channels[0][i]; 143 for (int j = 1; j < num_channels; ++j) { 144 value += input_channels[j][i]; 145 } 146 out[i] = value / num_channels; 147 } 148 } 149 150 // Downmixes an interleaved multichannel signal to a single channel by averaging 151 // all channels. 152 template <typename T, typename Intermediate> 153 void DownmixInterleavedToMonoImpl(const T* interleaved, 154 size_t num_frames, 155 int num_channels, 156 T* deinterleaved) { 157 RTC_DCHECK_GT(num_channels, 0); 158 RTC_DCHECK_GT(num_frames, 0u); 159 160 const T* const end = interleaved + num_frames * num_channels; 161 162 while (interleaved < end) { 163 const T* const frame_end = interleaved + num_channels; 164 165 Intermediate value = *interleaved++; 166 while (interleaved < frame_end) { 167 value += *interleaved++; 168 } 169 170 *deinterleaved++ = value / num_channels; 171 } 172 } 173 174 template <typename T> 175 void DownmixInterleavedToMono(const T* interleaved, 176 size_t num_frames, 177 int num_channels, 178 T* deinterleaved); 179 180 template <> 181 void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved, 182 size_t num_frames, 183 int num_channels, 184 int16_t* deinterleaved); 185 186 } // namespace webrtc 187 188 #endif // WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_ 189