1 /*
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
11 #include "modules/audio_processing/splitting_filter.h"
12
13 #include <array>
14
15 #include "api/array_view.h"
16 #include "common_audio/channel_buffer.h"
17 #include "common_audio/signal_processing/include/signal_processing_library.h"
18 #include "rtc_base/checks.h"
19
20 namespace webrtc {
21 namespace {
22
23 constexpr size_t kSamplesPerBand = 160;
24 constexpr size_t kTwoBandFilterSamplesPerFrame = 320;
25
26 } // namespace
27
SplittingFilter(size_t num_channels,size_t num_bands,size_t num_frames)28 SplittingFilter::SplittingFilter(size_t num_channels,
29 size_t num_bands,
30 size_t num_frames)
31 : num_bands_(num_bands),
32 two_bands_states_(num_bands_ == 2 ? num_channels : 0),
33 three_band_filter_banks_(num_bands_ == 3 ? num_channels : 0) {
34 RTC_CHECK(num_bands_ == 2 || num_bands_ == 3);
35 }
36
37 SplittingFilter::~SplittingFilter() = default;
38
Analysis(const ChannelBuffer<float> * data,ChannelBuffer<float> * bands)39 void SplittingFilter::Analysis(const ChannelBuffer<float>* data,
40 ChannelBuffer<float>* bands) {
41 RTC_DCHECK_EQ(num_bands_, bands->num_bands());
42 RTC_DCHECK_EQ(data->num_channels(), bands->num_channels());
43 RTC_DCHECK_EQ(data->num_frames(),
44 bands->num_frames_per_band() * bands->num_bands());
45 if (bands->num_bands() == 2) {
46 TwoBandsAnalysis(data, bands);
47 } else if (bands->num_bands() == 3) {
48 ThreeBandsAnalysis(data, bands);
49 }
50 }
51
Synthesis(const ChannelBuffer<float> * bands,ChannelBuffer<float> * data)52 void SplittingFilter::Synthesis(const ChannelBuffer<float>* bands,
53 ChannelBuffer<float>* data) {
54 RTC_DCHECK_EQ(num_bands_, bands->num_bands());
55 RTC_DCHECK_EQ(data->num_channels(), bands->num_channels());
56 RTC_DCHECK_EQ(data->num_frames(),
57 bands->num_frames_per_band() * bands->num_bands());
58 if (bands->num_bands() == 2) {
59 TwoBandsSynthesis(bands, data);
60 } else if (bands->num_bands() == 3) {
61 ThreeBandsSynthesis(bands, data);
62 }
63 }
64
TwoBandsAnalysis(const ChannelBuffer<float> * data,ChannelBuffer<float> * bands)65 void SplittingFilter::TwoBandsAnalysis(const ChannelBuffer<float>* data,
66 ChannelBuffer<float>* bands) {
67 RTC_DCHECK_EQ(two_bands_states_.size(), data->num_channels());
68 RTC_DCHECK_EQ(data->num_frames(), kTwoBandFilterSamplesPerFrame);
69
70 for (size_t i = 0; i < two_bands_states_.size(); ++i) {
71 std::array<std::array<int16_t, kSamplesPerBand>, 2> bands16;
72 std::array<int16_t, kTwoBandFilterSamplesPerFrame> full_band16;
73 FloatS16ToS16(data->channels(0)[i], full_band16.size(), full_band16.data());
74 WebRtcSpl_AnalysisQMF(full_band16.data(), data->num_frames(),
75 bands16[0].data(), bands16[1].data(),
76 two_bands_states_[i].analysis_state1,
77 two_bands_states_[i].analysis_state2);
78 S16ToFloatS16(bands16[0].data(), bands16[0].size(), bands->channels(0)[i]);
79 S16ToFloatS16(bands16[1].data(), bands16[1].size(), bands->channels(1)[i]);
80 }
81 }
82
TwoBandsSynthesis(const ChannelBuffer<float> * bands,ChannelBuffer<float> * data)83 void SplittingFilter::TwoBandsSynthesis(const ChannelBuffer<float>* bands,
84 ChannelBuffer<float>* data) {
85 RTC_DCHECK_LE(data->num_channels(), two_bands_states_.size());
86 RTC_DCHECK_EQ(data->num_frames(), kTwoBandFilterSamplesPerFrame);
87 for (size_t i = 0; i < data->num_channels(); ++i) {
88 std::array<std::array<int16_t, kSamplesPerBand>, 2> bands16;
89 std::array<int16_t, kTwoBandFilterSamplesPerFrame> full_band16;
90 FloatS16ToS16(bands->channels(0)[i], bands16[0].size(), bands16[0].data());
91 FloatS16ToS16(bands->channels(1)[i], bands16[1].size(), bands16[1].data());
92 WebRtcSpl_SynthesisQMF(bands16[0].data(), bands16[1].data(),
93 bands->num_frames_per_band(), full_band16.data(),
94 two_bands_states_[i].synthesis_state1,
95 two_bands_states_[i].synthesis_state2);
96 S16ToFloatS16(full_band16.data(), full_band16.size(), data->channels(0)[i]);
97 }
98 }
99
ThreeBandsAnalysis(const ChannelBuffer<float> * data,ChannelBuffer<float> * bands)100 void SplittingFilter::ThreeBandsAnalysis(const ChannelBuffer<float>* data,
101 ChannelBuffer<float>* bands) {
102 RTC_DCHECK_EQ(three_band_filter_banks_.size(), data->num_channels());
103 RTC_DCHECK_LE(data->num_channels(), three_band_filter_banks_.size());
104 RTC_DCHECK_LE(data->num_channels(), bands->num_channels());
105 RTC_DCHECK_EQ(data->num_frames(), ThreeBandFilterBank::kFullBandSize);
106 RTC_DCHECK_EQ(bands->num_frames(), ThreeBandFilterBank::kFullBandSize);
107 RTC_DCHECK_EQ(bands->num_bands(), ThreeBandFilterBank::kNumBands);
108 RTC_DCHECK_EQ(bands->num_frames_per_band(),
109 ThreeBandFilterBank::kSplitBandSize);
110
111 for (size_t i = 0; i < three_band_filter_banks_.size(); ++i) {
112 three_band_filter_banks_[i].Analysis(
113 rtc::ArrayView<const float, ThreeBandFilterBank::kFullBandSize>(
114 data->channels_view()[i].data(),
115 ThreeBandFilterBank::kFullBandSize),
116 rtc::ArrayView<const rtc::ArrayView<float>,
117 ThreeBandFilterBank::kNumBands>(
118 bands->bands_view(i).data(), ThreeBandFilterBank::kNumBands));
119 }
120 }
121
ThreeBandsSynthesis(const ChannelBuffer<float> * bands,ChannelBuffer<float> * data)122 void SplittingFilter::ThreeBandsSynthesis(const ChannelBuffer<float>* bands,
123 ChannelBuffer<float>* data) {
124 RTC_DCHECK_LE(data->num_channels(), three_band_filter_banks_.size());
125 RTC_DCHECK_LE(data->num_channels(), bands->num_channels());
126 RTC_DCHECK_LE(data->num_channels(), three_band_filter_banks_.size());
127 RTC_DCHECK_EQ(data->num_frames(), ThreeBandFilterBank::kFullBandSize);
128 RTC_DCHECK_EQ(bands->num_frames(), ThreeBandFilterBank::kFullBandSize);
129 RTC_DCHECK_EQ(bands->num_bands(), ThreeBandFilterBank::kNumBands);
130 RTC_DCHECK_EQ(bands->num_frames_per_band(),
131 ThreeBandFilterBank::kSplitBandSize);
132
133 for (size_t i = 0; i < data->num_channels(); ++i) {
134 three_band_filter_banks_[i].Synthesis(
135 rtc::ArrayView<const rtc::ArrayView<float>,
136 ThreeBandFilterBank::kNumBands>(
137 bands->bands_view(i).data(), ThreeBandFilterBank::kNumBands),
138 rtc::ArrayView<float, ThreeBandFilterBank::kFullBandSize>(
139 data->channels_view()[i].data(),
140 ThreeBandFilterBank::kFullBandSize));
141 }
142 }
143
144 } // namespace webrtc
145