From ce302b82c919182887784eff6e6aca7716c6c9c1 Mon Sep 17 00:00:00 2001 From: alessiob Date: Wed, 22 Mar 2017 08:23:46 -0700 Subject: [PATCH] Conversational speech tool: timing model with data access. The conversational_speech::Timing class models a list of turns. Each turn, is identified by a speaker, the audiotrack name, and an offset in milliseconds. The unit test checks that an instance of Timing is correctly populated and that save/reload leads to the same data. BUG=webrtc:7218 Review-Url: https://codereview.webrtc.org/2750353002 Cr-Commit-Position: refs/heads/master@{#17346} --- .../test/conversational_speech/BUILD.gn | 6 +- .../generator_unittest.cc | 52 ++++++++++++-- .../test/conversational_speech/timing.cc | 67 +++++++++++++++++++ .../test/conversational_speech/timing.h | 46 +++++++++++++ 4 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 webrtc/modules/audio_processing/test/conversational_speech/timing.cc create mode 100644 webrtc/modules/audio_processing/test/conversational_speech/timing.h diff --git a/webrtc/modules/audio_processing/test/conversational_speech/BUILD.gn b/webrtc/modules/audio_processing/test/conversational_speech/BUILD.gn index d0cb1e7e7e..e85e1e3b1c 100644 --- a/webrtc/modules/audio_processing/test/conversational_speech/BUILD.gn +++ b/webrtc/modules/audio_processing/test/conversational_speech/BUILD.gn @@ -35,8 +35,12 @@ rtc_static_library("lib") { sources = [ "config.cc", "config.h", + "timing.cc", + "timing.h", + ] + deps = [ + "//webrtc/base:rtc_base_approved", ] - deps = [] visibility = [ ":*" ] # Only targets in this file can depend on this. } # lib 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 da923bc448..221ad7c706 100644 --- a/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc +++ b/webrtc/modules/audio_processing/test/conversational_speech/generator_unittest.cc @@ -8,27 +8,71 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include +#include + #include "webrtc/modules/audio_processing/test/conversational_speech/config.h" +#include "webrtc/modules/audio_processing/test/conversational_speech/timing.h" #include "webrtc/test/gtest.h" +#include "webrtc/test/testsupport/fileutils.h" namespace webrtc { namespace test { namespace { +using conversational_speech::LoadTiming; +using conversational_speech::SaveTiming; +using conversational_speech::Turn; + const char* const audiotracks_path = "/path/to/audiotracks"; const char* const timing_filepath = "/path/to/timing_file.txt"; const char* const output_path = "/path/to/output_dir"; +const std::vector expected_timing = { + {"A", "a1", 0}, + {"B", "b1", 0}, + {"A", "a2", 100}, + {"B", "b2", -200}, + {"A", "a3", 0}, + {"A", "a4", 0}, +}; +const std::size_t kNumberOfTurns = expected_timing.size(); + } // namespace TEST(ConversationalSpeechTest, Settings) { - conversational_speech::Config config( + const conversational_speech::Config config( audiotracks_path, timing_filepath, output_path); // Test getters. - EXPECT_EQ(config.audiotracks_path(), audiotracks_path); - EXPECT_EQ(config.timing_filepath(), timing_filepath); - EXPECT_EQ(config.output_path(), output_path); + EXPECT_EQ(audiotracks_path, config.audiotracks_path()); + EXPECT_EQ(timing_filepath, config.timing_filepath()); + EXPECT_EQ(output_path, config.output_path()); +} + +TEST(ConversationalSpeechTest, ExpectedTimingSize) { + // Check the expected timing size. + EXPECT_EQ(kNumberOfTurns, 6u); +} + +TEST(ConversationalSpeechTest, TimingSaveLoad) { + // Save test timing. + const std::string temporary_filepath = webrtc::test::TempFilename( + webrtc::test::OutputPath(), "TempTimingTestFile"); + SaveTiming(temporary_filepath, expected_timing); + + // Create a std::vector instance by loading from file. + std::vector actual_timing = LoadTiming(temporary_filepath); + std::remove(temporary_filepath.c_str()); + + // Check size. + EXPECT_EQ(expected_timing.size(), actual_timing.size()); + + // Check Turn instances. + for (size_t index = 0; index < expected_timing.size(); ++index) { + EXPECT_EQ(expected_timing[index], actual_timing[index]) + << "turn #" << index << " not matching"; + } } } // namespace test diff --git a/webrtc/modules/audio_processing/test/conversational_speech/timing.cc b/webrtc/modules/audio_processing/test/conversational_speech/timing.cc new file mode 100644 index 0000000000..dd2fdc4ca4 --- /dev/null +++ b/webrtc/modules/audio_processing/test/conversational_speech/timing.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/audio_processing/test/conversational_speech/timing.h" + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/stringencode.h" + +namespace webrtc { +namespace test { +namespace conversational_speech { + +bool Turn::operator==(const Turn &b) const { + return b.speaker_name == speaker_name && + b.audiotrack_file_name == audiotrack_file_name && + b.offset == offset; +} + +std::vector LoadTiming(const std::string& timing_filepath) { + // Line parser. + auto parse_line = [](const std::string& line) { + std::vector fields; + rtc::split(line, ' ', &fields); + RTC_CHECK_EQ(fields.size(), 3); + return Turn(fields[0], fields[1], std::atol(fields[2].c_str())); + }; + + // Init. + std::vector timing; + + // Parse lines. + std::string line; + std::ifstream infile(timing_filepath); + while (std::getline(infile, line)) { + if (line.empty()) + continue; + timing.push_back(parse_line(line)); + } + infile.close(); + + return timing; +} + +void SaveTiming(const std::string& timing_filepath, + rtc::ArrayView timing) { + std::ofstream outfile(timing_filepath); + // TODO(alessio): check if file open for writing. + for (const Turn& turn : timing) { + outfile << turn.speaker_name << " " << turn.audiotrack_file_name + << " " << turn.offset << std::endl; + } + outfile.close(); +} + +} // namespace conversational_speech +} // namespace test +} // namespace webrtc diff --git a/webrtc/modules/audio_processing/test/conversational_speech/timing.h b/webrtc/modules/audio_processing/test/conversational_speech/timing.h new file mode 100644 index 0000000000..6498e79588 --- /dev/null +++ b/webrtc/modules/audio_processing/test/conversational_speech/timing.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_CONVERSATIONAL_SPEECH_TIMING_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_CONVERSATIONAL_SPEECH_TIMING_H_ + +#include +#include + +#include "webrtc/base/array_view.h" + +namespace webrtc { +namespace test { +namespace conversational_speech { + +struct Turn{ + Turn(std::string new_speaker_name, std::string new_audiotrack_file_name, + int new_offset) + : speaker_name(new_speaker_name), + audiotrack_file_name(new_audiotrack_file_name), + offset(new_offset) {} + bool operator==(const Turn &b) const; + std::string speaker_name; + std::string audiotrack_file_name; + int offset; +}; + +// Loads a list of turns from a file. +std::vector LoadTiming(const std::string& timing_filepath); + +// Writes a list of turns into a file. +void SaveTiming(const std::string& timing_filepath, + rtc::ArrayView timing); + +} // namespace conversational_speech +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_CONVERSATIONAL_SPEECH_TIMING_H_