blob: 9925e54b0221cf005aa8412a61130670d8d2f950 [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]
Per Åhgren62c174c2019-08-16 13:43:00 +020030// FloatS16: float [-32768.0, 32768.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)
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000035static inline float S16ToFloat(int16_t v) {
Per Åhgren62c174c2019-08-16 13:43:00 +020036 constexpr float kScaling = 1.f / 32768.f;
37 return v * kScaling;
andrew@webrtc.orgb159c2e2013-09-06 21:15:55 +000038}
39
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000040static inline int16_t FloatS16ToS16(float v) {
Per Åhgren62c174c2019-08-16 13:43:00 +020041 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));
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000044}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000045
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000046static inline float FloatToFloatS16(float v) {
Per Åhgren62c174c2019-08-16 13:43:00 +020047 v = std::min(v, 1.f);
48 v = std::max(v, -1.f);
49 return v * 32768.f;
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000050}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000051
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000052static inline float FloatS16ToFloat(float v) {
Per Åhgren62c174c2019-08-16 13:43:00 +020053 v = std::min(v, 32768.f);
54 v = std::max(v, -32768.f);
55 constexpr float kScaling = 1.f / 32768.f;
56 return v * kScaling;
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000057}
58
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000059void S16ToFloat(const int16_t* src, size_t size, float* dest);
60void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
61void FloatToFloatS16(const float* src, size_t size, float* dest);
62void FloatS16ToFloat(const float* src, size_t size, float* dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +000063
Alex Loiko6df09f62018-02-16 10:42:48 +010064inline float DbToRatio(float v) {
65 return std::pow(10.0f, v / 20.0f);
66}
67
68inline float DbfsToFloatS16(float v) {
69 static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
70 return DbToRatio(v) * kMaximumAbsFloatS16;
71}
72
73inline float FloatS16ToDbfs(float v) {
74 RTC_DCHECK_GE(v, 0);
75
76 // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
77 static constexpr float kMinDbfs = -90.30899869919436f;
78 if (v <= 1.0f) {
79 return kMinDbfs;
80 }
81 // Equal to 20 * log10(v / (-limits_int16::min()))
82 return 20.0f * std::log10(v) + kMinDbfs;
83}
84
ekmeyerson60d9b332015-08-14 10:35:55 -070085// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
86// point to the same address. |src| and |dest| must have the same number of
87// channels, and there must be sufficient space allocated in |dest|.
88template <typename T>
89void CopyAudioIfNeeded(const T* const* src,
90 int num_frames,
91 int num_channels,
92 T* const* dest) {
93 for (int i = 0; i < num_channels; ++i) {
94 if (src[i] != dest[i]) {
95 std::copy(src[i], src[i] + num_frames, dest[i]);
96 }
97 }
98}
99
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000100// Deinterleave audio from |interleaved| to the channel buffers pointed to
101// by |deinterleaved|. There must be sufficient space allocated in the
102// |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
103// per buffer).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000104template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700105void Deinterleave(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700106 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800107 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700108 T* const* deinterleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800109 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000110 T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800111 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700112 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000113 channel[j] = interleaved[interleaved_idx];
114 interleaved_idx += num_channels;
115 }
116 }
117}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000118
119// Interleave audio from the channel buffers pointed to by |deinterleaved| to
120// |interleaved|. There must be sufficient space allocated in |interleaved|
121// (|samples_per_channel| * |num_channels|).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000122template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700123void Interleave(const T* const* deinterleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700124 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800125 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700126 T* interleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800127 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000128 const T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800129 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700130 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000131 interleaved[interleaved_idx] = channel[j];
132 interleaved_idx += num_channels;
133 }
134 }
135}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000136
ekmeyerson60d9b332015-08-14 10:35:55 -0700137// Copies audio from a single channel buffer pointed to by |mono| to each
138// channel of |interleaved|. There must be sufficient space allocated in
139// |interleaved| (|samples_per_channel| * |num_channels|).
140template <typename T>
141void UpmixMonoToInterleaved(const T* mono,
142 int num_frames,
143 int num_channels,
144 T* interleaved) {
145 int interleaved_idx = 0;
146 for (int i = 0; i < num_frames; ++i) {
147 for (int j = 0; j < num_channels; ++j) {
148 interleaved[interleaved_idx++] = mono[i];
149 }
150 }
151}
152
Michael Graczyk86c6d332015-07-23 11:41:39 -0700153template <typename T, typename Intermediate>
154void DownmixToMono(const T* const* input_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700155 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700156 int num_channels,
157 T* out) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700158 for (size_t i = 0; i < num_frames; ++i) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700159 Intermediate value = input_channels[0][i];
160 for (int j = 1; j < num_channels; ++j) {
161 value += input_channels[j][i];
162 }
163 out[i] = value / num_channels;
164 }
165}
166
167// Downmixes an interleaved multichannel signal to a single channel by averaging
168// all channels.
169template <typename T, typename Intermediate>
170void DownmixInterleavedToMonoImpl(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700171 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700172 int num_channels,
173 T* deinterleaved) {
henrikg91d6ede2015-09-17 00:24:34 -0700174 RTC_DCHECK_GT(num_channels, 0);
kwibergaf476c72016-11-28 15:21:39 -0800175 RTC_DCHECK_GT(num_frames, 0);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700176
177 const T* const end = interleaved + num_frames * num_channels;
178
179 while (interleaved < end) {
180 const T* const frame_end = interleaved + num_channels;
181
182 Intermediate value = *interleaved++;
183 while (interleaved < frame_end) {
184 value += *interleaved++;
185 }
186
187 *deinterleaved++ = value / num_channels;
188 }
189}
190
191template <typename T>
192void DownmixInterleavedToMono(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700193 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700194 int num_channels,
195 T* deinterleaved);
196
197template <>
198void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700199 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700200 int num_channels,
201 int16_t* deinterleaved);
202
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000203} // namespace webrtc
204
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200205#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_