Add stereo support to FakeAudioDevice.

The stereo-ness depends on the input Capturer and Renderer:
1) The stereo-ness of playout equals to Renderer;
2) The stereo-ness of recording equals to Capturer.

Bug: webrtc:8978
Change-Id: Ib41b8294c30ef6db54fdaf9d1890de0135a976d1
Reviewed-on: https://webrtc-review.googlesource.com/60100
Commit-Queue: Pengyu Liao <pengyul@google.com>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22374}
This commit is contained in:
Pengyu Liao 2018-03-09 09:25:46 -08:00 committed by Commit Bot
parent 2770c3df91
commit ba907f0058
2 changed files with 153 additions and 30 deletions

View File

@ -35,6 +35,8 @@ class TestAudioDeviceModule : public AudioDeviceModule {
// Returns the sampling frequency in Hz of the audio data that this
// capturer produces.
virtual int SamplingFrequency() const = 0;
// Returns the number of channels of captured audio data.
virtual int NumChannels() const = 0;
// Replaces the contents of |buffer| with 10ms of captured audio data
// (see TestAudioDeviceModule::SamplesPerFrame). Returns true if the
// capturer can keep producing data, or false when the capture finishes.
@ -47,6 +49,8 @@ class TestAudioDeviceModule : public AudioDeviceModule {
// Returns the sampling frequency in Hz of the audio data that this
// renderer receives.
virtual int SamplingFrequency() const = 0;
// Returns the number of channels of audio data to be required.
virtual int NumChannels() const = 0;
// Renders the passed audio data and returns true if the renderer wants
// to keep receiving data, or false otherwise.
virtual bool Render(rtc::ArrayView<const int16_t> data) = 0;
@ -75,14 +79,28 @@ class TestAudioDeviceModule : public AudioDeviceModule {
std::unique_ptr<Renderer> renderer,
float speed = 1);
// Returns a Capturer instance that generates a signal where every second
// frame is zero and every second frame is evenly distributed random noise
// with max amplitude |max_amplitude|.
// Returns a Capturer instance that generates a signal of |num_channels|
// channels where every second frame is zero and every second frame is evenly
// distributed random noise with max amplitude |max_amplitude|.
static std::unique_ptr<PulsedNoiseCapturer> CreatePulsedNoiseCapturer(
int16_t max_amplitude,
int sampling_frequency_in_hz,
int num_channels);
// Same as calling CreatePulsedNoiseCapturer(max_amplitude,
// sampling_frequency_in_hz, 1).
static std::unique_ptr<PulsedNoiseCapturer> CreatePulsedNoiseCapturer(
int16_t max_amplitude,
int sampling_frequency_in_hz);
// Returns a Capturer instance that gets its data from a file.
// Returns a Capturer instance that gets its data from a file. The sample rate
// and channels will be check against the Wav file.
static std::unique_ptr<Capturer> CreateWavFileReader(
std::string filename,
int sampling_frequency_in_hz,
int num_channels);
// Same as calling CreateWavFileReader(filename, sampling_frequency_in_hz, 1).
static std::unique_ptr<Capturer> CreateWavFileReader(
std::string filename,
int sampling_frequency_in_hz);
@ -92,6 +110,12 @@ class TestAudioDeviceModule : public AudioDeviceModule {
static std::unique_ptr<Capturer> CreateWavFileReader(std::string filename);
// Returns a Renderer instance that writes its data to a file.
static std::unique_ptr<Renderer> CreateWavFileWriter(
std::string filename,
int sampling_frequency_in_hz,
int num_channels);
// Same as calling CreateWavFileWriter(filename, sampling_frequency_in_hz, 1).
static std::unique_ptr<Renderer> CreateWavFileWriter(
std::string filename,
int sampling_frequency_in_hz);
@ -99,11 +123,23 @@ class TestAudioDeviceModule : public AudioDeviceModule {
// Returns a Renderer instance that writes its data to a WAV file, cutting
// off silence at the beginning (not necessarily perfect silence, see
// kAmplitudeThreshold) and at the end (only actual 0 samples in this case).
static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
std::string filename,
int sampling_frequency_in_hz,
int num_channels);
// Same as calling CreateBounderWavFileWriter(filename,
// sampling_frequency_in_hz, 1).
static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
std::string filename,
int sampling_frequency_in_hz);
// Returns a Renderer instance that does nothing with the audio data.
static std::unique_ptr<Renderer> CreateDiscardRenderer(
int sampling_frequency_in_hz,
int num_channels);
// Same as calling CreateDiscardRenderer(sampling_frequency_in_hz, 1).
static std::unique_ptr<Renderer> CreateDiscardRenderer(
int sampling_frequency_in_hz);

View File

@ -65,7 +65,8 @@ TestAudioDeviceModuleImpl::TestAudioDeviceModuleImpl(
if (renderer_) {
const int sample_rate = renderer_->SamplingFrequency();
playout_buffer_.resize(SamplesPerFrame(sample_rate), 0);
playout_buffer_.resize(
SamplesPerFrame(sample_rate) * renderer_->NumChannels(), 0);
RTC_CHECK(good_sample_rate(sample_rate));
}
if (capturer_) {
@ -154,8 +155,9 @@ void TestAudioDeviceModuleImpl::ProcessAudio() {
uint32_t new_mic_level;
if (recording_buffer_.size() > 0) {
audio_callback_->RecordedDataIsAvailable(
recording_buffer_.data(), recording_buffer_.size(), 2, 1,
capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
recording_buffer_.data(), recording_buffer_.size(), 2,
capturer_->NumChannels(), capturer_->SamplingFrequency(), 0, 0, 0,
false, new_mic_level);
}
if (!keep_capturing) {
capturing_ = false;
@ -168,8 +170,9 @@ void TestAudioDeviceModuleImpl::ProcessAudio() {
int64_t ntp_time_ms;
const int sampling_frequency = renderer_->SamplingFrequency();
audio_callback_->NeedMorePlayData(
SamplesPerFrame(sampling_frequency), 2, 1, sampling_frequency,
playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
SamplesPerFrame(sampling_frequency), 2, renderer_->NumChannels(),
sampling_frequency, playout_buffer_.data(), samples_out,
&elapsed_time_ms, &ntp_time_ms);
const bool keep_rendering = renderer_->Render(
rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
if (!keep_rendering) {
@ -195,16 +198,21 @@ class PulsedNoiseCapturerImpl final
: public TestAudioDeviceModule::PulsedNoiseCapturer {
public:
// Assuming 10ms audio packets.
PulsedNoiseCapturerImpl(int16_t max_amplitude, int sampling_frequency_in_hz)
PulsedNoiseCapturerImpl(int16_t max_amplitude,
int sampling_frequency_in_hz,
int num_channels)
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
fill_with_zero_(false),
random_generator_(1),
max_amplitude_(max_amplitude) {
max_amplitude_(max_amplitude),
num_channels_(num_channels) {
RTC_DCHECK_GT(max_amplitude, 0);
}
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
int NumChannels() const override { return num_channels_; }
bool Capture(rtc::BufferT<int16_t>* buffer) override {
fill_with_zero_ = !fill_with_zero_;
int16_t max_amplitude;
@ -213,7 +221,8 @@ class PulsedNoiseCapturerImpl final
max_amplitude = max_amplitude_;
}
buffer->SetData(
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_),
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
num_channels_,
[&](rtc::ArrayView<int16_t> data) {
if (fill_with_zero_) {
std::fill(data.begin(), data.end(), 0);
@ -238,22 +247,31 @@ class PulsedNoiseCapturerImpl final
Random random_generator_;
rtc::CriticalSection lock_;
int16_t max_amplitude_ RTC_GUARDED_BY(lock_);
const int num_channels_;
};
class WavFileReader final : public TestAudioDeviceModule::Capturer {
public:
WavFileReader(std::string filename, int sampling_frequency_in_hz)
WavFileReader(std::string filename,
int sampling_frequency_in_hz,
int num_channels)
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
num_channels_(num_channels),
wav_reader_(filename) {
RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
RTC_CHECK_EQ(wav_reader_.num_channels(), 1);
RTC_CHECK_EQ(wav_reader_.num_channels(), num_channels);
}
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
int NumChannels() const override {
return num_channels_;
}
bool Capture(rtc::BufferT<int16_t>* buffer) override {
buffer->SetData(
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_),
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
num_channels_,
[&](rtc::ArrayView<int16_t> data) {
return wav_reader_.ReadSamples(data.size(), data.data());
});
@ -262,17 +280,25 @@ class WavFileReader final : public TestAudioDeviceModule::Capturer {
private:
int sampling_frequency_in_hz_;
const int num_channels_;
WavReader wav_reader_;
};
class WavFileWriter final : public TestAudioDeviceModule::Renderer {
public:
WavFileWriter(std::string filename, int sampling_frequency_in_hz)
WavFileWriter(std::string filename, int sampling_frequency_in_hz,
int num_channels)
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
wav_writer_(filename, sampling_frequency_in_hz, 1) {}
wav_writer_(filename, sampling_frequency_in_hz,
num_channels),
num_channels_(num_channels) {}
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
int NumChannels() const override {
return num_channels_;
}
bool Render(rtc::ArrayView<const int16_t> data) override {
wav_writer_.WriteSamples(data.data(), data.size());
return true;
@ -281,21 +307,30 @@ class WavFileWriter final : public TestAudioDeviceModule::Renderer {
private:
int sampling_frequency_in_hz_;
WavWriter wav_writer_;
const int num_channels_;
};
class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer {
public:
BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz)
BoundedWavFileWriter(std::string filename,
int sampling_frequency_in_hz,
int num_channels)
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
wav_writer_(filename, sampling_frequency_in_hz, 1),
wav_writer_(filename, sampling_frequency_in_hz, num_channels),
num_channels_(num_channels),
silent_audio_(
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz),
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) *
num_channels,
0),
started_writing_(false),
trailing_zeros_(0) {}
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
int NumChannels() const override {
return num_channels_;
}
bool Render(rtc::ArrayView<const int16_t> data) override {
const int16_t kAmplitudeThreshold = 5;
@ -339,6 +374,7 @@ class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer {
private:
int sampling_frequency_in_hz_;
WavWriter wav_writer_;
const int num_channels_;
std::vector<int16_t> silent_audio_;
bool started_writing_;
size_t trailing_zeros_;
@ -346,15 +382,23 @@ class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer {
class DiscardRenderer final : public TestAudioDeviceModule::Renderer {
public:
explicit DiscardRenderer(int sampling_frequency_in_hz)
: sampling_frequency_in_hz_(sampling_frequency_in_hz) {}
explicit DiscardRenderer(int sampling_frequency_in_hz, int num_channels)
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
num_channels_(num_channels) {}
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
bool Render(rtc::ArrayView<const int16_t> data) override { return true; }
int NumChannels() const override {
return num_channels_;
}
bool Render(rtc::ArrayView<const int16_t> data) override {
return true;
}
private:
int sampling_frequency_in_hz_;
const int num_channels_;
};
} // namespace
@ -373,32 +417,68 @@ TestAudioDeviceModule::CreateTestAudioDeviceModule(
std::move(capturer), std::move(renderer), speed);
}
std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>
TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude,
int sampling_frequency_in_hz,
int num_channels) {
return std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>(
new PulsedNoiseCapturerImpl(max_amplitude, sampling_frequency_in_hz,
num_channels));
}
std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>
TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude,
int sampling_frequency_in_hz) {
return std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>(
new PulsedNoiseCapturerImpl(max_amplitude, sampling_frequency_in_hz));
new PulsedNoiseCapturerImpl(max_amplitude, sampling_frequency_in_hz, 1));
}
std::unique_ptr<TestAudioDeviceModule::Capturer>
TestAudioDeviceModule::CreateWavFileReader(std::string filename,
int sampling_frequency_in_hz,
int num_channels) {
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
new WavFileReader(filename, sampling_frequency_in_hz, num_channels));
}
std::unique_ptr<TestAudioDeviceModule::Capturer>
TestAudioDeviceModule::CreateWavFileReader(std::string filename,
int sampling_frequency_in_hz) {
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
new WavFileReader(filename, sampling_frequency_in_hz));
new WavFileReader(filename, sampling_frequency_in_hz, 1));
}
std::unique_ptr<TestAudioDeviceModule::Capturer>
TestAudioDeviceModule::CreateWavFileReader(std::string filename) {
int sampling_frequency_in_hz = WavReader(filename).sample_rate();
WavReader reader(filename);
int sampling_frequency_in_hz = reader.sample_rate();
int num_channels = static_cast<int>(reader.num_channels());
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
new WavFileReader(filename, sampling_frequency_in_hz));
new WavFileReader(filename, sampling_frequency_in_hz, num_channels));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
TestAudioDeviceModule::CreateWavFileWriter(std::string filename,
int sampling_frequency_in_hz,
int num_channels) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new WavFileWriter(filename, sampling_frequency_in_hz, num_channels));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
TestAudioDeviceModule::CreateWavFileWriter(std::string filename,
int sampling_frequency_in_hz) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new WavFileWriter(filename, sampling_frequency_in_hz));
new WavFileWriter(filename, sampling_frequency_in_hz, 1));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
TestAudioDeviceModule::CreateBoundedWavFileWriter(std::string filename,
int sampling_frequency_in_hz,
int num_channels) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new BoundedWavFileWriter(filename, sampling_frequency_in_hz,
num_channels));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
@ -406,13 +486,20 @@ TestAudioDeviceModule::CreateBoundedWavFileWriter(
std::string filename,
int sampling_frequency_in_hz) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new BoundedWavFileWriter(filename, sampling_frequency_in_hz));
new BoundedWavFileWriter(filename, sampling_frequency_in_hz, 1));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz,
int num_channels) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new DiscardRenderer(sampling_frequency_in_hz, num_channels));
}
std::unique_ptr<TestAudioDeviceModule::Renderer>
TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz) {
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
new DiscardRenderer(sampling_frequency_in_hz));
new DiscardRenderer(sampling_frequency_in_hz, 1));
}
} // namespace webrtc