Home | History | Annotate | Download | only in common_audio
      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/common_audio/lapped_transform.h"
     12 
     13 #include <algorithm>
     14 #include <cstdlib>
     15 #include <cstring>
     16 
     17 #include "webrtc/base/checks.h"
     18 #include "webrtc/common_audio/real_fourier.h"
     19 
     20 namespace webrtc {
     21 
     22 void LappedTransform::BlockThunk::ProcessBlock(const float* const* input,
     23                                                size_t num_frames,
     24                                                size_t num_input_channels,
     25                                                size_t num_output_channels,
     26                                                float* const* output) {
     27   RTC_CHECK_EQ(num_input_channels, parent_->num_in_channels_);
     28   RTC_CHECK_EQ(num_output_channels, parent_->num_out_channels_);
     29   RTC_CHECK_EQ(parent_->block_length_, num_frames);
     30 
     31   for (size_t i = 0; i < num_input_channels; ++i) {
     32     memcpy(parent_->real_buf_.Row(i), input[i],
     33            num_frames * sizeof(*input[0]));
     34     parent_->fft_->Forward(parent_->real_buf_.Row(i),
     35                            parent_->cplx_pre_.Row(i));
     36   }
     37 
     38   size_t block_length = RealFourier::ComplexLength(
     39       RealFourier::FftOrder(num_frames));
     40   RTC_CHECK_EQ(parent_->cplx_length_, block_length);
     41   parent_->block_processor_->ProcessAudioBlock(parent_->cplx_pre_.Array(),
     42                                                num_input_channels,
     43                                                parent_->cplx_length_,
     44                                                num_output_channels,
     45                                                parent_->cplx_post_.Array());
     46 
     47   for (size_t i = 0; i < num_output_channels; ++i) {
     48     parent_->fft_->Inverse(parent_->cplx_post_.Row(i),
     49                            parent_->real_buf_.Row(i));
     50     memcpy(output[i], parent_->real_buf_.Row(i),
     51            num_frames * sizeof(*input[0]));
     52   }
     53 }
     54 
     55 LappedTransform::LappedTransform(size_t num_in_channels,
     56                                  size_t num_out_channels,
     57                                  size_t chunk_length,
     58                                  const float* window,
     59                                  size_t block_length,
     60                                  size_t shift_amount,
     61                                  Callback* callback)
     62     : blocker_callback_(this),
     63       num_in_channels_(num_in_channels),
     64       num_out_channels_(num_out_channels),
     65       block_length_(block_length),
     66       chunk_length_(chunk_length),
     67       block_processor_(callback),
     68       blocker_(chunk_length_,
     69                block_length_,
     70                num_in_channels_,
     71                num_out_channels_,
     72                window,
     73                shift_amount,
     74                &blocker_callback_),
     75       fft_(RealFourier::Create(RealFourier::FftOrder(block_length_))),
     76       cplx_length_(RealFourier::ComplexLength(fft_->order())),
     77       real_buf_(num_in_channels,
     78                 block_length_,
     79                 RealFourier::kFftBufferAlignment),
     80       cplx_pre_(num_in_channels,
     81                 cplx_length_,
     82                 RealFourier::kFftBufferAlignment),
     83       cplx_post_(num_out_channels,
     84                  cplx_length_,
     85                  RealFourier::kFftBufferAlignment) {
     86   RTC_CHECK(num_in_channels_ > 0 && num_out_channels_ > 0);
     87   RTC_CHECK_GT(block_length_, 0u);
     88   RTC_CHECK_GT(chunk_length_, 0u);
     89   RTC_CHECK(block_processor_);
     90 
     91   // block_length_ power of 2?
     92   RTC_CHECK_EQ(0u, block_length_ & (block_length_ - 1));
     93 }
     94 
     95 void LappedTransform::ProcessChunk(const float* const* in_chunk,
     96                                    float* const* out_chunk) {
     97   blocker_.ProcessChunk(in_chunk, chunk_length_, num_in_channels_,
     98                         num_out_channels_, out_chunk);
     99 }
    100 
    101 }  // namespace webrtc
    102