audio_util.h (7212B)
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 COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_ 12 #define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_ 13 14 #include <stdint.h> 15 16 #include <algorithm> 17 #include <cmath> 18 #include <cstring> 19 #include <limits> 20 21 #include "api/audio/audio_view.h" 22 #include "rtc_base/checks.h" 23 24 namespace webrtc { 25 26 typedef std::numeric_limits<int16_t> limits_int16; 27 28 // TODO(tommi, peah): Move these constants to their own header, e.g. 29 // `audio_constants.h`. Also consider if they should be in api/. 30 31 // Absolute highest acceptable sample rate supported for audio processing, 32 // capture and codecs. Note that for some components some cases a lower limit 33 // applies which typically is 48000 but in some cases is lower. 34 constexpr int kMaxSampleRateHz = 384000; 35 36 // Number of samples per channel for 10ms of audio at the highest sample rate. 37 constexpr size_t kMaxSamplesPerChannel10ms = kMaxSampleRateHz / 100u; 38 39 // The conversion functions use the following naming convention: 40 // S16: int16_t [-32768, 32767] 41 // Float: float [-1.0, 1.0] 42 // FloatS16: float [-32768.0, 32768.0] 43 // Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0] 44 // The ratio conversion functions use this naming convention: 45 // Ratio: float (0, +inf) 46 // Db: float (-inf, +inf) 47 static inline float S16ToFloat(int16_t v) { 48 constexpr float kScaling = 1.f / 32768.f; 49 return v * kScaling; 50 } 51 52 static inline int16_t FloatS16ToS16(float v) { 53 v = std::min(v, 32767.f); 54 v = std::max(v, -32768.f); 55 return static_cast<int16_t>(v + std::copysign(0.5f, v)); 56 } 57 58 static inline int16_t FloatToS16(float v) { 59 v *= 32768.f; 60 v = std::min(v, 32767.f); 61 v = std::max(v, -32768.f); 62 return static_cast<int16_t>(v + std::copysign(0.5f, v)); 63 } 64 65 static inline float FloatToFloatS16(float v) { 66 v = std::min(v, 1.f); 67 v = std::max(v, -1.f); 68 return v * 32768.f; 69 } 70 71 static inline float FloatS16ToFloat(float v) { 72 v = std::min(v, 32768.f); 73 v = std::max(v, -32768.f); 74 constexpr float kScaling = 1.f / 32768.f; 75 return v * kScaling; 76 } 77 78 void FloatToS16(const float* src, size_t size, int16_t* dest); 79 void S16ToFloat(const int16_t* src, size_t size, float* dest); 80 void S16ToFloatS16(const int16_t* src, size_t size, float* dest); 81 void FloatS16ToS16(const float* src, size_t size, int16_t* dest); 82 void FloatToFloatS16(const float* src, size_t size, float* dest); 83 void FloatS16ToFloat(const float* src, size_t size, float* dest); 84 85 inline float DbToRatio(float v) { 86 return std::pow(10.0f, v / 20.0f); 87 } 88 89 inline float DbfsToFloatS16(float v) { 90 static constexpr float kMaximumAbsFloatS16 = -limits_int16::min(); 91 return DbToRatio(v) * kMaximumAbsFloatS16; 92 } 93 94 inline float FloatS16ToDbfs(float v) { 95 RTC_DCHECK_GE(v, 0); 96 97 // kMinDbfs is equal to -20.0 * log10(-limits_int16::min()) 98 static constexpr float kMinDbfs = -90.30899869919436f; 99 if (v <= 1.0f) { 100 return kMinDbfs; 101 } 102 // Equal to 20 * log10(v / (-limits_int16::min())) 103 return 20.0f * std::log10(v) + kMinDbfs; 104 } 105 106 // Copy audio from `src` channels to `dest` channels unless `src` and `dest` 107 // point to the same address. `src` and `dest` must have the same number of 108 // channels, and there must be sufficient space allocated in `dest`. 109 // TODO: b/335805780 - Accept ArrayView. 110 template <typename T> 111 void CopyAudioIfNeeded(const T* const* src, 112 int num_frames, 113 int num_channels, 114 T* const* dest) { 115 for (int i = 0; i < num_channels; ++i) { 116 if (src[i] != dest[i]) { 117 std::copy(src[i], src[i] + num_frames, dest[i]); 118 } 119 } 120 } 121 122 // Deinterleave audio from `interleaved` to the channel buffers pointed to 123 // by `deinterleaved`. There must be sufficient space allocated in the 124 // `deinterleaved` buffers (`num_channel` buffers with `samples_per_channel` 125 // per buffer). 126 template <typename T> 127 void Deinterleave(const InterleavedView<const T>& interleaved, 128 const DeinterleavedView<T>& deinterleaved) { 129 RTC_DCHECK_EQ(NumChannels(interleaved), NumChannels(deinterleaved)); 130 RTC_DCHECK_EQ(SamplesPerChannel(interleaved), 131 SamplesPerChannel(deinterleaved)); 132 const auto num_channels = NumChannels(interleaved); 133 const auto samples_per_channel = SamplesPerChannel(interleaved); 134 for (size_t i = 0; i < num_channels; ++i) { 135 MonoView<T> channel = deinterleaved[i]; 136 size_t interleaved_idx = i; 137 for (size_t j = 0; j < samples_per_channel; ++j) { 138 channel[j] = interleaved[interleaved_idx]; 139 interleaved_idx += num_channels; 140 } 141 } 142 } 143 144 // Interleave audio from the channel buffers pointed to by `deinterleaved` to 145 // `interleaved`. There must be sufficient space allocated in `interleaved` 146 // (`samples_per_channel` * `num_channels`). 147 template <typename T> 148 void Interleave(const DeinterleavedView<const T>& deinterleaved, 149 const InterleavedView<T>& interleaved) { 150 RTC_DCHECK_EQ(NumChannels(interleaved), NumChannels(deinterleaved)); 151 RTC_DCHECK_EQ(SamplesPerChannel(interleaved), 152 SamplesPerChannel(deinterleaved)); 153 for (size_t i = 0; i < deinterleaved.num_channels(); ++i) { 154 const auto channel = deinterleaved[i]; 155 size_t interleaved_idx = i; 156 for (size_t j = 0; j < deinterleaved.samples_per_channel(); ++j) { 157 interleaved[interleaved_idx] = channel[j]; 158 interleaved_idx += deinterleaved.num_channels(); 159 } 160 } 161 } 162 163 // Downmixes an interleaved multichannel signal to a single channel by averaging 164 // all channels. 165 // TODO: b/335805780 - Accept InterleavedView and DeinterleavedView. 166 template <typename T, typename Intermediate> 167 void DownmixInterleavedToMonoImpl(const T* interleaved, 168 size_t num_frames, 169 int num_channels, 170 T* deinterleaved) { 171 RTC_DCHECK_GT(num_channels, 0); 172 RTC_DCHECK_GT(num_frames, 0); 173 174 const T* const end = interleaved + num_frames * num_channels; 175 176 while (interleaved < end) { 177 const T* const frame_end = interleaved + num_channels; 178 179 Intermediate value = *interleaved++; 180 while (interleaved < frame_end) { 181 value += *interleaved++; 182 } 183 184 *deinterleaved++ = value / num_channels; 185 } 186 } 187 188 // TODO: b/335805780 - Accept InterleavedView and DeinterleavedView. 189 template <typename T> 190 void DownmixInterleavedToMono(const T* interleaved, 191 size_t num_frames, 192 int num_channels, 193 T* deinterleaved); 194 195 // TODO: b/335805780 - Accept InterleavedView and DeinterleavedView. 196 template <> 197 void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved, 198 size_t num_frames, 199 int num_channels, 200 int16_t* deinterleaved); 201 202 } // namespace webrtc 203 204 #endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_