Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(982)

Unified Diff: webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc

Issue 2790933002: Conversational speech tool, simualtor + unit tests (Closed)
Patch Set: UT workaround due to webrtc:7769 bug Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc
diff --git a/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc b/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc
index 6797beb98305272e9aa19626317a049000b0dcf1..02513c4336abf6aadfc3623ed05f9fdd4db8fd95 100644
--- a/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc
+++ b/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc
@@ -40,13 +40,16 @@
#include <cmath>
#include <map>
#include <memory>
+#include <vector>
#include "webrtc/base/logging.h"
+#include "webrtc/base/optional.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/common_audio/wav_file.h"
#include "webrtc/modules/audio_processing/test/conversational_speech/config.h"
#include "webrtc/modules/audio_processing/test/conversational_speech/mock_wavreader_factory.h"
#include "webrtc/modules/audio_processing/test/conversational_speech/multiend_call.h"
+#include "webrtc/modules/audio_processing/test/conversational_speech/simulator.h"
#include "webrtc/modules/audio_processing/test/conversational_speech/timing.h"
#include "webrtc/modules/audio_processing/test/conversational_speech/wavreader_factory.h"
#include "webrtc/test/gmock.h"
@@ -83,9 +86,12 @@ const std::size_t kNumberOfTurns = expected_timing.size();
constexpr int kDefaultSampleRate = 48000;
const std::map<std::string, const MockWavReaderFactory::Params>
kDefaultMockWavReaderFactoryParamsMap = {
- {"t300", {kDefaultSampleRate, 1u, 14400u}}, // 0.3 seconds.
- {"t500", {kDefaultSampleRate, 1u, 24000u}}, // 0.5 seconds.
- {"t1000", {kDefaultSampleRate, 1u, 48000u}}, // 1.0 seconds.
+ {"t300", {kDefaultSampleRate, 1u, 14400u}}, // Mono, 0.3 seconds.
+ {"t500", {kDefaultSampleRate, 1u, 24000u}}, // Mono, 0.5 seconds.
+ {"t1000", {kDefaultSampleRate, 1u, 48000u}}, // Mono, 1.0 seconds.
+ {"sr8000", {8000, 1u, 8000u}}, // 8kHz sample rate, mono, 1 second.
+ {"sr16000", {16000, 1u, 16000u}}, // 16kHz sample rate, mono, 1 second.
+ {"sr16000_stereo", {16000, 2u, 16000u}}, // Like sr16000, but stereo.
};
const MockWavReaderFactory::Params& kDefaultMockWavReaderFactoryParams =
kDefaultMockWavReaderFactoryParamsMap.at("t500");
@@ -113,6 +119,57 @@ void CreateSineWavFile(const std::string& filepath,
wav_writer.WriteSamples(samples.data(), params.num_samples);
}
+// Parameters to generate audio tracks with CreateSineWavFile.
+struct SineAudioTrackParams {
+ MockWavReaderFactory::Params params;
+ float frequency;
+};
+
+// Creates a temporary directory in which sine audio tracks are written.
+std::string CreateTemporarySineAudioTracks(
+ const std::map<std::string, SineAudioTrackParams>& sine_tracks_params) {
+ // Create temporary directory.
+ rtc::Pathname temp_directory(OutputPath());
+ temp_directory.AppendFolder("TempConversationalSpeechAudioTracks");
+ CreateDir(temp_directory.pathname());
+
+ // Create sine tracks.
+ for (const auto& it : sine_tracks_params) {
+ const rtc::Pathname temp_filepath(temp_directory.pathname(), it.first);
+ CreateSineWavFile(
+ temp_filepath.pathname(), it.second.params, it.second.frequency);
+ }
+
+ return temp_directory.pathname();
+}
+
+void CheckAudioTrackParams(const WavReaderFactory& wav_reader_factory,
+ const std::string& filepath,
+ const MockWavReaderFactory::Params& expeted_params) {
+ auto wav_reader = wav_reader_factory.Create(filepath);
+ EXPECT_EQ(expeted_params.sample_rate, wav_reader->SampleRate());
+ EXPECT_EQ(expeted_params.num_channels, wav_reader->NumChannels());
+ EXPECT_EQ(expeted_params.num_samples, wav_reader->NumSamples());
+}
+
+void DeleteFolderAndContents(const std::string& dir) {
+ if (!DirExists(dir)) { return; }
+ rtc::Optional<std::vector<std::string>> dir_content = ReadDirectory(dir);
+ EXPECT_TRUE(dir_content);
+ for (const auto& path : *dir_content) {
+ if (DirExists(path)) {
+ DeleteFolderAndContents(path);
+ } else if (FileExists(path)) {
+ // TODO(alessiob): Wrap with EXPECT_TRUE() once webrtc:7769 bug fixed.
+ RemoveFile(path);
+ } else {
+ FAIL();
+ }
+ }
+ // TODO(alessiob): Wrap with EXPECT_TRUE() once webrtc:7769 bug fixed.
+ RemoveDir(dir);
+}
+
} // namespace
using testing::_;
@@ -138,8 +195,8 @@ TEST_F(ConversationalSpeechTest, Settings) {
TEST_F(ConversationalSpeechTest, TimingSaveLoad) {
// Save test timing.
- const std::string temporary_filepath = webrtc::test::TempFilename(
- webrtc::test::OutputPath(), "TempTimingTestFile");
+ const std::string temporary_filepath = TempFilename(
+ OutputPath(), "TempTimingTestFile");
SaveTiming(temporary_filepath, expected_timing);
// Create a std::vector<Turn> instance by loading from file.
@@ -173,6 +230,52 @@ TEST_F(ConversationalSpeechTest, MultiEndCallCreate) {
EXPECT_EQ(6u, multiend_call.speaking_turns().size());
}
+TEST_F(ConversationalSpeechTest, MultiEndCallSetupDifferentSampleRates) {
+ const std::vector<Turn> timing = {
+ {"A", "sr8000", 0},
+ {"B", "sr16000", 0},
+ };
+ auto mock_wavreader_factory = CreateMockWavReaderFactory();
+
+ // There are two unique audio tracks to read.
+ EXPECT_CALL(*mock_wavreader_factory, Create(testing::_)).Times(2);
+
+ MultiEndCall multiend_call(
+ timing, audiotracks_path, std::move(mock_wavreader_factory));
+ EXPECT_FALSE(multiend_call.valid());
+}
+
+TEST_F(ConversationalSpeechTest, MultiEndCallSetupMultipleChannels) {
+ const std::vector<Turn> timing = {
+ {"A", "sr16000_stereo", 0},
+ {"B", "sr16000_stereo", 0},
+ };
+ auto mock_wavreader_factory = CreateMockWavReaderFactory();
+
+ // There is one unique audio track to read.
+ EXPECT_CALL(*mock_wavreader_factory, Create(testing::_)).Times(1);
+
+ MultiEndCall multiend_call(
+ timing, audiotracks_path, std::move(mock_wavreader_factory));
+ EXPECT_FALSE(multiend_call.valid());
+}
+
+TEST_F(ConversationalSpeechTest,
+ MultiEndCallSetupDifferentSampleRatesAndMultipleNumChannels) {
+ const std::vector<Turn> timing = {
+ {"A", "sr8000", 0},
+ {"B", "sr16000_stereo", 0},
+ };
+ auto mock_wavreader_factory = CreateMockWavReaderFactory();
+
+ // There are two unique audio tracks to read.
+ EXPECT_CALL(*mock_wavreader_factory, Create(testing::_)).Times(2);
+
+ MultiEndCall multiend_call(
+ timing, audiotracks_path, std::move(mock_wavreader_factory));
+ EXPECT_FALSE(multiend_call.valid());
+}
+
TEST_F(ConversationalSpeechTest, MultiEndCallSetupFirstOffsetNegative) {
const std::vector<Turn> timing = {
{"A", "t500", -100},
@@ -525,20 +628,70 @@ TEST_F(ConversationalSpeechTest, MultiEndCallWavReaderAdaptorSine) {
const std::size_t num_samples = duration_seconds * sample_rate;
MockWavReaderFactory::Params params = {sample_rate, 1u, num_samples};
CreateSineWavFile(temp_filename.pathname(), params);
- LOG(LS_VERBOSE) << "wav file @" << sample_rate << " Hz created ("
- << num_samples << " samples)";
// Load wav file and check if params match.
WavReaderFactory wav_reader_factory;
- auto wav_reader = wav_reader_factory.Create(temp_filename.pathname());
- EXPECT_EQ(sample_rate, wav_reader->SampleRate());
- EXPECT_EQ(1u, wav_reader->NumChannels());
- EXPECT_EQ(num_samples, wav_reader->NumSamples());
+ MockWavReaderFactory::Params expeted_params = {
+ sample_rate, 1u, num_samples};
+ CheckAudioTrackParams(
+ wav_reader_factory, temp_filename.pathname(), expeted_params);
// Clean up.
remove(temp_filename.pathname().c_str());
}
}
+TEST_F(ConversationalSpeechTest, MultiEndCallSimulator) {
+ // Simulated call (one character corresponding to 500 ms):
+ // A 0*********...........2*********.....
+ // B ...........1*********.....3*********
+ const std::vector<Turn> expected_timing = {
+ {"A", "t5000_440.wav", 0},
+ {"B", "t5000_880.wav", 500},
+ {"A", "t5000_440.wav", 0},
+ {"B", "t5000_880.wav", -2500},
+ };
+ const std::size_t expected_duration_seconds = 18;
+
+ // Create temporary audio track files.
+ const int sample_rate = 16000;
+ const std::map<std::string, SineAudioTrackParams> sine_tracks_params = {
+ {"t5000_440.wav", {{sample_rate, 1u, sample_rate * 5}, 440.0}},
+ {"t5000_880.wav", {{sample_rate, 1u, sample_rate * 5}, 880.0}},
+ };
+ const std::string audiotracks_path = CreateTemporarySineAudioTracks(
+ sine_tracks_params);
+
+ // Set up the multi-end call.
+ auto wavreader_factory = std::unique_ptr<WavReaderFactory>(
+ new WavReaderFactory());
+ MultiEndCall multiend_call(
+ expected_timing, audiotracks_path, std::move(wavreader_factory));
+
+ // Simulate the call.
+ rtc::Pathname output_path(audiotracks_path);
+ output_path.AppendFolder("output");
+ CreateDir(output_path.pathname());
+ LOG(LS_VERBOSE) << "simulator output path: " << output_path.pathname();
+ auto generated_audiotrak_pairs = conversational_speech::Simulate(
+ multiend_call, output_path.pathname());
+ EXPECT_EQ(2u, generated_audiotrak_pairs->size());
+
+ // Check the output.
+ WavReaderFactory wav_reader_factory;
+ const MockWavReaderFactory::Params expeted_params = {
+ sample_rate, 1u, sample_rate * expected_duration_seconds};
+ for (const auto& it : *generated_audiotrak_pairs) {
+ LOG(LS_VERBOSE) << "checking far/near-end for <" << it.first << ">";
+ CheckAudioTrackParams(
+ wav_reader_factory, it.second.near_end, expeted_params);
+ CheckAudioTrackParams(
+ wav_reader_factory, it.second.far_end, expeted_params);
+ }
+
+ // Clean.
+ EXPECT_NO_FATAL_FAILURE(DeleteFolderAndContents(audiotracks_path));
+}
+
} // namespace test
} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698