audio_mixer_test.cc (6101B)
1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "api/audio/audio_mixer.h" 12 13 #include <algorithm> 14 #include <cstring> 15 #include <iostream> 16 #include <memory> 17 #include <string> 18 #include <vector> 19 20 #include "absl/flags/flag.h" 21 #include "absl/flags/parse.h" 22 #include "absl/strings/string_view.h" 23 #include "api/audio/audio_frame.h" 24 #include "api/scoped_refptr.h" 25 #include "common_audio/wav_file.h" 26 #include "modules/audio_mixer/audio_mixer_impl.h" 27 #include "modules/audio_mixer/default_output_rate_calculator.h" 28 #include "modules/audio_mixer/output_rate_calculator.h" 29 #include "rtc_base/checks.h" 30 #include "rtc_base/strings/string_builder.h" 31 32 ABSL_FLAG(int, 33 sampling_rate, 34 16000, 35 "Rate at which to mix (all input streams must have this rate)"); 36 37 ABSL_FLAG(bool, 38 stereo, 39 false, 40 "Enable stereo (interleaved). Inputs need not be as this parameter."); 41 42 ABSL_FLAG(bool, limiter, true, "Enable limiter."); 43 ABSL_FLAG(std::string, 44 output_file, 45 "mixed_file.wav", 46 "File in which to store the mixed result."); 47 ABSL_FLAG(std::string, input_file_1, "", "First input. Default none."); 48 ABSL_FLAG(std::string, input_file_2, "", "Second input. Default none."); 49 ABSL_FLAG(std::string, input_file_3, "", "Third input. Default none."); 50 ABSL_FLAG(std::string, input_file_4, "", "Fourth input. Default none."); 51 52 namespace webrtc { 53 namespace test { 54 55 class FilePlayingSource : public AudioMixer::Source { 56 public: 57 explicit FilePlayingSource(absl::string_view filename) 58 : wav_reader_(new WavReader(filename)), 59 sample_rate_hz_(wav_reader_->sample_rate()), 60 samples_per_channel_(sample_rate_hz_ / 100), 61 number_of_channels_(wav_reader_->num_channels()) {} 62 63 AudioFrameInfo GetAudioFrameWithInfo(int target_rate_hz, 64 AudioFrame* frame) override { 65 frame->samples_per_channel_ = samples_per_channel_; 66 frame->num_channels_ = number_of_channels_; 67 frame->sample_rate_hz_ = target_rate_hz; 68 69 RTC_CHECK_EQ(target_rate_hz, sample_rate_hz_); 70 71 const size_t num_to_read = number_of_channels_ * samples_per_channel_; 72 const size_t num_read = 73 wav_reader_->ReadSamples(num_to_read, frame->mutable_data()); 74 75 file_has_ended_ = num_to_read != num_read; 76 if (file_has_ended_) { 77 frame->Mute(); 78 } 79 return file_has_ended_ ? AudioFrameInfo::kMuted : AudioFrameInfo::kNormal; 80 } 81 82 int Ssrc() const override { return 0; } 83 84 int PreferredSampleRate() const override { return sample_rate_hz_; } 85 86 bool FileHasEnded() const { return file_has_ended_; } 87 88 std::string ToString() const { 89 StringBuilder ss; 90 ss << "{rate: " << sample_rate_hz_ << ", channels: " << number_of_channels_ 91 << ", samples_tot: " << wav_reader_->num_samples() << "}"; 92 return ss.Release(); 93 } 94 95 private: 96 std::unique_ptr<WavReader> wav_reader_; 97 int sample_rate_hz_; 98 int samples_per_channel_; 99 int number_of_channels_; 100 bool file_has_ended_ = false; 101 }; 102 } // namespace test 103 } // namespace webrtc 104 105 namespace { 106 107 const std::vector<std::string> parse_input_files() { 108 std::vector<std::string> result; 109 for (auto& x : 110 {absl::GetFlag(FLAGS_input_file_1), absl::GetFlag(FLAGS_input_file_2), 111 absl::GetFlag(FLAGS_input_file_3), absl::GetFlag(FLAGS_input_file_4)}) { 112 if (!x.empty()) { 113 result.push_back(x); 114 } 115 } 116 return result; 117 } 118 } // namespace 119 120 int main(int argc, char* argv[]) { 121 absl::ParseCommandLine(argc, argv); 122 123 webrtc::scoped_refptr<webrtc::AudioMixerImpl> mixer( 124 webrtc::AudioMixerImpl::Create( 125 std::unique_ptr<webrtc::OutputRateCalculator>( 126 new webrtc::DefaultOutputRateCalculator()), 127 absl::GetFlag(FLAGS_limiter))); 128 129 const std::vector<std::string> input_files = parse_input_files(); 130 std::vector<webrtc::test::FilePlayingSource> sources; 131 const int num_channels = absl::GetFlag(FLAGS_stereo) ? 2 : 1; 132 sources.reserve(input_files.size()); 133 for (const auto& input_file : input_files) { 134 sources.emplace_back(input_file); 135 } 136 137 for (auto& source : sources) { 138 auto error = mixer->AddSource(&source); 139 RTC_CHECK(error); 140 } 141 142 if (sources.empty()) { 143 std::cout << "Need at least one source!\n"; 144 return 1; 145 } 146 147 const size_t sample_rate = sources[0].PreferredSampleRate(); 148 for (const auto& source : sources) { 149 RTC_CHECK_EQ(sample_rate, source.PreferredSampleRate()); 150 } 151 152 // Print stats. 153 std::cout << "Limiting is: " << (absl::GetFlag(FLAGS_limiter) ? "on" : "off") 154 << "\n" 155 "Channels: " 156 << num_channels 157 << "\n" 158 "Rate: " 159 << sample_rate 160 << "\n" 161 "Number of input streams: " 162 << input_files.size() << "\n"; 163 for (const auto& source : sources) { 164 std::cout << "\t" << source.ToString() << "\n"; 165 } 166 std::cout << "Now mixing\n...\n"; 167 168 webrtc::WavWriter wav_writer(absl::GetFlag(FLAGS_output_file), sample_rate, 169 num_channels); 170 171 webrtc::AudioFrame frame; 172 173 bool all_streams_finished = false; 174 while (!all_streams_finished) { 175 mixer->Mix(num_channels, &frame); 176 RTC_CHECK_EQ(sample_rate / 100, frame.samples_per_channel_); 177 RTC_CHECK_EQ(sample_rate, frame.sample_rate_hz_); 178 RTC_CHECK_EQ(num_channels, frame.num_channels_); 179 wav_writer.WriteSamples(frame.data(), 180 num_channels * frame.samples_per_channel_); 181 182 all_streams_finished = 183 std::all_of(sources.begin(), sources.end(), 184 [](const webrtc::test::FilePlayingSource& source) { 185 return source.FileHasEnded(); 186 }); 187 } 188 189 std::cout << "Done!\n" << std::endl; 190 }