Modify NetEqQualityTest
- Take input sample rate as parameter - provides resampling when needed. - Add support for wav output. BUG=2692 R=minyue@webrtc.org Review URL: https://webrtc-codereview.appspot.com/49699004 Cr-Commit-Position: refs/heads/master@{#9158}
This commit is contained in:
parent
cb05b72eb2
commit
83b5c053b9
@ -81,7 +81,7 @@ class NetEq {
|
||||
background_noise_mode(kBgnOff),
|
||||
playout_mode(kPlayoutOn) {}
|
||||
|
||||
int sample_rate_hz; // Initial vale. Will change with input data.
|
||||
int sample_rate_hz; // Initial value. Will change with input data.
|
||||
bool enable_audio_classifier;
|
||||
int max_packets_in_buffer;
|
||||
int max_delay_ms;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
using google::RegisterFlagValidator;
|
||||
using google::ParseCommandLineFlags;
|
||||
@ -19,47 +18,12 @@ using testing::InitGoogleTest;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
namespace {
|
||||
static const int kIsacBlockDurationMs = 30;
|
||||
static const int kIsacInputSamplingKhz = 16;
|
||||
static const int kIsacOutputSamplingKhz = 16;
|
||||
|
||||
// Define switch for input file name.
|
||||
static bool ValidateInFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "rb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
printf("Invalid input filename.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_string(in_filename,
|
||||
ResourcePath("audio_coding/speech_mono_16kHz", "pcm"),
|
||||
"Filename for input audio (should be 16 kHz sampled mono).");
|
||||
|
||||
static const bool in_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename);
|
||||
|
||||
// Define switch for output file name.
|
||||
static bool ValidateOutFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "wb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
printf("Invalid output filename.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_string(out_filename, OutputPath() + "neteq4_isac_quality_test.pcm",
|
||||
"Name of output audio file.");
|
||||
|
||||
static const bool out_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename);
|
||||
|
||||
// Define switch for bir rate.
|
||||
// Define switch for bit rate.
|
||||
static bool ValidateBitRate(const char* flagname, int32_t value) {
|
||||
if (value >= 10 && value <= 32)
|
||||
return true;
|
||||
@ -85,6 +49,8 @@ DEFINE_int32(runtime_ms, 10000, "Simulated runtime (milliseconds).");
|
||||
static const bool runtime_dummy =
|
||||
RegisterFlagValidator(&FLAGS_runtime_ms, &ValidateRuntime);
|
||||
|
||||
} // namespace
|
||||
|
||||
class NetEqIsacQualityTest : public NetEqQualityTest {
|
||||
protected:
|
||||
NetEqIsacQualityTest();
|
||||
@ -98,12 +64,11 @@ class NetEqIsacQualityTest : public NetEqQualityTest {
|
||||
};
|
||||
|
||||
NetEqIsacQualityTest::NetEqIsacQualityTest()
|
||||
: NetEqQualityTest(kIsacBlockDurationMs, kIsacInputSamplingKhz,
|
||||
: NetEqQualityTest(kIsacBlockDurationMs,
|
||||
kIsacInputSamplingKhz,
|
||||
kIsacOutputSamplingKhz,
|
||||
kDecoderISAC,
|
||||
1,
|
||||
FLAGS_in_filename,
|
||||
FLAGS_out_filename),
|
||||
1),
|
||||
isac_encoder_(NULL),
|
||||
bit_rate_kbps_(FLAGS_bit_rate_kbps) {
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
using google::RegisterFlagValidator;
|
||||
using google::ParseCommandLineFlags;
|
||||
@ -20,44 +19,25 @@ using testing::InitGoogleTest;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
static const int kOpusBlockDurationMs = 20;
|
||||
static const int kOpusSamplingKhz = 48;
|
||||
|
||||
// Define switch for input file name.
|
||||
static bool ValidateInFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "rb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
// Define switch for sample rate.
|
||||
static bool ValidateSampleRate(const char* flagname, int32_t value) {
|
||||
if (value == 8000 || value == 16000 || value == 32000 || value == 48000)
|
||||
return true;
|
||||
}
|
||||
printf("Invalid input filename.");
|
||||
printf("Invalid sample rate should be 8000, 16000, 32000 or 48000 Hz.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_string(in_filename,
|
||||
ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm"),
|
||||
"Filename for input audio (should be 48 kHz sampled raw data).");
|
||||
DEFINE_int32(input_sample_rate,
|
||||
kOpusSamplingKhz * 1000,
|
||||
"Sample rate of input file.");
|
||||
|
||||
static const bool in_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename);
|
||||
|
||||
// Define switch for output file name.
|
||||
static bool ValidateOutFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "wb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
printf("Invalid output filename.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_string(out_filename, OutputPath() + "neteq_opus_quality_test.pcm",
|
||||
"Name of output audio file.");
|
||||
|
||||
static const bool out_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename);
|
||||
static const bool sample_rate_dummy =
|
||||
RegisterFlagValidator(&FLAGS_input_sample_rate, &ValidateSampleRate);
|
||||
|
||||
// Define switch for channels.
|
||||
static bool ValidateChannels(const char* flagname, int32_t value) {
|
||||
@ -125,6 +105,8 @@ DEFINE_int32(sub_packets, 1, "Number of sub packets to repacketize.");
|
||||
static const bool sub_packets_dummy =
|
||||
RegisterFlagValidator(&FLAGS_sub_packets, &ValidateSubPackets);
|
||||
|
||||
} // namepsace
|
||||
|
||||
class NetEqOpusQualityTest : public NetEqQualityTest {
|
||||
protected:
|
||||
NetEqOpusQualityTest();
|
||||
@ -149,9 +131,7 @@ NetEqOpusQualityTest::NetEqOpusQualityTest()
|
||||
kOpusSamplingKhz,
|
||||
kOpusSamplingKhz,
|
||||
(FLAGS_channels == 1) ? kDecoderOpus : kDecoderOpus_2ch,
|
||||
FLAGS_channels,
|
||||
FLAGS_in_filename,
|
||||
FLAGS_out_filename),
|
||||
FLAGS_channels),
|
||||
opus_encoder_(NULL),
|
||||
repacketizer_(NULL),
|
||||
sub_block_size_samples_(kOpusBlockDurationMs * kOpusSamplingKhz),
|
||||
|
@ -32,7 +32,7 @@ class InputAudioFile {
|
||||
// if the read was successful, otherwise false. If the file end is reached,
|
||||
// the file is rewound and reading continues from the beginning.
|
||||
// The output |destination| must have the capacity to hold |samples| elements.
|
||||
bool Read(size_t samples, int16_t* destination);
|
||||
virtual bool Read(size_t samples, int16_t* destination);
|
||||
|
||||
// Creates a multi-channel signal from a mono signal. Each sample is repeated
|
||||
// |channels| times to create an interleaved multi-channel signal where all
|
||||
|
@ -10,7 +10,14 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
@ -20,6 +27,61 @@ const int kOutputSizeMs = 10;
|
||||
const int kInitSeed = 0x12345678;
|
||||
const int kPacketLossTimeUnitMs = 10;
|
||||
|
||||
// Common validator for file names.
|
||||
static bool ValidateFilename(const string& value, bool write) {
|
||||
FILE* fid = write ? fopen(value.c_str(), "wb") : fopen(value.c_str(), "rb");
|
||||
if (fid == nullptr)
|
||||
return false;
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Define switch for input file name.
|
||||
static bool ValidateInFilename(const char* flagname, const string& value) {
|
||||
if (!ValidateFilename(value, false)) {
|
||||
printf("Invalid input filename.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_string(
|
||||
in_filename,
|
||||
ResourcePath("audio_coding/speech_mono_16kHz", "pcm"),
|
||||
"Filename for input audio (specify sample rate with --input_sample_rate).");
|
||||
|
||||
static const bool in_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename);
|
||||
|
||||
// Define switch for sample rate.
|
||||
static bool ValidateSampleRate(const char* flagname, int32_t value) {
|
||||
if (value == 8000 || value == 16000 || value == 32000 || value == 48000)
|
||||
return true;
|
||||
printf("Invalid sample rate should be 8000, 16000, 32000 or 48000 Hz.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_int32(input_sample_rate, 16000, "Sample rate of input file in Hz.");
|
||||
|
||||
static const bool sample_rate_dummy =
|
||||
RegisterFlagValidator(&FLAGS_input_sample_rate, &ValidateSampleRate);
|
||||
|
||||
// Define switch for output file name.
|
||||
static bool ValidateOutFilename(const char* flagname, const string& value) {
|
||||
if (!ValidateFilename(value, true)) {
|
||||
printf("Invalid output filename.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_string(out_filename,
|
||||
OutputPath() + "neteq_quality_test_out.pcm",
|
||||
"Name of output audio file.");
|
||||
|
||||
static const bool out_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename);
|
||||
|
||||
// Define switch for packet loss rate.
|
||||
static bool ValidatePacketLossRate(const char* /* flag_name */, int32_t value) {
|
||||
if (value >= 0 && value <= 100)
|
||||
@ -120,9 +182,7 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
|
||||
int in_sampling_khz,
|
||||
int out_sampling_khz,
|
||||
enum NetEqDecoder decoder_type,
|
||||
int channels,
|
||||
std::string in_filename,
|
||||
std::string out_filename)
|
||||
int channels)
|
||||
: decoded_time_ms_(0),
|
||||
decodable_time_ms_(0),
|
||||
drift_factor_(FLAGS_drift_factor),
|
||||
@ -132,19 +192,32 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
|
||||
out_sampling_khz_(out_sampling_khz),
|
||||
decoder_type_(decoder_type),
|
||||
channels_(channels),
|
||||
in_filename_(in_filename),
|
||||
out_filename_(out_filename),
|
||||
log_filename_(out_filename + ".log"),
|
||||
in_size_samples_(in_sampling_khz_ * block_duration_ms_),
|
||||
out_size_samples_(out_sampling_khz_ * kOutputSizeMs),
|
||||
payload_size_bytes_(0),
|
||||
max_payload_bytes_(0),
|
||||
in_file_(new InputAudioFile(in_filename_)),
|
||||
out_file_(NULL),
|
||||
in_file_(new ResampleInputAudioFile(FLAGS_in_filename,
|
||||
FLAGS_input_sample_rate,
|
||||
in_sampling_khz * 1000)),
|
||||
log_file_(NULL),
|
||||
rtp_generator_(new RtpGenerator(in_sampling_khz_, 0, 0,
|
||||
decodable_time_ms_)),
|
||||
rtp_generator_(
|
||||
new RtpGenerator(in_sampling_khz_, 0, 0, decodable_time_ms_)),
|
||||
total_payload_size_bytes_(0) {
|
||||
const std::string out_filename = FLAGS_out_filename;
|
||||
const std::string log_filename = out_filename + ".log";
|
||||
log_file_ = fopen(log_filename.c_str(), "wt");
|
||||
CHECK(log_file_);
|
||||
|
||||
if (out_filename.size() >= 4 &&
|
||||
out_filename.substr(out_filename.size() - 4) == ".wav") {
|
||||
// Open a wav file.
|
||||
output_.reset(
|
||||
new webrtc::test::OutputWavFile(out_filename, 1000 * out_sampling_khz));
|
||||
} else {
|
||||
// Open a pcm file.
|
||||
output_.reset(new webrtc::test::OutputAudioFile(out_filename));
|
||||
}
|
||||
|
||||
NetEq::Config config;
|
||||
config.sample_rate_hz = out_sampling_khz_ * 1000;
|
||||
neteq_.reset(NetEq::Create(config));
|
||||
@ -189,9 +262,6 @@ bool GilbertElliotLoss::Lost() {
|
||||
}
|
||||
|
||||
void NetEqQualityTest::SetUp() {
|
||||
out_file_ = fopen(out_filename_.c_str(), "wb");
|
||||
log_file_ = fopen(log_filename_.c_str(), "wt");
|
||||
ASSERT_TRUE(out_file_ != NULL);
|
||||
ASSERT_EQ(0, neteq_->RegisterPayloadType(decoder_type_, kPayloadType));
|
||||
rtp_generator_->set_drift_factor(drift_factor_);
|
||||
|
||||
@ -245,10 +315,6 @@ void NetEqQualityTest::SetUp() {
|
||||
srand(kInitSeed);
|
||||
}
|
||||
|
||||
void NetEqQualityTest::TearDown() {
|
||||
fclose(out_file_);
|
||||
}
|
||||
|
||||
bool NetEqQualityTest::PacketLost() {
|
||||
int cycles = block_duration_ms_ / kPacketLossTimeUnitMs;
|
||||
|
||||
@ -297,7 +363,7 @@ int NetEqQualityTest::DecodeBlock() {
|
||||
} else {
|
||||
assert(channels == channels_);
|
||||
assert(samples == kOutputSizeMs * out_sampling_khz_);
|
||||
fwrite(&out_data_[0], sizeof(int16_t), samples * channels, out_file_);
|
||||
CHECK(output_->WriteArray(out_data_.get(), samples * channels));
|
||||
return samples;
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,10 @@
|
||||
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_QUALITY_TEST_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <string>
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
@ -66,11 +66,8 @@ class NetEqQualityTest : public ::testing::Test {
|
||||
int in_sampling_khz,
|
||||
int out_sampling_khz,
|
||||
enum NetEqDecoder decoder_type,
|
||||
int channels,
|
||||
std::string in_filename,
|
||||
std::string out_filename);
|
||||
int channels);
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
// EncodeBlock(...) does the following:
|
||||
// 1. encodes a block of audio, saved in |in_data| and has a length of
|
||||
@ -108,9 +105,6 @@ class NetEqQualityTest : public ::testing::Test {
|
||||
const int out_sampling_khz_;
|
||||
const enum NetEqDecoder decoder_type_;
|
||||
const int channels_;
|
||||
const std::string in_filename_;
|
||||
const std::string out_filename_;
|
||||
const std::string log_filename_;
|
||||
|
||||
// Number of samples per channel in a frame.
|
||||
const int in_size_samples_;
|
||||
@ -122,7 +116,7 @@ class NetEqQualityTest : public ::testing::Test {
|
||||
int max_payload_bytes_;
|
||||
|
||||
rtc::scoped_ptr<InputAudioFile> in_file_;
|
||||
FILE* out_file_;
|
||||
rtc::scoped_ptr<AudioSink> output_;
|
||||
FILE* log_file_;
|
||||
|
||||
rtc::scoped_ptr<RtpGenerator> rtp_generator_;
|
||||
|
@ -37,5 +37,14 @@ bool ResampleInputAudioFile::Read(size_t samples,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResampleInputAudioFile::Read(size_t samples, int16_t* destination) {
|
||||
CHECK_GT(output_rate_hz_, 0) << "Output rate not set.";
|
||||
return Read(samples, output_rate_hz_, destination);
|
||||
}
|
||||
|
||||
void ResampleInputAudioFile::set_output_rate_hz(int rate_hz) {
|
||||
output_rate_hz_ = rate_hz;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
@ -25,12 +25,23 @@ namespace test {
|
||||
class ResampleInputAudioFile : public InputAudioFile {
|
||||
public:
|
||||
ResampleInputAudioFile(const std::string file_name, int file_rate_hz)
|
||||
: InputAudioFile(file_name), file_rate_hz_(file_rate_hz) {}
|
||||
: InputAudioFile(file_name),
|
||||
file_rate_hz_(file_rate_hz),
|
||||
output_rate_hz_(-1) {}
|
||||
ResampleInputAudioFile(const std::string file_name,
|
||||
int file_rate_hz,
|
||||
int output_rate_hz)
|
||||
: InputAudioFile(file_name),
|
||||
file_rate_hz_(file_rate_hz),
|
||||
output_rate_hz_(output_rate_hz) {}
|
||||
|
||||
bool Read(size_t samples, int output_rate_hz, int16_t* destination);
|
||||
bool Read(size_t samples, int16_t* destination) override;
|
||||
void set_output_rate_hz(int rate_hz);
|
||||
|
||||
private:
|
||||
const int file_rate_hz_;
|
||||
int output_rate_hz_;
|
||||
Resampler resampler_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ResampleInputAudioFile);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user