blob: f0270803f55f42cf82291226313dd56babb52eb2 [file] [log] [blame]
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +00001/*
2 * Copyright (c) 2014 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_CHANNEL_BUFFER_H_
12#define COMMON_AUDIO_CHANNEL_BUFFER_H_
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +000013
aluebs@webrtc.org87893762014-11-27 23:40:25 +000014#include <string.h>
15
kwibergc2b785d2016-02-24 05:22:32 -080016#include <memory>
Per Åhgren1883d3e2020-02-21 13:31:07 +010017#include <vector>
kwibergc2b785d2016-02-24 05:22:32 -080018
Per Åhgren1883d3e2020-02-21 13:31:07 +010019#include "api/array_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "common_audio/include/audio_util.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/gtest_prod_util.h"
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +000023
24namespace webrtc {
25
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000026// Helper to encapsulate a contiguous data buffer, full or split into frequency
27// bands, with access to a pointer arrays of the deinterleaved channels and
28// bands. The buffer is zero initialized at creation.
29//
30// The buffer structure is showed below for a 2 channel and 2 bands case:
31//
32// |data_|:
33// { [ --- b1ch1 --- ] [ --- b2ch1 --- ] [ --- b1ch2 --- ] [ --- b2ch2 --- ] }
34//
35// The pointer arrays for the same example are as follows:
36//
37// |channels_|:
38// { [ b1ch1* ] [ b1ch2* ] [ b2ch1* ] [ b2ch2* ] }
39//
40// |bands_|:
41// { [ b1ch1* ] [ b2ch1* ] [ b1ch2* ] [ b2ch2* ] }
aluebs@webrtc.org87893762014-11-27 23:40:25 +000042template <typename T>
43class ChannelBuffer {
44 public:
Yves Gerey665174f2018-06-19 15:03:05 +020045 ChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1)
mgraczyk@chromium.orge5340862015-03-12 23:23:38 +000046 : data_(new T[num_frames * num_channels]()),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000047 channels_(new T*[num_channels * num_bands]),
48 bands_(new T*[num_channels * num_bands]),
49 num_frames_(num_frames),
50 num_frames_per_band_(num_frames / num_bands),
Alejandro Luebsa181c9a2016-06-30 15:33:37 -070051 num_allocated_channels_(num_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000052 num_channels_(num_channels),
Per Åhgren1883d3e2020-02-21 13:31:07 +010053 num_bands_(num_bands),
54 bands_view_(num_allocated_channels_,
55 std::vector<rtc::ArrayView<T>>(num_bands_)),
56 channels_view_(
57 num_bands_,
58 std::vector<rtc::ArrayView<T>>(num_allocated_channels_)) {
59 // Temporarily cast away const_ness to allow populating the array views.
60 auto* bands_view =
61 const_cast<std::vector<std::vector<rtc::ArrayView<T>>>*>(&bands_view_);
62 auto* channels_view =
63 const_cast<std::vector<std::vector<rtc::ArrayView<T>>>*>(
64 &channels_view_);
65
66 for (size_t ch = 0; ch < num_allocated_channels_; ++ch) {
67 for (size_t band = 0; band < num_bands_; ++band) {
68 (*channels_view)[band][ch] = rtc::ArrayView<T>(
69 &data_[ch * num_frames_ + band * num_frames_per_band_],
70 num_frames_per_band_);
71 (*bands_view)[ch][band] = channels_view_[band][ch];
72 channels_[band * num_allocated_channels_ + ch] =
73 channels_view_[band][ch].data();
74 bands_[ch * num_bands_ + band] =
75 channels_[band * num_allocated_channels_ + ch];
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000076 }
77 }
aluebs@webrtc.org87893762014-11-27 23:40:25 +000078 }
79
Per Åhgren1883d3e2020-02-21 13:31:07 +010080 // Returns a pointer array to the channels.
81 // If band is explicitly specificed, the channels for a specific band are
82 // returned and the usage becomes: channels(band)[channel][sample].
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000083 // Where:
84 // 0 <= band < |num_bands_|
Alejandro Luebsa181c9a2016-06-30 15:33:37 -070085 // 0 <= channel < |num_allocated_channels_|
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086 // 0 <= sample < |num_frames_per_band_|
Per Åhgren1883d3e2020-02-21 13:31:07 +010087
88 // If band is not explicitly specified, the full-band channels (or lower band
89 // channels) are returned and the usage becomes: channels()[channel][sample].
90 // Where:
91 // 0 <= channel < |num_allocated_channels_|
92 // 0 <= sample < |num_frames_|
93 const T* const* channels(size_t band = 0) const {
henrikg91d6ede2015-09-17 00:24:34 -070094 RTC_DCHECK_LT(band, num_bands_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -070095 return &channels_[band * num_allocated_channels_];
aluebs@webrtc.org87893762014-11-27 23:40:25 +000096 }
Per Åhgren1883d3e2020-02-21 13:31:07 +010097 T* const* channels(size_t band = 0) {
aluebs@webrtc.org87893762014-11-27 23:40:25 +000098 const ChannelBuffer<T>* t = this;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000099 return const_cast<T* const*>(t->channels(band));
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000100 }
Per Åhgren1883d3e2020-02-21 13:31:07 +0100101 rtc::ArrayView<const rtc::ArrayView<T>> channels_view(size_t band = 0) {
102 return channels_view_[band];
103 }
104 rtc::ArrayView<const rtc::ArrayView<T>> channels_view(size_t band = 0) const {
105 return channels_view_[band];
106 }
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000107
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000108 // Returns a pointer array to the bands for a specific channel.
109 // Usage:
110 // bands(channel)[band][sample].
111 // Where:
112 // 0 <= channel < |num_channels_|
113 // 0 <= band < |num_bands_|
114 // 0 <= sample < |num_frames_per_band_|
Peter Kasting69558702016-01-12 16:26:35 -0800115 const T* const* bands(size_t channel) const {
henrikg91d6ede2015-09-17 00:24:34 -0700116 RTC_DCHECK_LT(channel, num_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800117 RTC_DCHECK_GE(channel, 0);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000118 return &bands_[channel * num_bands_];
119 }
Peter Kasting69558702016-01-12 16:26:35 -0800120 T* const* bands(size_t channel) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000121 const ChannelBuffer<T>* t = this;
122 return const_cast<T* const*>(t->bands(channel));
123 }
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000124
Per Åhgren1883d3e2020-02-21 13:31:07 +0100125 rtc::ArrayView<const rtc::ArrayView<T>> bands_view(size_t channel) {
126 return bands_view_[channel];
127 }
128 rtc::ArrayView<const rtc::ArrayView<T>> bands_view(size_t channel) const {
129 return bands_view_[channel];
130 }
131
andrew@webrtc.org041035b2015-01-26 21:23:53 +0000132 // Sets the |slice| pointers to the |start_frame| position for each channel.
133 // Returns |slice| for convenience.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700134 const T* const* Slice(T** slice, size_t start_frame) const {
henrikg91d6ede2015-09-17 00:24:34 -0700135 RTC_DCHECK_LT(start_frame, num_frames_);
Peter Kasting69558702016-01-12 16:26:35 -0800136 for (size_t i = 0; i < num_channels_; ++i)
andrew@webrtc.org041035b2015-01-26 21:23:53 +0000137 slice[i] = &channels_[i][start_frame];
138 return slice;
139 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700140 T** Slice(T** slice, size_t start_frame) {
andrew@webrtc.org041035b2015-01-26 21:23:53 +0000141 const ChannelBuffer<T>* t = this;
142 return const_cast<T**>(t->Slice(slice, start_frame));
143 }
144
Peter Kastingdce40cf2015-08-24 14:52:23 -0700145 size_t num_frames() const { return num_frames_; }
146 size_t num_frames_per_band() const { return num_frames_per_band_; }
Peter Kasting69558702016-01-12 16:26:35 -0800147 size_t num_channels() const { return num_channels_; }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700148 size_t num_bands() const { return num_bands_; }
Yves Gerey665174f2018-06-19 15:03:05 +0200149 size_t size() const { return num_frames_ * num_allocated_channels_; }
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700150
151 void set_num_channels(size_t num_channels) {
152 RTC_DCHECK_LE(num_channels, num_allocated_channels_);
153 num_channels_ = num_channels;
154 }
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000155
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000156 void SetDataForTesting(const T* data, size_t size) {
henrikg91d6ede2015-09-17 00:24:34 -0700157 RTC_CHECK_EQ(size, this->size());
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000158 memcpy(data_.get(), data, size * sizeof(*data));
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000159 }
160
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000161 private:
kwibergc2b785d2016-02-24 05:22:32 -0800162 std::unique_ptr<T[]> data_;
Jonas Olssona4d87372019-07-05 19:08:33 +0200163 std::unique_ptr<T*[]> channels_;
164 std::unique_ptr<T*[]> bands_;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700165 const size_t num_frames_;
166 const size_t num_frames_per_band_;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700167 // Number of channels the internal buffer holds.
168 const size_t num_allocated_channels_;
169 // Number of channels the user sees.
170 size_t num_channels_;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700171 const size_t num_bands_;
Per Åhgren1883d3e2020-02-21 13:31:07 +0100172 const std::vector<std::vector<rtc::ArrayView<T>>> bands_view_;
173 const std::vector<std::vector<rtc::ArrayView<T>>> channels_view_;
aluebs@webrtc.org87893762014-11-27 23:40:25 +0000174};
175
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000176// One int16_t and one float ChannelBuffer that are kept in sync. The sync is
177// broken when someone requests write access to either ChannelBuffer, and
178// reestablished when someone requests the outdated ChannelBuffer. It is
179// therefore safe to use the return value of ibuf_const() and fbuf_const()
180// until the next call to ibuf() or fbuf(), and the return value of ibuf() and
181// fbuf() until the next call to any of the other functions.
182class IFChannelBuffer {
183 public:
Peter Kasting69558702016-01-12 16:26:35 -0800184 IFChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1);
kwiberg942c8512016-08-29 13:10:29 -0700185 ~IFChannelBuffer();
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000186
187 ChannelBuffer<int16_t>* ibuf();
188 ChannelBuffer<float>* fbuf();
189 const ChannelBuffer<int16_t>* ibuf_const() const;
190 const ChannelBuffer<float>* fbuf_const() const;
191
Peter Kastingdce40cf2015-08-24 14:52:23 -0700192 size_t num_frames() const { return ibuf_.num_frames(); }
193 size_t num_frames_per_band() const { return ibuf_.num_frames_per_band(); }
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700194 size_t num_channels() const {
195 return ivalid_ ? ibuf_.num_channels() : fbuf_.num_channels();
196 }
197 void set_num_channels(size_t num_channels) {
198 ibuf_.set_num_channels(num_channels);
199 fbuf_.set_num_channels(num_channels);
200 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700201 size_t num_bands() const { return ibuf_.num_bands(); }
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000202
203 private:
204 void RefreshF() const;
205 void RefreshI() const;
206
207 mutable bool ivalid_;
208 mutable ChannelBuffer<int16_t> ibuf_;
209 mutable bool fvalid_;
210 mutable ChannelBuffer<float> fbuf_;
211};
212
213} // namespace webrtc
214
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200215#endif // COMMON_AUDIO_CHANNEL_BUFFER_H_