| /* | 
 |  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "webrtc/common_audio/lapped_transform.h" | 
 |  | 
 | #include <algorithm> | 
 | #include <cstdlib> | 
 | #include <cstring> | 
 |  | 
 | #include "webrtc/base/checks.h" | 
 | #include "webrtc/common_audio/real_fourier.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | void LappedTransform::BlockThunk::ProcessBlock(const float* const* input, | 
 |                                                size_t num_frames, | 
 |                                                size_t num_input_channels, | 
 |                                                size_t num_output_channels, | 
 |                                                float* const* output) { | 
 |   RTC_CHECK_EQ(num_input_channels, parent_->num_in_channels_); | 
 |   RTC_CHECK_EQ(num_output_channels, parent_->num_out_channels_); | 
 |   RTC_CHECK_EQ(parent_->block_length_, num_frames); | 
 |  | 
 |   for (size_t i = 0; i < num_input_channels; ++i) { | 
 |     memcpy(parent_->real_buf_.Row(i), input[i], | 
 |            num_frames * sizeof(*input[0])); | 
 |     parent_->fft_->Forward(parent_->real_buf_.Row(i), | 
 |                            parent_->cplx_pre_.Row(i)); | 
 |   } | 
 |  | 
 |   size_t block_length = RealFourier::ComplexLength( | 
 |       RealFourier::FftOrder(num_frames)); | 
 |   RTC_CHECK_EQ(parent_->cplx_length_, block_length); | 
 |   parent_->block_processor_->ProcessAudioBlock(parent_->cplx_pre_.Array(), | 
 |                                                num_input_channels, | 
 |                                                parent_->cplx_length_, | 
 |                                                num_output_channels, | 
 |                                                parent_->cplx_post_.Array()); | 
 |  | 
 |   for (size_t i = 0; i < num_output_channels; ++i) { | 
 |     parent_->fft_->Inverse(parent_->cplx_post_.Row(i), | 
 |                            parent_->real_buf_.Row(i)); | 
 |     memcpy(output[i], parent_->real_buf_.Row(i), | 
 |            num_frames * sizeof(*input[0])); | 
 |   } | 
 | } | 
 |  | 
 | LappedTransform::LappedTransform(size_t num_in_channels, | 
 |                                  size_t num_out_channels, | 
 |                                  size_t chunk_length, | 
 |                                  const float* window, | 
 |                                  size_t block_length, | 
 |                                  size_t shift_amount, | 
 |                                  Callback* callback) | 
 |     : blocker_callback_(this), | 
 |       num_in_channels_(num_in_channels), | 
 |       num_out_channels_(num_out_channels), | 
 |       block_length_(block_length), | 
 |       chunk_length_(chunk_length), | 
 |       block_processor_(callback), | 
 |       blocker_(chunk_length_, | 
 |                block_length_, | 
 |                num_in_channels_, | 
 |                num_out_channels_, | 
 |                window, | 
 |                shift_amount, | 
 |                &blocker_callback_), | 
 |       fft_(RealFourier::Create(RealFourier::FftOrder(block_length_))), | 
 |       cplx_length_(RealFourier::ComplexLength(fft_->order())), | 
 |       real_buf_(num_in_channels, | 
 |                 block_length_, | 
 |                 RealFourier::kFftBufferAlignment), | 
 |       cplx_pre_(num_in_channels, | 
 |                 cplx_length_, | 
 |                 RealFourier::kFftBufferAlignment), | 
 |       cplx_post_(num_out_channels, | 
 |                  cplx_length_, | 
 |                  RealFourier::kFftBufferAlignment) { | 
 |   RTC_CHECK(num_in_channels_ > 0); | 
 |   RTC_CHECK_GT(block_length_, 0); | 
 |   RTC_CHECK_GT(chunk_length_, 0); | 
 |   RTC_CHECK(block_processor_); | 
 |  | 
 |   // block_length_ power of 2? | 
 |   RTC_CHECK_EQ(0, block_length_ & (block_length_ - 1)); | 
 | } | 
 |  | 
 | LappedTransform::~LappedTransform() = default; | 
 |  | 
 | void LappedTransform::ProcessChunk(const float* const* in_chunk, | 
 |                                    float* const* out_chunk) { | 
 |   blocker_.ProcessChunk(in_chunk, chunk_length_, num_in_channels_, | 
 |                         num_out_channels_, out_chunk); | 
 | } | 
 |  | 
 | }  // namespace webrtc |