Skip to content

Commit

Permalink
Use better reference files with audioproc_unittest.
Browse files Browse the repository at this point in the history
The files are shorter (7 s) with one set provided for each sample rate.

Will be accompanied by the following set of files in the resource bundle:
far8_stereo.pcm
far16_stereo.pcm
far32_stereo.pcm
near8_stereo.pcm
near16_stereo.pcm
near32_stereo.pcm

BUG=114
TEST=audioproc_unittest

Review URL: https://webrtc-codereview.appspot.com/380003

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1617 4adac7df-926f-26a2-2b94-8c16560cd09d
  • Loading branch information
[email protected] committed Feb 7, 2012
1 parent 2660460 commit daacee8
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 66 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ vars = {

# External resources like video and audio files used for testing purposes.
# Downloaded on demand when needed.
"webrtc_resources_revision": "7",
"webrtc_resources_revision": "8",
}

# NOTE: Prefer revision numbers to tags for svn deps.
Expand Down
211 changes: 146 additions & 65 deletions src/modules/audio_processing/test/unit_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ using webrtc::VoiceDetection;
namespace {
// When false, this will compare the output data with the results stored to
// file. This is the typical case. When the file should be updated, it can
// be set to true with the command-line switch --write_output_data.
bool write_output_data = false;
// be set to true with the command-line switch --write_ref_data.
bool write_ref_data = false;

class ApmTest : public ::testing::Test {
protected:
Expand All @@ -66,29 +66,43 @@ class ApmTest : public ::testing::Test {
static void TearDownTestCase() {
Trace::ReturnTrace();
}
// Path to where the resource files to be used for this test are located.
const std::string resource_path;
const std::string output_filename;

void Init(int sample_rate_hz, int num_reverse_channels,
int num_input_channels, int num_output_channels,
bool open_output_file);
std::string ResourceFilePath(std::string name, int sample_rate_hz);
std::string OutputFilePath(std::string name,
int sample_rate_hz,
int num_reverse_channels,
int num_input_channels,
int num_output_channels);

const std::string output_path_;
const std::string ref_path_;
const std::string ref_filename_;
webrtc::AudioProcessing* apm_;
webrtc::AudioFrame* frame_;
webrtc::AudioFrame* revframe_;
FILE* far_file_;
FILE* near_file_;
FILE* out_file_;
};

ApmTest::ApmTest()
: resource_path(webrtc::test::ProjectRootPath() +
"test/data/audio_processing/"),
: output_path_(webrtc::test::OutputPath()),
ref_path_(webrtc::test::ProjectRootPath() +
"test/data/audio_processing/"),
#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
output_filename(resource_path + "output_data_fixed.pb"),
ref_filename_(ref_path_ + "output_data_fixed.pb"),
#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
output_filename(resource_path + "output_data_float.pb"),
ref_filename_(ref_path_ + "output_data_float.pb"),
#endif
apm_(NULL),
frame_(NULL),
revframe_(NULL),
far_file_(NULL),
near_file_(NULL) {}
near_file_(NULL),
out_file_(NULL) {}

void ApmTest::SetUp() {
apm_ = AudioProcessing::Create(0);
Expand All @@ -97,25 +111,7 @@ void ApmTest::SetUp() {
frame_ = new AudioFrame();
revframe_ = new AudioFrame();

ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2));
ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2));

frame_->_payloadDataLengthInSamples = 320;
frame_->_audioChannel = 2;
frame_->_frequencyInHz = 32000;
revframe_->_payloadDataLengthInSamples = 320;
revframe_->_audioChannel = 2;
revframe_->_frequencyInHz = 32000;

std::string input_filename = resource_path + "aec_far.pcm";
far_file_ = fopen(input_filename.c_str(), "rb");
ASSERT_TRUE(far_file_ != NULL) << "Could not open input file " <<
input_filename << "\n";
input_filename = resource_path + "aec_near.pcm";
near_file_ = fopen(input_filename.c_str(), "rb");
ASSERT_TRUE(near_file_ != NULL) << "Could not open input file " <<
input_filename << "\n";
Init(32000, 2, 2, 2, false);
}

void ApmTest::TearDown() {
Expand All @@ -139,12 +135,95 @@ void ApmTest::TearDown() {
}
near_file_ = NULL;

if (out_file_) {
ASSERT_EQ(0, fclose(out_file_));
}
out_file_ = NULL;

if (apm_ != NULL) {
AudioProcessing::Destroy(apm_);
}
apm_ = NULL;
}

std::string ApmTest::ResourceFilePath(std::string name, int sample_rate_hz) {
std::ostringstream ss;
// Resource files are all stereo.
ss << name << sample_rate_hz / 1000 << "_stereo";
return webrtc::test::ResourcePath(ss.str(), "pcm");
}

std::string ApmTest::OutputFilePath(std::string name,
int sample_rate_hz,
int num_reverse_channels,
int num_input_channels,
int num_output_channels) {
std::ostringstream ss;
ss << name << sample_rate_hz / 1000 << "_" << num_reverse_channels << "r" <<
num_input_channels << "i" << "_";
if (num_output_channels == 1) {
ss << "mono";
} else if (num_output_channels == 2) {
ss << "stereo";
} else {
assert(false);
return "";
}
ss << ".pcm";

return output_path_ + ss.str();
}


void ApmTest::Init(int sample_rate_hz, int num_reverse_channels,
int num_input_channels, int num_output_channels,
bool open_output_file) {
ASSERT_EQ(apm_->kNoError, apm_->Initialize());

// Handles error checking of the parameters as well. No need to repeat it.
ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(sample_rate_hz));
ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(num_input_channels,
num_output_channels));
ASSERT_EQ(apm_->kNoError,
apm_->set_num_reverse_channels(num_reverse_channels));

// We always use 10 ms frames.
const int samples_per_channel = sample_rate_hz / 100;
frame_->_payloadDataLengthInSamples = samples_per_channel;
frame_->_audioChannel = num_input_channels;
frame_->_frequencyInHz = sample_rate_hz;
revframe_->_payloadDataLengthInSamples = samples_per_channel;
revframe_->_audioChannel = num_reverse_channels;
revframe_->_frequencyInHz = sample_rate_hz;

if (far_file_) {
ASSERT_EQ(0, fclose(far_file_));
}
std::string filename = ResourceFilePath("far", sample_rate_hz);
far_file_ = fopen(filename.c_str(), "rb");
ASSERT_TRUE(far_file_ != NULL) << "Could not open file " <<
filename << "\n";

if (near_file_) {
ASSERT_EQ(0, fclose(near_file_));
}
filename = ResourceFilePath("near", sample_rate_hz);
near_file_ = fopen(filename.c_str(), "rb");
ASSERT_TRUE(near_file_ != NULL) << "Could not open file " <<
filename << "\n";

if (open_output_file) {
if (out_file_) {
ASSERT_EQ(0, fclose(out_file_));
}
filename = OutputFilePath("out", sample_rate_hz, num_reverse_channels,
num_input_channels, num_output_channels);
out_file_ = fopen(filename.c_str(), "wb");
ASSERT_TRUE(out_file_ != NULL) << "Could not open file " <<
filename << "\n";
}
}

void MixStereoToMono(const int16_t* stereo,
int16_t* mono,
int samples_per_channel) {
Expand Down Expand Up @@ -1014,13 +1093,12 @@ TEST_F(ApmTest, DebugDump) {
#ifdef WEBRTC_AUDIOPROC_BIT_EXACT
TEST_F(ApmTest, Process) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
webrtc::audioproc::OutputData output_data;
webrtc::audioproc::OutputData ref_data;

if (!write_output_data) {
ReadMessageLiteFromFile(output_filename, &output_data);
if (!write_ref_data) {
ReadMessageLiteFromFile(ref_filename_, &ref_data);
} else {
// We don't have a file; add the required tests to the protobuf.
// TODO(ajm): vary the output channels as well?
// Write the desired tests to the protobuf reference file.
const int channels[] = {1, 2};
const size_t channels_size = sizeof(channels) / sizeof(*channels);
#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
Expand All @@ -1032,12 +1110,15 @@ TEST_F(ApmTest, Process) {
const size_t sample_rates_size = sizeof(sample_rates) / sizeof(*sample_rates);
for (size_t i = 0; i < channels_size; i++) {
for (size_t j = 0; j < channels_size; j++) {
for (size_t k = 0; k < sample_rates_size; k++) {
webrtc::audioproc::Test* test = output_data.add_test();
test->set_num_reverse_channels(channels[i]);
test->set_num_input_channels(channels[j]);
test->set_num_output_channels(channels[j]);
test->set_sample_rate(sample_rates[k]);
// We can't have more output than input channels.
for (size_t k = 0; k <= j; k++) {
for (size_t l = 0; l < sample_rates_size; l++) {
webrtc::audioproc::Test* test = ref_data.add_test();
test->set_num_reverse_channels(channels[i]);
test->set_num_input_channels(channels[j]);
test->set_num_output_channels(channels[k]);
test->set_sample_rate(sample_rates[l]);
}
}
}
}
Expand Down Expand Up @@ -1078,25 +1159,14 @@ TEST_F(ApmTest, Process) {
EXPECT_EQ(apm_->kNoError,
apm_->voice_detection()->Enable(true));

for (int i = 0; i < output_data.test_size(); i++) {
printf("Running test %d of %d...\n", i + 1, output_data.test_size());
for (int i = 0; i < ref_data.test_size(); i++) {
printf("Running test %d of %d...\n", i + 1, ref_data.test_size());

webrtc::audioproc::Test* test = output_data.mutable_test(i);
const int samples_per_channel = test->sample_rate() / 100;
revframe_->_payloadDataLengthInSamples = samples_per_channel;
revframe_->_audioChannel = test->num_reverse_channels();
revframe_->_frequencyInHz = test->sample_rate();
frame_->_payloadDataLengthInSamples = samples_per_channel;
frame_->_audioChannel = test->num_input_channels();
frame_->_frequencyInHz = test->sample_rate();

EXPECT_EQ(apm_->kNoError, apm_->Initialize());
ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(test->sample_rate()));
ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(frame_->_audioChannel,
frame_->_audioChannel));
ASSERT_EQ(apm_->kNoError,
apm_->set_num_reverse_channels(revframe_->_audioChannel));
webrtc::audioproc::Test* test = ref_data.mutable_test(i);
Init(test->sample_rate(), test->num_reverse_channels(),
test->num_input_channels(), test->num_output_channels(), true);

const int samples_per_channel = test->sample_rate() / 100;
int frame_count = 0;
int has_echo_count = 0;
int has_voice_count = 0;
Expand All @@ -1106,8 +1176,8 @@ TEST_F(ApmTest, Process) {
int max_output_average = 0;

while (1) {
// Read far-end frame
const size_t frame_size = samples_per_channel * 2;
// Read far-end frame, always stereo.
size_t frame_size = samples_per_channel * 2;
size_t read_count = fread(revframe_->_payloadData,
sizeof(int16_t),
frame_size,
Expand All @@ -1131,7 +1201,7 @@ TEST_F(ApmTest, Process) {
EXPECT_EQ(apm_->kNoError,
apm_->gain_control()->set_stream_analog_level(analog_level));

// Read near-end frame
// Read near-end frame, always stereo.
read_count = fread(frame_->_payloadData,
sizeof(int16_t),
frame_size,
Expand All @@ -1149,6 +1219,8 @@ TEST_F(ApmTest, Process) {
frame_->_vadActivity = AudioFrame::kVadUnknown;

EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
// Ensure the frame was downmixed properly.
EXPECT_EQ(test->num_output_channels(), frame_->_audioChannel);

max_output_average += MaxAudioFrame(*frame_);

Expand All @@ -1168,6 +1240,15 @@ TEST_F(ApmTest, Process) {
EXPECT_EQ(AudioFrame::kVadPassive, frame_->_vadActivity);
}

frame_size = samples_per_channel * frame_->_audioChannel;
size_t write_count = fwrite(frame_->_payloadData,
sizeof(int16_t),
frame_size,
out_file_);
ASSERT_EQ(frame_size, write_count);

// Reset in case of downmixing.
frame_->_audioChannel = test->num_input_channels();
frame_count++;
}
max_output_average /= frame_count;
Expand All @@ -1187,7 +1268,7 @@ TEST_F(ApmTest, Process) {
EXPECT_GE(127, rms_level);
#endif

if (!write_output_data) {
if (!write_ref_data) {
EXPECT_EQ(test->has_echo_count(), has_echo_count);
EXPECT_EQ(test->has_voice_count(), has_voice_count);
EXPECT_EQ(test->is_saturated_count(), is_saturated_count);
Expand Down Expand Up @@ -1247,8 +1328,8 @@ TEST_F(ApmTest, Process) {
rewind(near_file_);
}

if (write_output_data) {
WriteMessageLiteToFile(output_filename, output_data);
if (write_ref_data) {
WriteMessageLiteToFile(ref_filename_, ref_data);
}
}
#endif // WEBRTC_AUDIOPROC_BIT_EXACT
Expand All @@ -1259,8 +1340,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);

for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--write_output_data") == 0) {
write_output_data = true;
if (strcmp(argv[i], "--write_ref_data") == 0) {
write_ref_data = true;
}
}

Expand Down
Binary file removed test/data/audio_processing/aec_far.pcm
Binary file not shown.
Binary file removed test/data/audio_processing/aec_near.pcm
Binary file not shown.
Binary file modified test/data/audio_processing/output_data_fixed.pb
Binary file not shown.
Binary file modified test/data/audio_processing/output_data_float.pb
Binary file not shown.

0 comments on commit daacee8

Please sign in to comment.