1 /*
2  *  Copyright (c) 2014 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 #ifndef MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_
12 #define MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_
13 
14 #include <math.h>
15 
16 #include <iterator>
17 #include <limits>
18 #include <memory>
19 #include <sstream>  // no-presubmit-check TODO(webrtc:8982)
20 #include <string>
21 #include <vector>
22 
23 #include "common_audio/channel_buffer.h"
24 #include "common_audio/wav_file.h"
25 #include "modules/audio_processing/include/audio_processing.h"
26 #include "rtc_base/constructor_magic.h"
27 
28 namespace webrtc {
29 
30 static const AudioProcessing::Error kNoErr = AudioProcessing::kNoError;
31 #define EXPECT_NOERR(expr) EXPECT_EQ(kNoErr, (expr))
32 
33 class RawFile final {
34  public:
35   explicit RawFile(const std::string& filename);
36   ~RawFile();
37 
38   void WriteSamples(const int16_t* samples, size_t num_samples);
39   void WriteSamples(const float* samples, size_t num_samples);
40 
41  private:
42   FILE* file_handle_;
43 
44   RTC_DISALLOW_COPY_AND_ASSIGN(RawFile);
45 };
46 
47 // Encapsulates samples and metadata for an integer frame.
48 struct Int16FrameData {
49   // Max data size that matches the data size of the AudioFrame class, providing
50   // storage for 8 channels of 96 kHz data.
51   static const int kMaxDataSizeSamples = 7680;
52 
Int16FrameDataInt16FrameData53   Int16FrameData() {
54     sample_rate_hz = 0;
55     num_channels = 0;
56     samples_per_channel = 0;
57     data.fill(0);
58   }
59 
CopyFromInt16FrameData60   void CopyFrom(const Int16FrameData& src) {
61     samples_per_channel = src.samples_per_channel;
62     sample_rate_hz = src.sample_rate_hz;
63     num_channels = src.num_channels;
64 
65     const size_t length = samples_per_channel * num_channels;
66     RTC_CHECK_LE(length, kMaxDataSizeSamples);
67     memcpy(data.data(), src.data.data(), sizeof(int16_t) * length);
68   }
69   std::array<int16_t, kMaxDataSizeSamples> data;
70   int32_t sample_rate_hz;
71   size_t num_channels;
72   size_t samples_per_channel;
73 };
74 
75 // Reads ChannelBuffers from a provided WavReader.
76 class ChannelBufferWavReader final {
77  public:
78   explicit ChannelBufferWavReader(std::unique_ptr<WavReader> file);
79   ~ChannelBufferWavReader();
80 
81   // Reads data from the file according to the |buffer| format. Returns false if
82   // a full buffer can't be read from the file.
83   bool Read(ChannelBuffer<float>* buffer);
84 
85  private:
86   std::unique_ptr<WavReader> file_;
87   std::vector<float> interleaved_;
88 
89   RTC_DISALLOW_COPY_AND_ASSIGN(ChannelBufferWavReader);
90 };
91 
92 // Writes ChannelBuffers to a provided WavWriter.
93 class ChannelBufferWavWriter final {
94  public:
95   explicit ChannelBufferWavWriter(std::unique_ptr<WavWriter> file);
96   ~ChannelBufferWavWriter();
97 
98   void Write(const ChannelBuffer<float>& buffer);
99 
100  private:
101   std::unique_ptr<WavWriter> file_;
102   std::vector<float> interleaved_;
103 
104   RTC_DISALLOW_COPY_AND_ASSIGN(ChannelBufferWavWriter);
105 };
106 
107 // Takes a pointer to a vector. Allows appending the samples of channel buffers
108 // to the given vector, by interleaving the samples and converting them to float
109 // S16.
110 class ChannelBufferVectorWriter final {
111  public:
112   explicit ChannelBufferVectorWriter(std::vector<float>* output);
113   ChannelBufferVectorWriter(const ChannelBufferVectorWriter&) = delete;
114   ChannelBufferVectorWriter& operator=(const ChannelBufferVectorWriter&) =
115       delete;
116   ~ChannelBufferVectorWriter();
117 
118   // Creates an interleaved copy of |buffer|, converts the samples to float S16
119   // and appends the result to output_.
120   void Write(const ChannelBuffer<float>& buffer);
121 
122  private:
123   std::vector<float> interleaved_buffer_;
124   std::vector<float>* output_;
125 };
126 
127 void WriteIntData(const int16_t* data,
128                   size_t length,
129                   WavWriter* wav_file,
130                   RawFile* raw_file);
131 
132 void WriteFloatData(const float* const* data,
133                     size_t samples_per_channel,
134                     size_t num_channels,
135                     WavWriter* wav_file,
136                     RawFile* raw_file);
137 
138 // Exits on failure; do not use in unit tests.
139 FILE* OpenFile(const std::string& filename, const char* mode);
140 
141 size_t SamplesFromRate(int rate);
142 
143 void SetFrameSampleRate(Int16FrameData* frame, int sample_rate_hz);
144 
145 template <typename T>
SetContainerFormat(int sample_rate_hz,size_t num_channels,Int16FrameData * frame,std::unique_ptr<ChannelBuffer<T>> * cb)146 void SetContainerFormat(int sample_rate_hz,
147                         size_t num_channels,
148                         Int16FrameData* frame,
149                         std::unique_ptr<ChannelBuffer<T> >* cb) {
150   SetFrameSampleRate(frame, sample_rate_hz);
151   frame->num_channels = num_channels;
152   cb->reset(new ChannelBuffer<T>(frame->samples_per_channel, num_channels));
153 }
154 
155 AudioProcessing::ChannelLayout LayoutFromChannels(size_t num_channels);
156 
157 template <typename T>
ComputeSNR(const T * ref,const T * test,size_t length,float * variance)158 float ComputeSNR(const T* ref, const T* test, size_t length, float* variance) {
159   float mse = 0;
160   float mean = 0;
161   *variance = 0;
162   for (size_t i = 0; i < length; ++i) {
163     T error = ref[i] - test[i];
164     mse += error * error;
165     *variance += ref[i] * ref[i];
166     mean += ref[i];
167   }
168   mse /= length;
169   *variance /= length;
170   mean /= length;
171   *variance -= mean * mean;
172 
173   float snr = 100;  // We assign 100 dB to the zero-error case.
174   if (mse > 0)
175     snr = 10 * log10(*variance / mse);
176   return snr;
177 }
178 
179 // Returns a vector<T> parsed from whitespace delimited values in to_parse,
180 // or an empty vector if the string could not be parsed.
181 template <typename T>
ParseList(const std::string & to_parse)182 std::vector<T> ParseList(const std::string& to_parse) {
183   std::vector<T> values;
184 
185   std::istringstream str(to_parse);
186   std::copy(
187       std::istream_iterator<T>(str),  // no-presubmit-check TODO(webrtc:8982)
188       std::istream_iterator<T>(),     // no-presubmit-check TODO(webrtc:8982)
189       std::back_inserter(values));
190 
191   return values;
192 }
193 
194 }  // namespace webrtc
195 
196 #endif  // MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_
197