Extend TestAudioDeviceModule API.
Extend TestAudioDeviceModule API to be able to create WavReader/WavWriter from rtc::PlatformFile Bug: webrtc:8946 Change-Id: Ieea16be91c40a5928689cdeaa8a17d75fee0cf82 Reviewed-on: https://webrtc-review.googlesource.com/63266 Commit-Queue: Artem Titov <titovartem@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22576}
This commit is contained in:
parent
866e08d282
commit
8458cff411
@ -21,7 +21,9 @@
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/platform_thread.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "rtc_base/random.h"
|
||||
#include "rtc_base/refcountedobject.h"
|
||||
#include "system_wrappers/include/event_wrapper.h"
|
||||
@ -276,12 +278,16 @@ class WavFileReader final : public TestAudioDeviceModule::Capturer {
|
||||
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(), num_channels);
|
||||
}
|
||||
: WavFileReader(rtc::MakeUnique<WavReader>(filename),
|
||||
sampling_frequency_in_hz,
|
||||
num_channels) {}
|
||||
|
||||
WavFileReader(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels)
|
||||
: WavFileReader(rtc::MakeUnique<WavReader>(file),
|
||||
sampling_frequency_in_hz,
|
||||
num_channels) {}
|
||||
|
||||
int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
|
||||
|
||||
@ -292,15 +298,25 @@ class WavFileReader final : public TestAudioDeviceModule::Capturer {
|
||||
TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
|
||||
num_channels_,
|
||||
[&](rtc::ArrayView<int16_t> data) {
|
||||
return wav_reader_.ReadSamples(data.size(), data.data());
|
||||
return wav_reader_->ReadSamples(data.size(), data.data());
|
||||
});
|
||||
return buffer->size() > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
WavFileReader(std::unique_ptr<WavReader> wav_reader,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels)
|
||||
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
|
||||
num_channels_(num_channels),
|
||||
wav_reader_(std::move(wav_reader)) {
|
||||
RTC_CHECK_EQ(wav_reader_->sample_rate(), sampling_frequency_in_hz);
|
||||
RTC_CHECK_EQ(wav_reader_->num_channels(), num_channels);
|
||||
}
|
||||
|
||||
int sampling_frequency_in_hz_;
|
||||
const int num_channels_;
|
||||
WavReader wav_reader_;
|
||||
std::unique_ptr<WavReader> wav_reader_;
|
||||
};
|
||||
|
||||
class WavFileWriter final : public TestAudioDeviceModule::Renderer {
|
||||
@ -308,22 +324,40 @@ class WavFileWriter final : public TestAudioDeviceModule::Renderer {
|
||||
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, num_channels),
|
||||
num_channels_(num_channels) {}
|
||||
: WavFileWriter(rtc::MakeUnique<WavWriter>(filename,
|
||||
sampling_frequency_in_hz,
|
||||
num_channels),
|
||||
sampling_frequency_in_hz,
|
||||
num_channels) {}
|
||||
|
||||
WavFileWriter(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels)
|
||||
: WavFileWriter(rtc::MakeUnique<WavWriter>(file,
|
||||
sampling_frequency_in_hz,
|
||||
num_channels),
|
||||
sampling_frequency_in_hz,
|
||||
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());
|
||||
wav_writer_->WriteSamples(data.data(), data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
WavFileWriter(std::unique_ptr<WavWriter> wav_writer,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels)
|
||||
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
|
||||
wav_writer_(std::move(wav_writer)),
|
||||
num_channels_(num_channels) {}
|
||||
|
||||
int sampling_frequency_in_hz_;
|
||||
WavWriter wav_writer_;
|
||||
std::unique_ptr<WavWriter> wav_writer_;
|
||||
const int num_channels_;
|
||||
};
|
||||
|
||||
@ -342,6 +376,19 @@ class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer {
|
||||
started_writing_(false),
|
||||
trailing_zeros_(0) {}
|
||||
|
||||
BoundedWavFileWriter(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels)
|
||||
: sampling_frequency_in_hz_(sampling_frequency_in_hz),
|
||||
wav_writer_(file, sampling_frequency_in_hz, num_channels),
|
||||
num_channels_(num_channels),
|
||||
silent_audio_(
|
||||
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_; }
|
||||
@ -436,11 +483,11 @@ TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude,
|
||||
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, 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::Capturer>
|
||||
@ -451,18 +498,11 @@ TestAudioDeviceModule::CreateWavFileReader(std::string filename,
|
||||
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, 1));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Capturer>
|
||||
TestAudioDeviceModule::CreateWavFileReader(std::string filename) {
|
||||
WavReader reader(filename);
|
||||
int sampling_frequency_in_hz = reader.sample_rate();
|
||||
int num_channels = static_cast<int>(reader.num_channels());
|
||||
int num_channels = rtc::checked_cast<int>(reader.num_channels());
|
||||
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
|
||||
new WavFileReader(filename, sampling_frequency_in_hz, num_channels));
|
||||
}
|
||||
@ -475,13 +515,6 @@ TestAudioDeviceModule::CreateWavFileWriter(std::string filename,
|
||||
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, 1));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer>
|
||||
TestAudioDeviceModule::CreateBoundedWavFileWriter(std::string filename,
|
||||
int sampling_frequency_in_hz,
|
||||
@ -491,25 +524,37 @@ TestAudioDeviceModule::CreateBoundedWavFileWriter(std::string filename,
|
||||
num_channels));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer>
|
||||
TestAudioDeviceModule::CreateBoundedWavFileWriter(
|
||||
std::string filename,
|
||||
int sampling_frequency_in_hz) {
|
||||
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
|
||||
new BoundedWavFileWriter(filename, sampling_frequency_in_hz, 1));
|
||||
std::unique_ptr<TestAudioDeviceModule::Capturer>
|
||||
TestAudioDeviceModule::CreateWavFileReader(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels) {
|
||||
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
|
||||
new WavFileReader(file, sampling_frequency_in_hz, num_channels));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Capturer>
|
||||
TestAudioDeviceModule::CreateWavFileReader(rtc::PlatformFile file) {
|
||||
WavReader reader(file);
|
||||
int sampling_frequency_in_hz = reader.sample_rate();
|
||||
int num_channels = rtc::checked_cast<int>(reader.num_channels());
|
||||
return std::unique_ptr<TestAudioDeviceModule::Capturer>(
|
||||
new WavFileReader(file, sampling_frequency_in_hz, num_channels));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer>
|
||||
TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz,
|
||||
int num_channels) {
|
||||
TestAudioDeviceModule::CreateWavFileWriter(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels) {
|
||||
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
|
||||
new DiscardRenderer(sampling_frequency_in_hz, num_channels));
|
||||
new WavFileWriter(file, sampling_frequency_in_hz, num_channels));
|
||||
}
|
||||
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer>
|
||||
TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz) {
|
||||
TestAudioDeviceModule::CreateBoundedWavFileWriter(rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels) {
|
||||
return std::unique_ptr<TestAudioDeviceModule::Renderer>(
|
||||
new DiscardRenderer(sampling_frequency_in_hz, 1));
|
||||
new BoundedWavFileWriter(file, sampling_frequency_in_hz, num_channels));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "modules/audio_device/include/audio_device.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/platform_file.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
namespace webrtc {
|
||||
@ -85,40 +86,31 @@ class TestAudioDeviceModule : public AudioDeviceModule {
|
||||
static std::unique_ptr<PulsedNoiseCapturer> CreatePulsedNoiseCapturer(
|
||||
int16_t max_amplitude,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels);
|
||||
int num_channels = 1);
|
||||
|
||||
// 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 Renderer instance that does nothing with the audio data.
|
||||
static std::unique_ptr<Renderer> CreateDiscardRenderer(
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels = 1);
|
||||
|
||||
// WavReader and WavWriter creation based on file name.
|
||||
|
||||
// Returns a Capturer instance that gets its data from a file. The sample rate
|
||||
// and channels will be check against the Wav file.
|
||||
// and channels will be checked 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);
|
||||
int num_channels = 1);
|
||||
|
||||
// Returns a Capturer instance that gets its data from a file.
|
||||
// Automatically detects sample rate.
|
||||
// Automatically detects sample rate and num of channels.
|
||||
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);
|
||||
int num_channels = 1);
|
||||
|
||||
// Returns a Renderer instance that writes its data to a WAV file, cutting
|
||||
// off silence at the beginning (not necessarily perfect silence, see
|
||||
@ -126,22 +118,34 @@ class TestAudioDeviceModule : public AudioDeviceModule {
|
||||
static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
|
||||
std::string filename,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels);
|
||||
int num_channels = 1);
|
||||
|
||||
// Same as calling CreateBounderWavFileWriter(filename,
|
||||
// sampling_frequency_in_hz, 1).
|
||||
static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
|
||||
std::string filename,
|
||||
int sampling_frequency_in_hz);
|
||||
// WavReader and WavWriter creation based on rtc::PlatformFile.
|
||||
|
||||
// Returns a Renderer instance that does nothing with the audio data.
|
||||
static std::unique_ptr<Renderer> CreateDiscardRenderer(
|
||||
// Returns a Capturer instance that gets its data from a file. The sample rate
|
||||
// and channels will be checked against the Wav file.
|
||||
static std::unique_ptr<Capturer> CreateWavFileReader(
|
||||
rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels);
|
||||
int num_channels = 1);
|
||||
|
||||
// Same as calling CreateDiscardRenderer(sampling_frequency_in_hz, 1).
|
||||
static std::unique_ptr<Renderer> CreateDiscardRenderer(
|
||||
int sampling_frequency_in_hz);
|
||||
// Returns a Capturer instance that gets its data from a file.
|
||||
// Automatically detects sample rate and num of channels.
|
||||
static std::unique_ptr<Capturer> CreateWavFileReader(rtc::PlatformFile file);
|
||||
|
||||
// Returns a Renderer instance that writes its data to a file.
|
||||
static std::unique_ptr<Renderer> CreateWavFileWriter(
|
||||
rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels = 1);
|
||||
|
||||
// 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(
|
||||
rtc::PlatformFile file,
|
||||
int sampling_frequency_in_hz,
|
||||
int num_channels = 1);
|
||||
|
||||
virtual int32_t Init() = 0;
|
||||
virtual int32_t RegisterAudioCallback(AudioTransport* callback) = 0;
|
||||
|
||||
@ -11,30 +11,78 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "common_audio/wav_file.h"
|
||||
#include "common_audio/wav_header.h"
|
||||
#include "modules/audio_device/include/test_audio_device.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/testsupport/fileutils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
void RunTest(const std::vector<int16_t>& input_samples,
|
||||
const std::vector<int16_t>& expected_samples,
|
||||
size_t samples_per_frame) {
|
||||
|
||||
void RunTestViaRtcPlatformFileAPI(
|
||||
rtc::ArrayView<const int16_t> input_samples,
|
||||
rtc::ArrayView<const int16_t> expected_samples,
|
||||
size_t samples_per_frame) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
const std::string output_filename = test::OutputPath() +
|
||||
"BoundedWavFileWriterTest_" +
|
||||
test_info->name() + ".wav";
|
||||
const std::string output_filename =
|
||||
test::OutputPath() + "BoundedWavFileWriterTest_" + test_info->name() +
|
||||
"_" + std::to_string(std::rand()) + ".wav";
|
||||
|
||||
static const size_t kSamplesPerFrame = 8;
|
||||
static const int kSampleRate = kSamplesPerFrame * 100;
|
||||
EXPECT_EQ(TestAudioDeviceModule::SamplesPerFrame(kSampleRate),
|
||||
kSamplesPerFrame);
|
||||
|
||||
// Test through rtc::PlatformFile API.
|
||||
{
|
||||
auto file = rtc::CreatePlatformFile(output_filename);
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer> writer =
|
||||
TestAudioDeviceModule::CreateBoundedWavFileWriter(file, 800);
|
||||
|
||||
for (size_t i = 0; i < input_samples.size(); i += kSamplesPerFrame) {
|
||||
EXPECT_TRUE(writer->Render(rtc::ArrayView<const int16_t>(
|
||||
&input_samples[i],
|
||||
std::min(kSamplesPerFrame, input_samples.size() - i))));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto file = rtc::OpenPlatformFile(output_filename);
|
||||
WavReader reader(file);
|
||||
std::vector<int16_t> read_samples(expected_samples.size());
|
||||
EXPECT_EQ(expected_samples.size(),
|
||||
reader.ReadSamples(read_samples.size(), read_samples.data()));
|
||||
EXPECT_THAT(expected_samples, testing::ElementsAreArray(read_samples));
|
||||
|
||||
EXPECT_EQ(0u, reader.ReadSamples(read_samples.size(), read_samples.data()));
|
||||
}
|
||||
|
||||
remove(output_filename.c_str());
|
||||
}
|
||||
|
||||
void RunTest(const std::vector<int16_t>& input_samples,
|
||||
const std::vector<int16_t>& expected_samples,
|
||||
size_t samples_per_frame) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
const std::string output_filename =
|
||||
test::OutputPath() + "BoundedWavFileWriterTest_" + test_info->name() +
|
||||
"_" + std::to_string(std::rand()) + ".wav";
|
||||
|
||||
static const size_t kSamplesPerFrame = 8;
|
||||
static const int kSampleRate = kSamplesPerFrame * 100;
|
||||
EXPECT_EQ(TestAudioDeviceModule::SamplesPerFrame(kSampleRate),
|
||||
kSamplesPerFrame);
|
||||
|
||||
// Test through file name API.
|
||||
{
|
||||
std::unique_ptr<TestAudioDeviceModule::Renderer> writer =
|
||||
TestAudioDeviceModule::CreateBoundedWavFileWriter(output_filename, 800);
|
||||
@ -76,6 +124,14 @@ TEST(BoundedWavFileWriterTest, SomeStartSilence) {
|
||||
RunTest(kInputSamples, kExpectedSamples, 8);
|
||||
}
|
||||
|
||||
TEST(BoundedWavFileWriterTest, SomeStartSilenceRtcFile) {
|
||||
static const std::vector<int16_t> kInputSamples = {
|
||||
0, 0, 0, 0, 3, 0, 0, 0, 0, 3, -13222, -7, -3525, 5787, -25247, 8};
|
||||
static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 10,
|
||||
kInputSamples.end());
|
||||
RunTestViaRtcPlatformFileAPI(kInputSamples, kExpectedSamples, 8);
|
||||
}
|
||||
|
||||
TEST(BoundedWavFileWriterTest, NegativeStartSilence) {
|
||||
static const std::vector<int16_t> kInputSamples = {
|
||||
0, -4, -6, 0, 3, 0, 0, 0, 0, 3, -13222, -7, -3525, 5787, -25247, 8};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user