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 "webrtc/modules/audio_processing/splitting_filter.h"
12 
13 #include "webrtc/base/checks.h"
14 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
15 #include "webrtc/common_audio/channel_buffer.h"
16 
17 namespace webrtc {
18 
SplittingFilter(int num_channels,size_t num_bands,size_t num_frames)19 SplittingFilter::SplittingFilter(int num_channels,
20                                  size_t num_bands,
21                                  size_t num_frames)
22     : num_bands_(num_bands) {
23   RTC_CHECK(num_bands_ == 2 || num_bands_ == 3);
24   if (num_bands_ == 2) {
25     two_bands_states_.resize(num_channels);
26   } else if (num_bands_ == 3) {
27     for (int i = 0; i < num_channels; ++i) {
28       three_band_filter_banks_.push_back(new ThreeBandFilterBank(num_frames));
29     }
30   }
31 }
32 
Analysis(const IFChannelBuffer * data,IFChannelBuffer * bands)33 void SplittingFilter::Analysis(const IFChannelBuffer* data,
34                                IFChannelBuffer* bands) {
35   RTC_DCHECK_EQ(num_bands_, bands->num_bands());
36   RTC_DCHECK_EQ(data->num_channels(), bands->num_channels());
37   RTC_DCHECK_EQ(data->num_frames(),
38                 bands->num_frames_per_band() * bands->num_bands());
39   if (bands->num_bands() == 2) {
40     TwoBandsAnalysis(data, bands);
41   } else if (bands->num_bands() == 3) {
42     ThreeBandsAnalysis(data, bands);
43   }
44 }
45 
Synthesis(const IFChannelBuffer * bands,IFChannelBuffer * data)46 void SplittingFilter::Synthesis(const IFChannelBuffer* bands,
47                                 IFChannelBuffer* data) {
48   RTC_DCHECK_EQ(num_bands_, bands->num_bands());
49   RTC_DCHECK_EQ(data->num_channels(), bands->num_channels());
50   RTC_DCHECK_EQ(data->num_frames(),
51                 bands->num_frames_per_band() * bands->num_bands());
52   if (bands->num_bands() == 2) {
53     TwoBandsSynthesis(bands, data);
54   } else if (bands->num_bands() == 3) {
55     ThreeBandsSynthesis(bands, data);
56   }
57 }
58 
TwoBandsAnalysis(const IFChannelBuffer * data,IFChannelBuffer * bands)59 void SplittingFilter::TwoBandsAnalysis(const IFChannelBuffer* data,
60                                        IFChannelBuffer* bands) {
61   RTC_DCHECK_EQ(static_cast<int>(two_bands_states_.size()),
62                 data->num_channels());
63   for (size_t i = 0; i < two_bands_states_.size(); ++i) {
64     WebRtcSpl_AnalysisQMF(data->ibuf_const()->channels()[i],
65                           data->num_frames(),
66                           bands->ibuf()->channels(0)[i],
67                           bands->ibuf()->channels(1)[i],
68                           two_bands_states_[i].analysis_state1,
69                           two_bands_states_[i].analysis_state2);
70   }
71 }
72 
TwoBandsSynthesis(const IFChannelBuffer * bands,IFChannelBuffer * data)73 void SplittingFilter::TwoBandsSynthesis(const IFChannelBuffer* bands,
74                                         IFChannelBuffer* data) {
75   RTC_DCHECK_EQ(static_cast<int>(two_bands_states_.size()),
76                 data->num_channels());
77   for (size_t i = 0; i < two_bands_states_.size(); ++i) {
78     WebRtcSpl_SynthesisQMF(bands->ibuf_const()->channels(0)[i],
79                            bands->ibuf_const()->channels(1)[i],
80                            bands->num_frames_per_band(),
81                            data->ibuf()->channels()[i],
82                            two_bands_states_[i].synthesis_state1,
83                            two_bands_states_[i].synthesis_state2);
84   }
85 }
86 
ThreeBandsAnalysis(const IFChannelBuffer * data,IFChannelBuffer * bands)87 void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* data,
88                                          IFChannelBuffer* bands) {
89   RTC_DCHECK_EQ(static_cast<int>(three_band_filter_banks_.size()),
90                 data->num_channels());
91   for (size_t i = 0; i < three_band_filter_banks_.size(); ++i) {
92     three_band_filter_banks_[i]->Analysis(data->fbuf_const()->channels()[i],
93                                           data->num_frames(),
94                                           bands->fbuf()->bands(i));
95   }
96 }
97 
ThreeBandsSynthesis(const IFChannelBuffer * bands,IFChannelBuffer * data)98 void SplittingFilter::ThreeBandsSynthesis(const IFChannelBuffer* bands,
99                                           IFChannelBuffer* data) {
100   RTC_DCHECK_EQ(static_cast<int>(three_band_filter_banks_.size()),
101                 data->num_channels());
102   for (size_t i = 0; i < three_band_filter_banks_.size(); ++i) {
103     three_band_filter_banks_[i]->Synthesis(bands->fbuf_const()->bands(i),
104                                            bands->num_frames_per_band(),
105                                            data->fbuf()->channels()[i]);
106   }
107 }
108 
109 }  // namespace webrtc
110