blob: de242a49be8b663484a8b9eb4e5faecb03827af4 [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"
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000020
21namespace webrtc {
22
andrew@webrtc.org17e40642014-03-04 20:58:13 +000023typedef std::numeric_limits<int16_t> limits_int16;
24
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000025// The conversion functions use the following naming convention:
26// S16: int16_t [-32768, 32767]
27// Float: float [-1.0, 1.0]
28// FloatS16: float [-32768.0, 32767.0]
Alex Loiko6df09f62018-02-16 10:42:48 +010029// Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
30// The ratio conversion functions use this naming convention:
31// Ratio: float (0, +inf)
32// Db: float (-inf, +inf)
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000033static inline int16_t FloatToS16(float v) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +000034 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070035 return v >= 1 ? limits_int16::max()
36 : static_cast<int16_t>(v * limits_int16::max() + 0.5f);
37 return v <= -1 ? limits_int16::min()
38 : static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
turaj@webrtc.orgd4d5be82014-02-20 20:55:21 +000039}
40
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000041static inline float S16ToFloat(int16_t v) {
42 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
43 static const float kMinInt16Inverse = 1.f / limits_int16::min();
andrew@webrtc.org17e40642014-03-04 20:58:13 +000044 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
andrew@webrtc.orgb159c2e2013-09-06 21:15:55 +000045}
46
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000047static inline int16_t FloatS16ToS16(float v) {
48 static const float kMaxRound = limits_int16::max() - 0.5f;
49 static const float kMinRound = limits_int16::min() + 0.5f;
50 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070051 return v >= kMaxRound ? limits_int16::max()
52 : static_cast<int16_t>(v + 0.5f);
53 return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000054}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000055
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000056static inline float FloatToFloatS16(float v) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000057 return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000058}
andrew@webrtc.org17e40642014-03-04 20:58:13 +000059
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000060static inline float FloatS16ToFloat(float v) {
61 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
62 static const float kMinInt16Inverse = 1.f / limits_int16::min();
63 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
64}
65
66void FloatToS16(const float* src, size_t size, int16_t* dest);
67void S16ToFloat(const int16_t* src, size_t size, float* dest);
68void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
69void FloatToFloatS16(const float* src, size_t size, float* dest);
70void FloatS16ToFloat(const float* src, size_t size, float* dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +000071
Alex Loiko6df09f62018-02-16 10:42:48 +010072inline float DbToRatio(float v) {
73 return std::pow(10.0f, v / 20.0f);
74}
75
76inline float DbfsToFloatS16(float v) {
77 static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
78 return DbToRatio(v) * kMaximumAbsFloatS16;
79}
80
81inline float FloatS16ToDbfs(float v) {
82 RTC_DCHECK_GE(v, 0);
83
84 // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
85 static constexpr float kMinDbfs = -90.30899869919436f;
86 if (v <= 1.0f) {
87 return kMinDbfs;
88 }
89 // Equal to 20 * log10(v / (-limits_int16::min()))
90 return 20.0f * std::log10(v) + kMinDbfs;
91}
92
ekmeyerson60d9b332015-08-14 10:35:55 -070093// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
94// point to the same address. |src| and |dest| must have the same number of
95// channels, and there must be sufficient space allocated in |dest|.
96template <typename T>
97void CopyAudioIfNeeded(const T* const* src,
98 int num_frames,
99 int num_channels,
100 T* const* dest) {
101 for (int i = 0; i < num_channels; ++i) {
102 if (src[i] != dest[i]) {
103 std::copy(src[i], src[i] + num_frames, dest[i]);
104 }
105 }
106}
107
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000108// Deinterleave audio from |interleaved| to the channel buffers pointed to
109// by |deinterleaved|. There must be sufficient space allocated in the
110// |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
111// per buffer).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000112template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700113void Deinterleave(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700114 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800115 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700116 T* const* deinterleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800117 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000118 T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800119 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700120 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000121 channel[j] = interleaved[interleaved_idx];
122 interleaved_idx += num_channels;
123 }
124 }
125}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000126
127// Interleave audio from the channel buffers pointed to by |deinterleaved| to
128// |interleaved|. There must be sufficient space allocated in |interleaved|
129// (|samples_per_channel| * |num_channels|).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000130template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700131void Interleave(const T* const* deinterleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700132 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800133 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700134 T* interleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800135 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000136 const T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800137 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700138 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000139 interleaved[interleaved_idx] = channel[j];
140 interleaved_idx += num_channels;
141 }
142 }
143}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000144
ekmeyerson60d9b332015-08-14 10:35:55 -0700145// Copies audio from a single channel buffer pointed to by |mono| to each
146// channel of |interleaved|. There must be sufficient space allocated in
147// |interleaved| (|samples_per_channel| * |num_channels|).
148template <typename T>
149void UpmixMonoToInterleaved(const T* mono,
150 int num_frames,
151 int num_channels,
152 T* interleaved) {
153 int interleaved_idx = 0;
154 for (int i = 0; i < num_frames; ++i) {
155 for (int j = 0; j < num_channels; ++j) {
156 interleaved[interleaved_idx++] = mono[i];
157 }
158 }
159}
160
Michael Graczyk86c6d332015-07-23 11:41:39 -0700161template <typename T, typename Intermediate>
162void DownmixToMono(const T* const* input_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700163 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700164 int num_channels,
165 T* out) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700166 for (size_t i = 0; i < num_frames; ++i) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700167 Intermediate value = input_channels[0][i];
168 for (int j = 1; j < num_channels; ++j) {
169 value += input_channels[j][i];
170 }
171 out[i] = value / num_channels;
172 }
173}
174
175// Downmixes an interleaved multichannel signal to a single channel by averaging
176// all channels.
177template <typename T, typename Intermediate>
178void DownmixInterleavedToMonoImpl(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700179 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700180 int num_channels,
181 T* deinterleaved) {
henrikg91d6ede2015-09-17 00:24:34 -0700182 RTC_DCHECK_GT(num_channels, 0);
kwibergaf476c72016-11-28 15:21:39 -0800183 RTC_DCHECK_GT(num_frames, 0);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700184
185 const T* const end = interleaved + num_frames * num_channels;
186
187 while (interleaved < end) {
188 const T* const frame_end = interleaved + num_channels;
189
190 Intermediate value = *interleaved++;
191 while (interleaved < frame_end) {
192 value += *interleaved++;
193 }
194
195 *deinterleaved++ = value / num_channels;
196 }
197}
198
199template <typename T>
200void DownmixInterleavedToMono(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700201 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700202 int num_channels,
203 T* deinterleaved);
204
205template <>
206void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700207 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700208 int num_channels,
209 int16_t* deinterleaved);
210
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000211} // namespace webrtc
212
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200213#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_