blob: edf81d337a5a8ff9dddbaa009a8ba74d0f8c5088 [file] [log] [blame]
andrew@webrtc.org325cff02014-10-01 17:42:18 +00001/*
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 WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_
12#define WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_
13
kwibergc2b785d2016-02-24 05:22:32 -080014#include <memory>
15
andrew@webrtc.org041035b2015-01-26 21:23:53 +000016#include "webrtc/common_audio/audio_ring_buffer.h"
kjellander@webrtc.org035e9122015-01-28 19:57:00 +000017#include "webrtc/common_audio/channel_buffer.h"
andrew@webrtc.org325cff02014-10-01 17:42:18 +000018
19namespace webrtc {
20
21// The callback function to process audio in the time domain. Input has already
22// been windowed, and output will be windowed. The number of input channels
23// must be >= the number of output channels.
24class BlockerCallback {
25 public:
26 virtual ~BlockerCallback() {}
27
28 virtual void ProcessBlock(const float* const* input,
Peter Kastingdce40cf2015-08-24 14:52:23 -070029 size_t num_frames,
Peter Kasting69558702016-01-12 16:26:35 -080030 size_t num_input_channels,
31 size_t num_output_channels,
andrew@webrtc.org325cff02014-10-01 17:42:18 +000032 float* const* output) = 0;
33};
34
35// The main purpose of Blocker is to abstract away the fact that often we
36// receive a different number of audio frames than our transform takes. For
37// example, most FFTs work best when the fft-size is a power of 2, but suppose
38// we receive 20ms of audio at a sample rate of 48000. That comes to 960 frames
39// of audio, which is not a power of 2. Blocker allows us to specify the
40// transform and all other necessary processing via the Process() callback
41// function without any constraints on the transform-size
42// (read: |block_size_|) or received-audio-size (read: |chunk_size_|).
43// We handle this for the multichannel audio case, allowing for different
44// numbers of input and output channels (for example, beamforming takes 2 or
45// more input channels and returns 1 output channel). Audio signals are
46// represented as deinterleaved floats in the range [-1, 1].
47//
48// Blocker is responsible for:
49// - blocking audio while handling potential discontinuities on the edges
50// of chunks
51// - windowing blocks before sending them to Process()
52// - windowing processed blocks, and overlap-adding them together before
53// sending back a processed chunk
54//
55// To use blocker:
56// 1. Impelment a BlockerCallback object |bc|.
57// 2. Instantiate a Blocker object |b|, passing in |bc|.
58// 3. As you receive audio, call b.ProcessChunk() to get processed audio.
59//
60// A small amount of delay is added to the first received chunk to deal with
61// the difference in chunk/block sizes. This delay is <= chunk_size.
mgraczyk@chromium.orge5340862015-03-12 23:23:38 +000062//
63// Ownership of window is retained by the caller. That is, Blocker makes a
64// copy of window and does not attempt to delete it.
andrew@webrtc.org325cff02014-10-01 17:42:18 +000065class Blocker {
66 public:
Peter Kastingdce40cf2015-08-24 14:52:23 -070067 Blocker(size_t chunk_size,
68 size_t block_size,
Peter Kasting69558702016-01-12 16:26:35 -080069 size_t num_input_channels,
70 size_t num_output_channels,
andrew@webrtc.org325cff02014-10-01 17:42:18 +000071 const float* window,
Peter Kastingdce40cf2015-08-24 14:52:23 -070072 size_t shift_amount,
andrew@webrtc.org325cff02014-10-01 17:42:18 +000073 BlockerCallback* callback);
74
75 void ProcessChunk(const float* const* input,
Peter Kastingdce40cf2015-08-24 14:52:23 -070076 size_t chunk_size,
Peter Kasting69558702016-01-12 16:26:35 -080077 size_t num_input_channels,
78 size_t num_output_channels,
andrew@webrtc.org325cff02014-10-01 17:42:18 +000079 float* const* output);
80
81 private:
Peter Kastingdce40cf2015-08-24 14:52:23 -070082 const size_t chunk_size_;
83 const size_t block_size_;
Peter Kasting69558702016-01-12 16:26:35 -080084 const size_t num_input_channels_;
85 const size_t num_output_channels_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +000086
87 // The number of frames of delay to add at the beginning of the first chunk.
Peter Kastingdce40cf2015-08-24 14:52:23 -070088 const size_t initial_delay_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +000089
90 // The frame index into the input buffer where the first block should be read
91 // from. This is necessary because shift_amount_ is not necessarily a
92 // multiple of chunk_size_, so blocks won't line up at the start of the
93 // buffer.
Peter Kastingdce40cf2015-08-24 14:52:23 -070094 size_t frame_offset_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +000095
96 // Since blocks nearly always overlap, there are certain blocks that require
97 // frames from the end of one chunk and the beginning of the next chunk. The
98 // input and output buffers are responsible for saving those frames between
99 // calls to ProcessChunk().
100 //
andrew@webrtc.org041035b2015-01-26 21:23:53 +0000101 // Both contain |initial delay| + |chunk_size| frames. The input is a fairly
102 // standard FIFO, but due to the overlap-add it's harder to use an
103 // AudioRingBuffer for the output.
104 AudioRingBuffer input_buffer_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +0000105 ChannelBuffer<float> output_buffer_;
106
107 // Space for the input block (can't wrap because of windowing).
108 ChannelBuffer<float> input_block_;
109
110 // Space for the output block (can't wrap because of overlap/add).
111 ChannelBuffer<float> output_block_;
112
kwibergc2b785d2016-02-24 05:22:32 -0800113 std::unique_ptr<float[]> window_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +0000114
115 // The amount of frames between the start of contiguous blocks. For example,
116 // |shift_amount_| = |block_size_| / 2 for a Hann window.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700117 size_t shift_amount_;
andrew@webrtc.org325cff02014-10-01 17:42:18 +0000118
119 BlockerCallback* callback_;
120};
121
122} // namespace webrtc
123
124#endif // WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_