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