blob: e4ea9a1a33b0fd3e37863c9980fac47cb84cca0c [file] [log] [blame]
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
12#define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000013
oprypin67fdb802017-03-09 06:25:06 -080014#include <algorithm>
Alex Loiko6df09f62018-02-16 10:42:48 +010015#include <cmath>
Michael Graczyk86c6d332015-07-23 11:41:39 -070016#include <cstring>
Alex Loiko6df09f62018-02-16 10:42:48 +010017#include <limits>
andrew@webrtc.org17e40642014-03-04 20:58:13 +000018
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/checks.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020020#include "typedefs.h" // NOLINT(build/include)
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000021
22namespace webrtc {
23
andrew@webrtc.org17e40642014-03-04 20:58:13 +000024typedef std::numeric_limits<int16_t> limits_int16;
25
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000026// The conversion functions use the following naming convention:
27// S16: int16_t [-32768, 32767]
28// Float: float [-1.0, 1.0]
29// FloatS16: float [-32768.0, 32767.0]
Alex Loiko6df09f62018-02-16 10:42:48 +010030// Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
31// The ratio conversion functions use this naming convention:
32// Ratio: float (0, +inf)
33// Db: float (-inf, +inf)
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000034static inline int16_t FloatToS16(float v) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +000035 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070036 return v >= 1 ? limits_int16::max()
37 : static_cast<int16_t>(v * limits_int16::max() + 0.5f);
38 return v <= -1 ? limits_int16::min()
39 : static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
turaj@webrtc.orgd4d5be82014-02-20 20:55:21 +000040}
41
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000042static inline float S16ToFloat(int16_t v) {
43 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
44 static const float kMinInt16Inverse = 1.f / limits_int16::min();
andrew@webrtc.org17e40642014-03-04 20:58:13 +000045 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
andrew@webrtc.orgb159c2e2013-09-06 21:15:55 +000046}
47
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000048static inline int16_t FloatS16ToS16(float v) {
49 static const float kMaxRound = limits_int16::max() - 0.5f;
50 static const float kMinRound = limits_int16::min() + 0.5f;
51 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070052 return v >= kMaxRound ? limits_int16::max()
53 : static_cast<int16_t>(v + 0.5f);
54 return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000055}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000056
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000057static inline float FloatToFloatS16(float v) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000058 return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000059}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000060
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000061static inline float FloatS16ToFloat(float v) {
62 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
63 static const float kMinInt16Inverse = 1.f / limits_int16::min();
64 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
65}
66
67void FloatToS16(const float* src, size_t size, int16_t* dest);
68void S16ToFloat(const int16_t* src, size_t size, float* dest);
69void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
70void FloatToFloatS16(const float* src, size_t size, float* dest);
71void FloatS16ToFloat(const float* src, size_t size, float* dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +000072
Alex Loiko6df09f62018-02-16 10:42:48 +010073inline float DbToRatio(float v) {
74 return std::pow(10.0f, v / 20.0f);
75}
76
77inline float DbfsToFloatS16(float v) {
78 static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
79 return DbToRatio(v) * kMaximumAbsFloatS16;
80}
81
82inline 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
ekmeyerson60d9b332015-08-14 10:35:55 -070094// 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|.
97template <typename T>
98void 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
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000109// 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).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000113template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700114void Deinterleave(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700115 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800116 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700117 T* const* deinterleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800118 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000119 T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800120 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700121 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000122 channel[j] = interleaved[interleaved_idx];
123 interleaved_idx += num_channels;
124 }
125 }
126}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000127
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|).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000131template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700132void Interleave(const T* const* deinterleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700133 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800134 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700135 T* interleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800136 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000137 const T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800138 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700139 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000140 interleaved[interleaved_idx] = channel[j];
141 interleaved_idx += num_channels;
142 }
143 }
144}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000145
ekmeyerson60d9b332015-08-14 10:35:55 -0700146// 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|).
149template <typename T>
150void 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
Michael Graczyk86c6d332015-07-23 11:41:39 -0700162template <typename T, typename Intermediate>
163void DownmixToMono(const T* const* input_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700164 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700165 int num_channels,
166 T* out) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700167 for (size_t i = 0; i < num_frames; ++i) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700168 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.
178template <typename T, typename Intermediate>
179void DownmixInterleavedToMonoImpl(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700180 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700181 int num_channels,
182 T* deinterleaved) {
henrikg91d6ede2015-09-17 00:24:34 -0700183 RTC_DCHECK_GT(num_channels, 0);
kwibergaf476c72016-11-28 15:21:39 -0800184 RTC_DCHECK_GT(num_frames, 0);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700185
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
200template <typename T>
201void DownmixInterleavedToMono(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700202 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700203 int num_channels,
204 T* deinterleaved);
205
206template <>
207void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700208 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700209 int num_channels,
210 int16_t* deinterleaved);
211
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000212} // namespace webrtc
213
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200214#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_