1 // Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8
9 #include <array>
10 #include <fstream>
11 #include <memory>
12
13 #include "common_audio/vad/include/vad.h"
14 #include "common_audio/wav_file.h"
15 #include "rtc_base/flags.h"
16 #include "rtc_base/logging.h"
17
18 namespace webrtc {
19 namespace test {
20 namespace {
21
22 // The allowed values are 10, 20 or 30 ms.
23 constexpr uint8_t kAudioFrameLengthMilliseconds = 30;
24 constexpr int kMaxSampleRate = 48000;
25 constexpr size_t kMaxFrameLen =
26 kAudioFrameLengthMilliseconds * kMaxSampleRate / 1000;
27
28 constexpr uint8_t kBitmaskBuffSize = 8;
29
30 DEFINE_string(i, "", "Input wav file");
31 DEFINE_string(o, "", "VAD output file");
32
main(int argc,char * argv[])33 int main(int argc, char* argv[]) {
34 if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true))
35 return 1;
36
37 // Open wav input file and check properties.
38 WavReader wav_reader(FLAG_i);
39 if (wav_reader.num_channels() != 1) {
40 RTC_LOG(LS_ERROR) << "Only mono wav files supported";
41 return 1;
42 }
43 if (wav_reader.sample_rate() > kMaxSampleRate) {
44 RTC_LOG(LS_ERROR) << "Beyond maximum sample rate (" << kMaxSampleRate
45 << ")";
46 return 1;
47 }
48 const size_t audio_frame_length = rtc::CheckedDivExact(
49 kAudioFrameLengthMilliseconds * wav_reader.sample_rate(), 1000);
50 if (audio_frame_length > kMaxFrameLen) {
51 RTC_LOG(LS_ERROR) << "The frame size and/or the sample rate are too large.";
52 return 1;
53 }
54
55 // Create output file and write header.
56 std::ofstream out_file(FLAG_o, std::ofstream::binary);
57 const char audio_frame_length_ms = kAudioFrameLengthMilliseconds;
58 out_file.write(&audio_frame_length_ms, 1); // Header.
59
60 // Run VAD and write decisions.
61 std::unique_ptr<Vad> vad = CreateVad(Vad::Aggressiveness::kVadNormal);
62 std::array<int16_t, kMaxFrameLen> samples;
63 char buff = 0; // Buffer to write one bit per frame.
64 uint8_t next = 0; // Points to the next bit to write in |buff|.
65 while (true) {
66 // Process frame.
67 const auto read_samples =
68 wav_reader.ReadSamples(audio_frame_length, samples.data());
69 if (read_samples < audio_frame_length)
70 break;
71 const auto is_speech = vad->VoiceActivity(
72 samples.data(), audio_frame_length, wav_reader.sample_rate());
73
74 // Write output.
75 buff = is_speech ? buff | (1 << next) : buff & ~(1 << next);
76 if (++next == kBitmaskBuffSize) {
77 out_file.write(&buff, 1); // Flush.
78 buff = 0; // Reset.
79 next = 0;
80 }
81 }
82
83 // Finalize.
84 char extra_bits = 0;
85 if (next > 0) {
86 extra_bits = kBitmaskBuffSize - next;
87 out_file.write(&buff, 1); // Flush.
88 }
89 out_file.write(&extra_bits, 1);
90 out_file.close();
91
92 return 0;
93 }
94
95 } // namespace
96 } // namespace test
97 } // namespace webrtc
98
main(int argc,char * argv[])99 int main(int argc, char* argv[]) {
100 return webrtc::test::main(argc, argv);
101 }
102