Use array geometry in Beamformer
R=andrew@webrtc.org Review URL: https://webrtc-codereview.appspot.com/35559004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8000 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
a37bf2c4fe
commit
fb7a039e9d
@ -185,7 +185,8 @@ AudioProcessingImpl::AudioProcessingImpl(const Config& config)
|
||||
use_new_agc_(config.Get<ExperimentalAgc>().enabled),
|
||||
#endif
|
||||
transient_suppressor_enabled_(config.Get<ExperimentalNs>().enabled),
|
||||
beamformer_enabled_(config.Get<Beamforming>().enabled) {
|
||||
beamformer_enabled_(config.Get<Beamforming>().enabled),
|
||||
array_geometry_(config.Get<Beamforming>().array_geometry) {
|
||||
echo_cancellation_ = new EchoCancellationImpl(this, crit_);
|
||||
component_list_.push_back(echo_cancellation_);
|
||||
|
||||
@ -400,7 +401,8 @@ int AudioProcessingImpl::MaybeInitializeLocked(int input_sample_rate_hz,
|
||||
return kNoError;
|
||||
}
|
||||
if (beamformer_enabled_ &&
|
||||
(num_input_channels < 2 || num_output_channels > 1)) {
|
||||
(static_cast<size_t>(num_input_channels) != array_geometry_.size() ||
|
||||
num_output_channels > 1)) {
|
||||
return kBadNumberChannelsError;
|
||||
}
|
||||
return InitializeLocked(input_sample_rate_hz,
|
||||
@ -995,11 +997,9 @@ int AudioProcessingImpl::InitializeTransient() {
|
||||
void AudioProcessingImpl::InitializeBeamformer() {
|
||||
if (beamformer_enabled_) {
|
||||
#ifdef WEBRTC_BEAMFORMER
|
||||
// TODO(aluebs): Don't use a hard-coded microphone spacing.
|
||||
beamformer_.reset(new Beamformer(kChunkSizeMs,
|
||||
split_rate_,
|
||||
fwd_in_format_.num_channels(),
|
||||
0.05f));
|
||||
array_geometry_));
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
|
@ -219,6 +219,7 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
scoped_ptr<TransientSuppressor> transient_suppressor_;
|
||||
const bool beamformer_enabled_;
|
||||
scoped_ptr<Beamformer> beamformer_;
|
||||
const std::vector<Point> array_geometry_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -128,13 +128,12 @@ int Round(float x) {
|
||||
|
||||
Beamformer::Beamformer(int chunk_size_ms,
|
||||
int sample_rate_hz,
|
||||
int num_input_channels,
|
||||
float mic_spacing)
|
||||
const std::vector<Point>& array_geometry)
|
||||
: chunk_length_(sample_rate_hz / (1000.f / chunk_size_ms)),
|
||||
window_(new float[kFftSize]),
|
||||
num_input_channels_(num_input_channels),
|
||||
num_input_channels_(array_geometry.size()),
|
||||
sample_rate_hz_(sample_rate_hz),
|
||||
mic_spacing_(mic_spacing),
|
||||
mic_spacing_(MicSpacingFromGeometry(array_geometry)),
|
||||
decay_threshold_(
|
||||
pow(2, (kFftSize / -2.f) / (sample_rate_hz_ * kHalfLifeSeconds))),
|
||||
mid_frequency_lower_bin_bound_(
|
||||
@ -477,4 +476,18 @@ void Beamformer::CalculateHighFrequencyMask() {
|
||||
high_pass_postfilter_mask_ += high_pass_mask;
|
||||
}
|
||||
|
||||
// This method CHECKs for a uniform linear array.
|
||||
float Beamformer::MicSpacingFromGeometry(const std::vector<Point>& geometry) {
|
||||
CHECK_GE(geometry.size(), 2u);
|
||||
float mic_spacing = 0.f;
|
||||
for (size_t i = 0u; i < 3u; ++i) {
|
||||
float difference = geometry[1].c[i] - geometry[0].c[i];
|
||||
for (size_t j = 2u; j < geometry.size(); ++j) {
|
||||
CHECK_LT(geometry[j].c[i] - geometry[j - 1].c[i] - difference, 1e-6);
|
||||
}
|
||||
mic_spacing += difference * difference;
|
||||
}
|
||||
return sqrt(mic_spacing);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "webrtc/common_audio/lapped_transform.h"
|
||||
#include "webrtc/modules/audio_processing/beamformer/complex_matrix.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -26,12 +27,12 @@ namespace webrtc {
|
||||
// TODO: Target angle assumed to be 0. Parameterize target angle.
|
||||
class Beamformer : public LappedTransform::Callback {
|
||||
public:
|
||||
// At the moment it only accepts uniform linear microphone arrays. Using the
|
||||
// first microphone as a reference position [0, 0, 0] is a natural choice.
|
||||
Beamformer(int chunk_size_ms,
|
||||
// Sample rate corresponds to the lower band.
|
||||
int sample_rate_hz,
|
||||
int num_input_channels,
|
||||
// Microphone spacing in meters.
|
||||
float mic_spacing);
|
||||
const std::vector<Point>& array_geometry);
|
||||
|
||||
// Process one time-domain chunk of audio. The audio can be separated into
|
||||
// two signals by frequency, with the higher half passed in as the second
|
||||
@ -91,6 +92,8 @@ class Beamformer : public LappedTransform::Callback {
|
||||
// Applies both sets of masks to |input| and store in |output|.
|
||||
void ApplyMasks(const complex_f* const* input, complex_f* const* output);
|
||||
|
||||
float MicSpacingFromGeometry(const std::vector<Point>& array_geometry);
|
||||
|
||||
// Deals with the fft transform and blocking.
|
||||
const int chunk_length_;
|
||||
scoped_ptr<LappedTransform> lapped_transform_;
|
||||
|
@ -54,10 +54,14 @@ int main(int argc, char* argv[]) {
|
||||
fseek(read_file, 44, SEEK_SET);
|
||||
|
||||
FILE* write_file = fopen(FLAGS_output_file_path.c_str(), "wb");
|
||||
|
||||
std::vector<webrtc::Point> array_geometry;
|
||||
for (int i = 0; i < FLAGS_num_input_channels; ++i) {
|
||||
array_geometry.push_back(webrtc::Point(i * FLAGS_mic_spacing, 0.f, 0.f));
|
||||
}
|
||||
webrtc::Beamformer bf(kChunkTimeMilliseconds,
|
||||
FLAGS_sample_rate,
|
||||
FLAGS_num_input_channels,
|
||||
FLAGS_mic_spacing);
|
||||
array_geometry);
|
||||
while (true) {
|
||||
size_t samples_read = webrtc::PcmReadToFloat(read_file,
|
||||
kInputSamplesPerChunk,
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdio.h> // FILE
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/platform_file.h"
|
||||
#include "webrtc/common.h"
|
||||
@ -82,12 +83,25 @@ struct ExperimentalNs {
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
// Coordinates in meters.
|
||||
struct Point {
|
||||
Point(float x, float y, float z) {
|
||||
c[0] = x;
|
||||
c[1] = y;
|
||||
c[2] = z;
|
||||
}
|
||||
float c[3];
|
||||
};
|
||||
|
||||
// Use to enable beamforming. Must be provided through the constructor. It will
|
||||
// have no impact if used with AudioProcessing::SetExtraOptions().
|
||||
struct Beamforming {
|
||||
Beamforming() : enabled(false) {}
|
||||
explicit Beamforming(bool enabled) : enabled(enabled) {}
|
||||
bool enabled;
|
||||
Beamforming(bool enabled, const std::vector<Point>& array_geometry)
|
||||
: enabled(enabled),
|
||||
array_geometry(array_geometry) {}
|
||||
const bool enabled;
|
||||
const std::vector<Point> array_geometry;
|
||||
};
|
||||
|
||||
static const int kAudioProcMaxNativeSampleRateHz = 32000;
|
||||
|
Loading…
x
Reference in New Issue
Block a user