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 COMMON_AUDIO_LAPPED_TRANSFORM_H_ 12 #define COMMON_AUDIO_LAPPED_TRANSFORM_H_ 13 14 #include <complex> 15 #include <memory> 16 17 #include "common_audio/blocker.h" 18 #include "common_audio/real_fourier.h" 19 #include "system_wrappers/include/aligned_array.h" 20 21 namespace webrtc { 22 23 // Helper class for audio processing modules which operate on frequency domain 24 // input derived from the windowed time domain audio stream. 25 // 26 // The input audio chunk is sliced into possibly overlapping blocks, multiplied 27 // by a window and transformed with an FFT implementation. The transformed data 28 // is supplied to the given callback for processing. The processed output is 29 // then inverse transformed into the time domain and spliced back into a chunk 30 // which constitutes the final output of this processing module. 31 class LappedTransform { 32 public: 33 class Callback { 34 public: ~Callback()35 virtual ~Callback() {} 36 37 virtual void ProcessAudioBlock(const std::complex<float>* const* in_block, 38 size_t num_in_channels, size_t frames, 39 size_t num_out_channels, 40 std::complex<float>* const* out_block) = 0; 41 }; 42 43 // Construct a transform instance. |chunk_length| is the number of samples in 44 // each channel. |window| defines the window, owned by the caller (a copy is 45 // made internally); |window| should have length equal to |block_length|. 46 // |block_length| defines the length of a block, in samples. 47 // |shift_amount| is in samples. |callback| is the caller-owned audio 48 // processing function called for each block of the input chunk. 49 LappedTransform(size_t num_in_channels, 50 size_t num_out_channels, 51 size_t chunk_length, 52 const float* window, 53 size_t block_length, 54 size_t shift_amount, 55 Callback* callback); 56 ~LappedTransform(); 57 58 // Main audio processing helper method. Internally slices |in_chunk| into 59 // blocks, transforms them to frequency domain, calls the callback for each 60 // block and returns a de-blocked time domain chunk of audio through 61 // |out_chunk|. Both buffers are caller-owned. 62 void ProcessChunk(const float* const* in_chunk, float* const* out_chunk); 63 64 // Get the chunk length. 65 // 66 // The chunk length is the number of samples per channel that must be passed 67 // to ProcessChunk via the parameter in_chunk. 68 // 69 // Returns the same chunk_length passed to the LappedTransform constructor. chunk_length()70 size_t chunk_length() const { return chunk_length_; } 71 72 // Get the number of input channels. 73 // 74 // This is the number of arrays that must be passed to ProcessChunk via 75 // in_chunk. 76 // 77 // Returns the same num_in_channels passed to the LappedTransform constructor. num_in_channels()78 size_t num_in_channels() const { return num_in_channels_; } 79 80 // Get the number of output channels. 81 // 82 // This is the number of arrays that must be passed to ProcessChunk via 83 // out_chunk. 84 // 85 // Returns the same num_out_channels passed to the LappedTransform 86 // constructor. num_out_channels()87 size_t num_out_channels() const { return num_out_channels_; } 88 89 // Returns the initial delay. 90 // 91 // This is the delay introduced by the |blocker_| to be able to get and return 92 // chunks of |chunk_length|, but process blocks of |block_length|. initial_delay()93 size_t initial_delay() const { return blocker_.initial_delay(); } 94 95 private: 96 // Internal middleware callback, given to the blocker. Transforms each block 97 // and hands it over to the processing method given at construction time. 98 class BlockThunk : public BlockerCallback { 99 public: BlockThunk(LappedTransform * parent)100 explicit BlockThunk(LappedTransform* parent) : parent_(parent) {} 101 102 void ProcessBlock(const float* const* input, 103 size_t num_frames, 104 size_t num_input_channels, 105 size_t num_output_channels, 106 float* const* output) override; 107 108 private: 109 LappedTransform* const parent_; 110 } blocker_callback_; 111 112 const size_t num_in_channels_; 113 const size_t num_out_channels_; 114 115 const size_t block_length_; 116 const size_t chunk_length_; 117 118 Callback* const block_processor_; 119 Blocker blocker_; 120 121 std::unique_ptr<RealFourier> fft_; 122 const size_t cplx_length_; 123 AlignedArray<float> real_buf_; 124 AlignedArray<std::complex<float> > cplx_pre_; 125 AlignedArray<std::complex<float> > cplx_post_; 126 }; 127 128 } // namespace webrtc 129 130 #endif // COMMON_AUDIO_LAPPED_TRANSFORM_H_ 131 132