blob: b9e1b26b0db7a27a3f78ed1d1fcdc93fec22bb17 [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>
andrew@webrtc.org17e40642014-03-04 20:58:13 +000015#include <limits>
Michael Graczyk86c6d332015-07-23 11:41:39 -070016#include <cstring>
andrew@webrtc.org17e40642014-03-04 20:58:13 +000017
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/checks.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020019#include "typedefs.h" // NOLINT(build/include)
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]
29static inline int16_t FloatToS16(float v) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +000030 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070031 return v >= 1 ? limits_int16::max()
32 : static_cast<int16_t>(v * limits_int16::max() + 0.5f);
33 return v <= -1 ? limits_int16::min()
34 : static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
turaj@webrtc.orgd4d5be82014-02-20 20:55:21 +000035}
36
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000037static inline float S16ToFloat(int16_t v) {
38 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
39 static const float kMinInt16Inverse = 1.f / limits_int16::min();
andrew@webrtc.org17e40642014-03-04 20:58:13 +000040 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
andrew@webrtc.orgb159c2e2013-09-06 21:15:55 +000041}
42
andrew@webrtc.org4fc4add2014-10-30 03:40:10 +000043static inline int16_t FloatS16ToS16(float v) {
44 static const float kMaxRound = limits_int16::max() - 0.5f;
45 static const float kMinRound = limits_int16::min() + 0.5f;
46 if (v > 0)
Michael Graczyk86c6d332015-07-23 11:41:39 -070047 return v >= kMaxRound ? limits_int16::max()
48 : static_cast<int16_t>(v + 0.5f);
49 return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
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 FloatToFloatS16(float v) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000053 return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
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 FloatS16ToFloat(float v) {
57 static const float kMaxInt16Inverse = 1.f / limits_int16::max();
58 static const float kMinInt16Inverse = 1.f / limits_int16::min();
59 return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
60}
61
62void FloatToS16(const float* src, size_t size, int16_t* dest);
63void S16ToFloat(const int16_t* src, size_t size, float* dest);
64void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
65void FloatToFloatS16(const float* src, size_t size, float* dest);
66void FloatS16ToFloat(const float* src, size_t size, float* dest);
andrew@webrtc.org17e40642014-03-04 20:58:13 +000067
ekmeyerson60d9b332015-08-14 10:35:55 -070068// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
69// point to the same address. |src| and |dest| must have the same number of
70// channels, and there must be sufficient space allocated in |dest|.
71template <typename T>
72void CopyAudioIfNeeded(const T* const* src,
73 int num_frames,
74 int num_channels,
75 T* const* dest) {
76 for (int i = 0; i < num_channels; ++i) {
77 if (src[i] != dest[i]) {
78 std::copy(src[i], src[i] + num_frames, dest[i]);
79 }
80 }
81}
82
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +000083// Deinterleave audio from |interleaved| to the channel buffers pointed to
84// by |deinterleaved|. There must be sufficient space allocated in the
85// |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
86// per buffer).
andrew@webrtc.org17e40642014-03-04 20:58:13 +000087template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -070088void Deinterleave(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -070089 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -080090 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -070091 T* const* deinterleaved) {
Peter Kasting69558702016-01-12 16:26:35 -080092 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +000093 T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -080094 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -070095 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +000096 channel[j] = interleaved[interleaved_idx];
97 interleaved_idx += num_channels;
98 }
99 }
100}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000101
102// Interleave audio from the channel buffers pointed to by |deinterleaved| to
103// |interleaved|. There must be sufficient space allocated in |interleaved|
104// (|samples_per_channel| * |num_channels|).
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000105template <typename T>
Michael Graczyk86c6d332015-07-23 11:41:39 -0700106void Interleave(const T* const* deinterleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700107 size_t samples_per_channel,
Peter Kasting69558702016-01-12 16:26:35 -0800108 size_t num_channels,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700109 T* interleaved) {
Peter Kasting69558702016-01-12 16:26:35 -0800110 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000111 const T* channel = deinterleaved[i];
Peter Kasting69558702016-01-12 16:26:35 -0800112 size_t interleaved_idx = i;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700113 for (size_t j = 0; j < samples_per_channel; ++j) {
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000114 interleaved[interleaved_idx] = channel[j];
115 interleaved_idx += num_channels;
116 }
117 }
118}
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000119
ekmeyerson60d9b332015-08-14 10:35:55 -0700120// Copies audio from a single channel buffer pointed to by |mono| to each
121// channel of |interleaved|. There must be sufficient space allocated in
122// |interleaved| (|samples_per_channel| * |num_channels|).
123template <typename T>
124void UpmixMonoToInterleaved(const T* mono,
125 int num_frames,
126 int num_channels,
127 T* interleaved) {
128 int interleaved_idx = 0;
129 for (int i = 0; i < num_frames; ++i) {
130 for (int j = 0; j < num_channels; ++j) {
131 interleaved[interleaved_idx++] = mono[i];
132 }
133 }
134}
135
Michael Graczyk86c6d332015-07-23 11:41:39 -0700136template <typename T, typename Intermediate>
137void DownmixToMono(const T* const* input_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700138 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700139 int num_channels,
140 T* out) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700141 for (size_t i = 0; i < num_frames; ++i) {
Michael Graczyk86c6d332015-07-23 11:41:39 -0700142 Intermediate value = input_channels[0][i];
143 for (int j = 1; j < num_channels; ++j) {
144 value += input_channels[j][i];
145 }
146 out[i] = value / num_channels;
147 }
148}
149
150// Downmixes an interleaved multichannel signal to a single channel by averaging
151// all channels.
152template <typename T, typename Intermediate>
153void DownmixInterleavedToMonoImpl(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700154 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700155 int num_channels,
156 T* deinterleaved) {
henrikg91d6ede2015-09-17 00:24:34 -0700157 RTC_DCHECK_GT(num_channels, 0);
kwibergaf476c72016-11-28 15:21:39 -0800158 RTC_DCHECK_GT(num_frames, 0);
Michael Graczyk86c6d332015-07-23 11:41:39 -0700159
160 const T* const end = interleaved + num_frames * num_channels;
161
162 while (interleaved < end) {
163 const T* const frame_end = interleaved + num_channels;
164
165 Intermediate value = *interleaved++;
166 while (interleaved < frame_end) {
167 value += *interleaved++;
168 }
169
170 *deinterleaved++ = value / num_channels;
171 }
172}
173
174template <typename T>
175void DownmixInterleavedToMono(const T* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700176 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700177 int num_channels,
178 T* deinterleaved);
179
180template <>
181void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700182 size_t num_frames,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700183 int num_channels,
184 int16_t* deinterleaved);
185
andrew@webrtc.org50b2efe2013-04-29 17:27:29 +0000186} // namespace webrtc
187
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200188#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_