• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "rtc_base/checks.h"
22 
23 namespace webrtc {
24 
25 typedef std::numeric_limits<int16_t> limits_int16;
26 
27 // The conversion functions use the following naming convention:
28 // S16:      int16_t [-32768, 32767]
29 // Float:    float   [-1.0, 1.0]
30 // FloatS16: float   [-32768.0, 32768.0]
31 // Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
32 // The ratio conversion functions use this naming convention:
33 // Ratio: float (0, +inf)
34 // Db: float (-inf, +inf)
S16ToFloat(int16_t v)35 static inline float S16ToFloat(int16_t v) {
36   constexpr float kScaling = 1.f / 32768.f;
37   return v * kScaling;
38 }
39 
FloatS16ToS16(float v)40 static inline int16_t FloatS16ToS16(float v) {
41   v = std::min(v, 32767.f);
42   v = std::max(v, -32768.f);
43   return static_cast<int16_t>(v + std::copysign(0.5f, v));
44 }
45 
FloatToS16(float v)46 static inline int16_t FloatToS16(float v) {
47   v *= 32768.f;
48   v = std::min(v, 32767.f);
49   v = std::max(v, -32768.f);
50   return static_cast<int16_t>(v + std::copysign(0.5f, v));
51 }
52 
FloatToFloatS16(float v)53 static inline float FloatToFloatS16(float v) {
54   v = std::min(v, 1.f);
55   v = std::max(v, -1.f);
56   return v * 32768.f;
57 }
58 
FloatS16ToFloat(float v)59 static inline float FloatS16ToFloat(float v) {
60   v = std::min(v, 32768.f);
61   v = std::max(v, -32768.f);
62   constexpr float kScaling = 1.f / 32768.f;
63   return v * kScaling;
64 }
65 
66 void FloatToS16(const float* src, size_t size, int16_t* dest);
67 void S16ToFloat(const int16_t* src, size_t size, float* dest);
68 void S16ToFloatS16(const int16_t* src, size_t size, float* dest);
69 void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
70 void FloatToFloatS16(const float* src, size_t size, float* dest);
71 void FloatS16ToFloat(const float* src, size_t size, float* dest);
72 
DbToRatio(float v)73 inline float DbToRatio(float v) {
74   return std::pow(10.0f, v / 20.0f);
75 }
76 
DbfsToFloatS16(float v)77 inline float DbfsToFloatS16(float v) {
78   static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
79   return DbToRatio(v) * kMaximumAbsFloatS16;
80 }
81 
FloatS16ToDbfs(float v)82 inline float FloatS16ToDbfs(float v) {
83   RTC_DCHECK_GE(v, 0);
84 
85   // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
86   static constexpr float kMinDbfs = -90.30899869919436f;
87   if (v <= 1.0f) {
88     return kMinDbfs;
89   }
90   // Equal to 20 * log10(v / (-limits_int16::min()))
91   return 20.0f * std::log10(v) + kMinDbfs;
92 }
93 
94 // Copy audio from |src| channels to |dest| channels unless |src| and |dest|
95 // point to the same address. |src| and |dest| must have the same number of
96 // channels, and there must be sufficient space allocated in |dest|.
97 template <typename T>
CopyAudioIfNeeded(const T * const * src,int num_frames,int num_channels,T * const * dest)98 void CopyAudioIfNeeded(const T* const* src,
99                        int num_frames,
100                        int num_channels,
101                        T* const* dest) {
102   for (int i = 0; i < num_channels; ++i) {
103     if (src[i] != dest[i]) {
104       std::copy(src[i], src[i] + num_frames, dest[i]);
105     }
106   }
107 }
108 
109 // Deinterleave audio from |interleaved| to the channel buffers pointed to
110 // by |deinterleaved|. There must be sufficient space allocated in the
111 // |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
112 // per buffer).
113 template <typename T>
Deinterleave(const T * interleaved,size_t samples_per_channel,size_t num_channels,T * const * deinterleaved)114 void Deinterleave(const T* interleaved,
115                   size_t samples_per_channel,
116                   size_t num_channels,
117                   T* const* deinterleaved) {
118   for (size_t i = 0; i < num_channels; ++i) {
119     T* channel = deinterleaved[i];
120     size_t interleaved_idx = i;
121     for (size_t j = 0; j < samples_per_channel; ++j) {
122       channel[j] = interleaved[interleaved_idx];
123       interleaved_idx += num_channels;
124     }
125   }
126 }
127 
128 // Interleave audio from the channel buffers pointed to by |deinterleaved| to
129 // |interleaved|. There must be sufficient space allocated in |interleaved|
130 // (|samples_per_channel| * |num_channels|).
131 template <typename T>
Interleave(const T * const * deinterleaved,size_t samples_per_channel,size_t num_channels,T * interleaved)132 void Interleave(const T* const* deinterleaved,
133                 size_t samples_per_channel,
134                 size_t num_channels,
135                 T* interleaved) {
136   for (size_t i = 0; i < num_channels; ++i) {
137     const T* channel = deinterleaved[i];
138     size_t interleaved_idx = i;
139     for (size_t j = 0; j < samples_per_channel; ++j) {
140       interleaved[interleaved_idx] = channel[j];
141       interleaved_idx += num_channels;
142     }
143   }
144 }
145 
146 // Copies audio from a single channel buffer pointed to by |mono| to each
147 // channel of |interleaved|. There must be sufficient space allocated in
148 // |interleaved| (|samples_per_channel| * |num_channels|).
149 template <typename T>
UpmixMonoToInterleaved(const T * mono,int num_frames,int num_channels,T * interleaved)150 void UpmixMonoToInterleaved(const T* mono,
151                             int num_frames,
152                             int num_channels,
153                             T* interleaved) {
154   int interleaved_idx = 0;
155   for (int i = 0; i < num_frames; ++i) {
156     for (int j = 0; j < num_channels; ++j) {
157       interleaved[interleaved_idx++] = mono[i];
158     }
159   }
160 }
161 
162 template <typename T, typename Intermediate>
DownmixToMono(const T * const * input_channels,size_t num_frames,int num_channels,T * out)163 void DownmixToMono(const T* const* input_channels,
164                    size_t num_frames,
165                    int num_channels,
166                    T* out) {
167   for (size_t i = 0; i < num_frames; ++i) {
168     Intermediate value = input_channels[0][i];
169     for (int j = 1; j < num_channels; ++j) {
170       value += input_channels[j][i];
171     }
172     out[i] = value / num_channels;
173   }
174 }
175 
176 // Downmixes an interleaved multichannel signal to a single channel by averaging
177 // all channels.
178 template <typename T, typename Intermediate>
DownmixInterleavedToMonoImpl(const T * interleaved,size_t num_frames,int num_channels,T * deinterleaved)179 void DownmixInterleavedToMonoImpl(const T* interleaved,
180                                   size_t num_frames,
181                                   int num_channels,
182                                   T* deinterleaved) {
183   RTC_DCHECK_GT(num_channels, 0);
184   RTC_DCHECK_GT(num_frames, 0);
185 
186   const T* const end = interleaved + num_frames * num_channels;
187 
188   while (interleaved < end) {
189     const T* const frame_end = interleaved + num_channels;
190 
191     Intermediate value = *interleaved++;
192     while (interleaved < frame_end) {
193       value += *interleaved++;
194     }
195 
196     *deinterleaved++ = value / num_channels;
197   }
198 }
199 
200 template <typename T>
201 void DownmixInterleavedToMono(const T* interleaved,
202                               size_t num_frames,
203                               int num_channels,
204                               T* deinterleaved);
205 
206 template <>
207 void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
208                                        size_t num_frames,
209                                        int num_channels,
210                                        int16_t* deinterleaved);
211 
212 }  // namespace webrtc
213 
214 #endif  // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
215