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
17namespace webrtc {
18
19SplittingFilter::SplittingFilter(size_t 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 (size_t i = 0; i < num_channels; ++i) {
28      three_band_filter_banks_.push_back(new ThreeBandFilterBank(num_frames));
29    }
30  }
31}
32
33void 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
46void 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
59void SplittingFilter::TwoBandsAnalysis(const IFChannelBuffer* data,
60                                       IFChannelBuffer* bands) {
61  RTC_DCHECK_EQ(two_bands_states_.size(), data->num_channels());
62  for (size_t i = 0; i < two_bands_states_.size(); ++i) {
63    WebRtcSpl_AnalysisQMF(data->ibuf_const()->channels()[i],
64                          data->num_frames(),
65                          bands->ibuf()->channels(0)[i],
66                          bands->ibuf()->channels(1)[i],
67                          two_bands_states_[i].analysis_state1,
68                          two_bands_states_[i].analysis_state2);
69  }
70}
71
72void SplittingFilter::TwoBandsSynthesis(const IFChannelBuffer* bands,
73                                        IFChannelBuffer* data) {
74  RTC_DCHECK_EQ(two_bands_states_.size(), data->num_channels());
75  for (size_t i = 0; i < two_bands_states_.size(); ++i) {
76    WebRtcSpl_SynthesisQMF(bands->ibuf_const()->channels(0)[i],
77                           bands->ibuf_const()->channels(1)[i],
78                           bands->num_frames_per_band(),
79                           data->ibuf()->channels()[i],
80                           two_bands_states_[i].synthesis_state1,
81                           two_bands_states_[i].synthesis_state2);
82  }
83}
84
85void SplittingFilter::ThreeBandsAnalysis(const IFChannelBuffer* data,
86                                         IFChannelBuffer* bands) {
87  RTC_DCHECK_EQ(three_band_filter_banks_.size(), data->num_channels());
88  for (size_t i = 0; i < three_band_filter_banks_.size(); ++i) {
89    three_band_filter_banks_[i]->Analysis(data->fbuf_const()->channels()[i],
90                                          data->num_frames(),
91                                          bands->fbuf()->bands(i));
92  }
93}
94
95void SplittingFilter::ThreeBandsSynthesis(const IFChannelBuffer* bands,
96                                          IFChannelBuffer* data) {
97  RTC_DCHECK_EQ(three_band_filter_banks_.size(), data->num_channels());
98  for (size_t i = 0; i < three_band_filter_banks_.size(); ++i) {
99    three_band_filter_banks_[i]->Synthesis(bands->fbuf_const()->bands(i),
100                                           bands->num_frames_per_band(),
101                                           data->fbuf()->channels()[i]);
102  }
103}
104
105}  // namespace webrtc
106