diff --git a/webrtc/modules/audio_coding/neteq/interface/neteq.h b/webrtc/modules/audio_coding/neteq/interface/neteq.h index 5d1bbfce9d..587a1a377c 100644 --- a/webrtc/modules/audio_coding/neteq/interface/neteq.h +++ b/webrtc/modules/audio_coding/neteq/interface/neteq.h @@ -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; diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc index 7abf5a1fa7..fc41115a2a 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc @@ -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) { } diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc index 3edf89cf52..3cc4888005 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc @@ -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), diff --git a/webrtc/modules/audio_coding/neteq/tools/input_audio_file.h b/webrtc/modules/audio_coding/neteq/tools/input_audio_file.h index f546119be2..075b5d33b5 100644 --- a/webrtc/modules/audio_coding/neteq/tools/input_audio_file.h +++ b/webrtc/modules/audio_coding/neteq/tools/input_audio_file.h @@ -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 diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc index 832885573c..fdbd66e1f0 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc @@ -10,7 +10,14 @@ #include #include +#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; } } diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h index cb40b1cc82..cbe753ac17 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h @@ -12,10 +12,10 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_QUALITY_TEST_H_ #include -#include #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 in_file_; - FILE* out_file_; + rtc::scoped_ptr output_; FILE* log_file_; rtc::scoped_ptr rtp_generator_; diff --git a/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.cc b/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.cc index 74d593e6ac..47450bc887 100644 --- a/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.cc +++ b/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.cc @@ -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 diff --git a/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h b/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h index 8c028005cb..b15d46faff 100644 --- a/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h +++ b/webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h @@ -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); };