blocker.h (5007B)
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_BLOCKER_H_ 12 #define MODULES_AUDIO_CODING_CODECS_OPUS_TEST_BLOCKER_H_ 13 14 #include <cstddef> 15 #include <memory> 16 17 #include "common_audio/channel_buffer.h" 18 #include "modules/audio_coding/codecs/opus/test/audio_ring_buffer.h" 19 20 namespace webrtc { 21 22 // The callback function to process audio in the time domain. Input has already 23 // been windowed, and output will be windowed. The number of input channels 24 // must be >= the number of output channels. 25 class BlockerCallback { 26 public: 27 virtual ~BlockerCallback() {} 28 29 virtual void ProcessBlock(const float* const* input, 30 size_t num_frames, 31 size_t num_input_channels, 32 size_t num_output_channels, 33 float* const* output) = 0; 34 }; 35 36 // The main purpose of Blocker is to abstract away the fact that often we 37 // receive a different number of audio frames than our transform takes. For 38 // example, most FFTs work best when the fft-size is a power of 2, but suppose 39 // we receive 20ms of audio at a sample rate of 48000. That comes to 960 frames 40 // of audio, which is not a power of 2. Blocker allows us to specify the 41 // transform and all other necessary processing via the Process() callback 42 // function without any constraints on the transform-size 43 // (read: `block_size_`) or received-audio-size (read: `chunk_size_`). 44 // We handle this for the multichannel audio case, allowing for different 45 // numbers of input and output channels (for example, beamforming takes 2 or 46 // more input channels and returns 1 output channel). Audio signals are 47 // represented as deinterleaved floats in the range [-1, 1]. 48 // 49 // Blocker is responsible for: 50 // - blocking audio while handling potential discontinuities on the edges 51 // of chunks 52 // - windowing blocks before sending them to Process() 53 // - windowing processed blocks, and overlap-adding them together before 54 // sending back a processed chunk 55 // 56 // To use blocker: 57 // 1. Impelment a BlockerCallback object `bc`. 58 // 2. Instantiate a Blocker object `b`, passing in `bc`. 59 // 3. As you receive audio, call b.ProcessChunk() to get processed audio. 60 // 61 // A small amount of delay is added to the first received chunk to deal with 62 // the difference in chunk/block sizes. This delay is <= chunk_size. 63 // 64 // Ownership of window is retained by the caller. That is, Blocker makes a 65 // copy of window and does not attempt to delete it. 66 class Blocker { 67 public: 68 Blocker(size_t chunk_size, 69 size_t block_size, 70 size_t num_input_channels, 71 size_t num_output_channels, 72 const float* window, 73 size_t shift_amount, 74 BlockerCallback* callback); 75 ~Blocker(); 76 77 void ProcessChunk(const float* const* input, 78 size_t chunk_size, 79 size_t num_input_channels, 80 size_t num_output_channels, 81 float* const* output); 82 83 size_t initial_delay() const { return initial_delay_; } 84 85 private: 86 const size_t chunk_size_; 87 const size_t block_size_; 88 const size_t num_input_channels_; 89 const size_t num_output_channels_; 90 91 // The number of frames of delay to add at the beginning of the first chunk. 92 const size_t initial_delay_; 93 94 // The frame index into the input buffer where the first block should be read 95 // from. This is necessary because shift_amount_ is not necessarily a 96 // multiple of chunk_size_, so blocks won't line up at the start of the 97 // buffer. 98 size_t frame_offset_; 99 100 // Since blocks nearly always overlap, there are certain blocks that require 101 // frames from the end of one chunk and the beginning of the next chunk. The 102 // input and output buffers are responsible for saving those frames between 103 // calls to ProcessChunk(). 104 // 105 // Both contain |initial delay| + `chunk_size` frames. The input is a fairly 106 // standard FIFO, but due to the overlap-add it's harder to use an 107 // AudioRingBuffer for the output. 108 AudioRingBuffer input_buffer_; 109 ChannelBuffer<float> output_buffer_; 110 111 // Space for the input block (can't wrap because of windowing). 112 ChannelBuffer<float> input_block_; 113 114 // Space for the output block (can't wrap because of overlap/add). 115 ChannelBuffer<float> output_block_; 116 117 std::unique_ptr<float[]> window_; 118 119 // The amount of frames between the start of contiguous blocks. For example, 120 // `shift_amount_` = `block_size_` / 2 for a Hann window. 121 size_t shift_amount_; 122 123 BlockerCallback* callback_; 124 }; 125 126 } // namespace webrtc 127 128 #endif // MODULES_AUDIO_CODING_CODECS_OPUS_TEST_BLOCKER_H_