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 #ifndef MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_ 12 #define MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_ 13 14 #include <complex> 15 #include <memory> 16 17 #include "common_audio/real_fourier.h" 18 #include "modules/audio_coding/codecs/opus/test/blocker.h" 19 #include "rtc_base/memory/aligned_malloc.h" 20 21 namespace webrtc { 22 23 // Wrapper class for aligned arrays. Every row (and the first dimension) are 24 // aligned to the given byte alignment. 25 template <typename T> 26 class AlignedArray { 27 public: AlignedArray(size_t rows,size_t cols,size_t alignment)28 AlignedArray(size_t rows, size_t cols, size_t alignment) 29 : rows_(rows), cols_(cols) { 30 RTC_CHECK_GT(alignment, 0); 31 head_row_ = 32 static_cast<T**>(AlignedMalloc(rows_ * sizeof(*head_row_), alignment)); 33 for (size_t i = 0; i < rows_; ++i) { 34 head_row_[i] = static_cast<T*>( 35 AlignedMalloc(cols_ * sizeof(**head_row_), alignment)); 36 } 37 } 38 ~AlignedArray()39 ~AlignedArray() { 40 for (size_t i = 0; i < rows_; ++i) { 41 AlignedFree(head_row_[i]); 42 } 43 AlignedFree(head_row_); 44 } 45 Array()46 T* const* Array() { return head_row_; } 47 Array()48 const T* const* Array() const { return head_row_; } 49 Row(size_t row)50 T* Row(size_t row) { 51 RTC_CHECK_LE(row, rows_); 52 return head_row_[row]; 53 } 54 Row(size_t row)55 const T* Row(size_t row) const { 56 RTC_CHECK_LE(row, rows_); 57 return head_row_[row]; 58 } 59 60 private: 61 size_t rows_; 62 size_t cols_; 63 T** head_row_; 64 }; 65 66 // Helper class for audio processing modules which operate on frequency domain 67 // input derived from the windowed time domain audio stream. 68 // 69 // The input audio chunk is sliced into possibly overlapping blocks, multiplied 70 // by a window and transformed with an FFT implementation. The transformed data 71 // is supplied to the given callback for processing. The processed output is 72 // then inverse transformed into the time domain and spliced back into a chunk 73 // which constitutes the final output of this processing module. 74 class LappedTransform { 75 public: 76 class Callback { 77 public: ~Callback()78 virtual ~Callback() {} 79 80 virtual void ProcessAudioBlock(const std::complex<float>* const* in_block, 81 size_t num_in_channels, 82 size_t frames, 83 size_t num_out_channels, 84 std::complex<float>* const* out_block) = 0; 85 }; 86 87 // Construct a transform instance. |chunk_length| is the number of samples in 88 // each channel. |window| defines the window, owned by the caller (a copy is 89 // made internally); |window| should have length equal to |block_length|. 90 // |block_length| defines the length of a block, in samples. 91 // |shift_amount| is in samples. |callback| is the caller-owned audio 92 // processing function called for each block of the input chunk. 93 LappedTransform(size_t num_in_channels, 94 size_t num_out_channels, 95 size_t chunk_length, 96 const float* window, 97 size_t block_length, 98 size_t shift_amount, 99 Callback* callback); 100 ~LappedTransform(); 101 102 // Main audio processing helper method. Internally slices |in_chunk| into 103 // blocks, transforms them to frequency domain, calls the callback for each 104 // block and returns a de-blocked time domain chunk of audio through 105 // |out_chunk|. Both buffers are caller-owned. 106 void ProcessChunk(const float* const* in_chunk, float* const* out_chunk); 107 108 // Get the chunk length. 109 // 110 // The chunk length is the number of samples per channel that must be passed 111 // to ProcessChunk via the parameter in_chunk. 112 // 113 // Returns the same chunk_length passed to the LappedTransform constructor. chunk_length()114 size_t chunk_length() const { return chunk_length_; } 115 116 // Get the number of input channels. 117 // 118 // This is the number of arrays that must be passed to ProcessChunk via 119 // in_chunk. 120 // 121 // Returns the same num_in_channels passed to the LappedTransform constructor. num_in_channels()122 size_t num_in_channels() const { return num_in_channels_; } 123 124 // Get the number of output channels. 125 // 126 // This is the number of arrays that must be passed to ProcessChunk via 127 // out_chunk. 128 // 129 // Returns the same num_out_channels passed to the LappedTransform 130 // constructor. num_out_channels()131 size_t num_out_channels() const { return num_out_channels_; } 132 133 // Returns the initial delay. 134 // 135 // This is the delay introduced by the |blocker_| to be able to get and return 136 // chunks of |chunk_length|, but process blocks of |block_length|. initial_delay()137 size_t initial_delay() const { return blocker_.initial_delay(); } 138 139 private: 140 // Internal middleware callback, given to the blocker. Transforms each block 141 // and hands it over to the processing method given at construction time. 142 class BlockThunk : public BlockerCallback { 143 public: BlockThunk(LappedTransform * parent)144 explicit BlockThunk(LappedTransform* parent) : parent_(parent) {} 145 146 void ProcessBlock(const float* const* input, 147 size_t num_frames, 148 size_t num_input_channels, 149 size_t num_output_channels, 150 float* const* output) override; 151 152 private: 153 LappedTransform* const parent_; 154 } blocker_callback_; 155 156 const size_t num_in_channels_; 157 const size_t num_out_channels_; 158 159 const size_t block_length_; 160 const size_t chunk_length_; 161 162 Callback* const block_processor_; 163 Blocker blocker_; 164 165 // TODO(alessiob): Replace RealFourier with a different FFT library. 166 std::unique_ptr<RealFourier> fft_; 167 const size_t cplx_length_; 168 AlignedArray<float> real_buf_; 169 AlignedArray<std::complex<float> > cplx_pre_; 170 AlignedArray<std::complex<float> > cplx_post_; 171 }; 172 173 } // namespace webrtc 174 175 #endif // MODULES_AUDIO_CODING_CODECS_OPUS_TEST_LAPPED_TRANSFORM_H_ 176