blob: 50c9cf282cfaa88782cec32fc94e1c2ffa1af45d [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
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
oprypin67fdb802017-03-09 06:25:06 -080016#include <algorithm>
Alex Loiko6df09f62018-02-16 10:42:48 +010017#include <cmath>
Michael Graczyk86c6d332015-07-23 11:41:39 -070018#include <cstring>
Alex Loiko6df09f62018-02-16 10:42:48 +010019#include <limits>
andrew@webrtc.org17e40642014-03-04 20:58:13 +000020
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000022
23namespace webrtc {
24
andrew@webrtc.org17e40642014-03-04 20:58:13 +000025typedef std::numeric_limits<int16_t> limits_int16;
26
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000027// The conversion functions use the following naming convention:
28// S16: int16_t [-32768, 32767]
29// Float: float [-1.0, 1.0]
Henrik Andreassson533c2252019-08-16 10:40:01 +000030// FloatS16: float [-32768.0, 32767.0]
Alex Loiko6df09f62018-02-16 10:42:48 +010031// 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)
Henrik Andreassson533c2252019-08-16 10:40:01 +000035static inline int16_t FloatToS16(float v) {
36 if (v > 0)
37 return v >= 1 ? limits_int16::max()
38 : static_cast<int16_t>(v * limits_int16::max() + 0.5f);
39 return v <= -1 ? limits_int16::min()
40 : static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
41}
42
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000043static inline float S16ToFloat(int16_t v) {
Henrik Andreassson533c2252019-08-16 10:40:01 +000044 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
45 static const float kMinInt16Inverse = 1.f / limits_int16::min();
46 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
andrew@webrtc.orgb159c2e2013-09-06 21:15:55 +000047}
48
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000049static inline int16_t FloatS16ToS16(float v) {
Henrik Andreassson533c2252019-08-16 10:40:01 +000050 static const float kMaxRound = limits_int16::max() - 0.5f;
51 static const float kMinRound = limits_int16::min() + 0.5f;
52 if (v > 0)
53 return v >= kMaxRound ? limits_int16::max()
54 : static_cast<int16_t>(v + 0.5f);
55 return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000056}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000057
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000058static inline float FloatToFloatS16(float v) {
Henrik Andreassson533c2252019-08-16 10:40:01 +000059 return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000060}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000061
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000062static inline float FloatS16ToFloat(float v) {
Henrik Andreassson533c2252019-08-16 10:40:01 +000063 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
64 static const float kMinInt16Inverse = 1.f / limits_int16::min();
65 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000066}
67
Henrik Andreassson533c2252019-08-16 10:40:01 +000068void FloatToS16(const float* src, size_t size, int16_t* dest);
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000069void S16ToFloat(const int16_t* src, size_t size, float* dest);
70void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
71void FloatToFloatS16(const float* src, size_t size, float* dest);
72void FloatS16ToFloat(const float* src, size_t size, float* dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +000073
Alex Loiko6df09f62018-02-16 10:42:48 +010074inline float DbToRatio(float v) {
75 return std::pow(10.0f, v / 20.0f);
76}
77
78inline float DbfsToFloatS16(float v) {
79 static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
80 return DbToRatio(v) * kMaximumAbsFloatS16;
81}
82
83inline float FloatS16ToDbfs(float v) {
84 RTC_DCHECK_GE(v, 0);
85
86 // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
87 static constexpr float kMinDbfs = -90.30899869919436f;
88 if (v <= 1.0f) {
89 return kMinDbfs;
90 }
91 // Equal to 20 * log10(v / (-limits_int16::min()))
92 return 20.0f * std::log10(v) + kMinDbfs;
93}
94
ekmeyerson60d9b332015-08-14 10:35:55 -070095// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
96// point to the same address. |src| and |dest| must have the same number of
97// channels, and there must be sufficient space allocated in |dest|.
98template <typename T>
99void CopyAudioIfNeeded(const T* const* src,
100 int num_frames,
101 int num_channels,
102 T* const* dest) {
103 for (int i = 0; i < num_channels; ++i) {
104 if (src[i] != dest[i]) {
105 std::copy(src[i], src[i] + num_frames, dest[i]);
106 }
107 }
108}
109
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000110// Deinterleave audio from |interleaved| to the channel buffers pointed to
111// by |deinterleaved|. There must be sufficient space allocated in the
112// |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
113// per buffer).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000114template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700115void Deinterleave(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700116 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800117 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700118 T* const* deinterleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800119 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000120 T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800121 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700122 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000123 channel[j] = interleaved[interleaved_idx];
124 interleaved_idx += num_channels;
125 }
126 }
127}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000128
129// Interleave audio from the channel buffers pointed to by |deinterleaved| to
130// |interleaved|. There must be sufficient space allocated in |interleaved|
131// (|samples_per_channel| * |num_channels|).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000132template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700133void Interleave(const T* const* deinterleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700134 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800135 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700136 T* interleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800137 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000138 const T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800139 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700140 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000141 interleaved[interleaved_idx] = channel[j];
142 interleaved_idx += num_channels;
143 }
144 }
145}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000146
ekmeyerson60d9b332015-08-14 10:35:55 -0700147// Copies audio from a single channel buffer pointed to by |mono| to each
148// channel of |interleaved|. There must be sufficient space allocated in
149// |interleaved| (|samples_per_channel| * |num_channels|).
150template <typename T>
151void UpmixMonoToInterleaved(const T* mono,
152 int num_frames,
153 int num_channels,
154 T* interleaved) {
155 int interleaved_idx = 0;
156 for (int i = 0; i < num_frames; ++i) {
157 for (int j = 0; j < num_channels; ++j) {
158 interleaved[interleaved_idx++] = mono[i];
159 }
160 }
161}
162
Michael Graczyk86c6d332015-07-23 11:41:39 -0700163template <typename T, typename Intermediate>
164void DownmixToMono(const T* const* input_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700165 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700166 int num_channels,
167 T* out) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700168 for (size_t i = 0; i < num_frames; ++i) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700169 Intermediate value = input_channels[0][i];
170 for (int j = 1; j < num_channels; ++j) {
171 value += input_channels[j][i];
172 }
173 out[i] = value / num_channels;
174 }
175}
176
177// Downmixes an interleaved multichannel signal to a single channel by averaging
178// all channels.
179template <typename T, typename Intermediate>
180void DownmixInterleavedToMonoImpl(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700181 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700182 int num_channels,
183 T* deinterleaved) {
henrikg91d6ede2015-09-17 00:24:34 -0700184 RTC_DCHECK_GT(num_channels, 0);
kwibergaf476c72016-11-28 15:21:39 -0800185 RTC_DCHECK_GT(num_frames, 0);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700186
187 const T* const end = interleaved + num_frames * num_channels;
188
189 while (interleaved < end) {
190 const T* const frame_end = interleaved + num_channels;
191
192 Intermediate value = *interleaved++;
193 while (interleaved < frame_end) {
194 value += *interleaved++;
195 }
196
197 *deinterleaved++ = value / num_channels;
198 }
199}
200
201template <typename T>
202void DownmixInterleavedToMono(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700203 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700204 int num_channels,
205 T* deinterleaved);
206
207template <>
208void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700209 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700210 int num_channels,
211 int16_t* deinterleaved);
212
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000213} // namespace webrtc
214
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200215#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_