test_utils.h (5263B)
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 <array> 15 #include <cmath> 16 #include <cstddef> 17 #include <cstdint> 18 #include <cstdio> 19 #include <memory> 20 #include <vector> 21 22 #include "absl/strings/string_view.h" 23 #include "api/audio/audio_frame.h" 24 #include "api/audio/audio_processing.h" 25 #include "api/audio/audio_view.h" 26 #include "common_audio/channel_buffer.h" 27 #include "common_audio/wav_file.h" 28 29 namespace webrtc { 30 31 static const AudioProcessing::Error kNoErr = AudioProcessing::kNoError; 32 #define EXPECT_NOERR(expr) EXPECT_EQ(AudioProcessing::kNoError, (expr)) 33 34 // Encapsulates samples and metadata for an integer frame. 35 struct Int16FrameData { 36 // Max data size that matches the data size of the AudioFrame class, providing 37 // storage for 8 channels of 96 kHz data. 38 static const int kMaxDataSizeSamples = AudioFrame::kMaxDataSizeSamples; 39 40 Int16FrameData() = default; 41 42 void CopyFrom(const Int16FrameData& src); 43 bool IsEqual(const Int16FrameData& frame) const; 44 void Scale(float f); 45 46 // Sets `samples_per_channel`, `num_channels` and, implicitly, the sample 47 // rate. The sample rate is set to 100x that of samples per channel. I.e. if 48 // samples_per_channel is 320, the sample rate will be set to 32000. 49 void SetProperties(size_t samples_per_channel, size_t num_channels); 50 51 size_t size() const { return view_.size(); } 52 size_t samples_per_channel() const { return view_.samples_per_channel(); } 53 size_t num_channels() const { return view_.num_channels(); } 54 void set_num_channels(size_t num_channels); 55 56 InterleavedView<int16_t> view() { return view_; } 57 InterleavedView<const int16_t> view() const { return view_; } 58 59 void FillData(int16_t value); 60 void FillStereoData(int16_t left, int16_t right); 61 62 // public struct members. 63 std::array<int16_t, kMaxDataSizeSamples> data = {}; 64 int32_t sample_rate_hz = 0; 65 66 private: 67 InterleavedView<int16_t> view_; 68 }; 69 70 // Reads ChannelBuffers from a provided WavReader. 71 class ChannelBufferWavReader final { 72 public: 73 explicit ChannelBufferWavReader(std::unique_ptr<WavReader> file); 74 ~ChannelBufferWavReader(); 75 76 ChannelBufferWavReader(const ChannelBufferWavReader&) = delete; 77 ChannelBufferWavReader& operator=(const ChannelBufferWavReader&) = delete; 78 79 // Reads data from the file according to the `buffer` format. Returns false if 80 // a full buffer can't be read from the file. 81 bool Read(ChannelBuffer<float>* buffer); 82 83 private: 84 std::unique_ptr<WavReader> file_; 85 std::vector<float> interleaved_; 86 }; 87 88 // Writes ChannelBuffers to a provided WavWriter. 89 class ChannelBufferWavWriter final { 90 public: 91 explicit ChannelBufferWavWriter(std::unique_ptr<WavWriter> file); 92 ~ChannelBufferWavWriter(); 93 94 ChannelBufferWavWriter(const ChannelBufferWavWriter&) = delete; 95 ChannelBufferWavWriter& operator=(const ChannelBufferWavWriter&) = delete; 96 97 void Write(const ChannelBuffer<float>& buffer); 98 99 private: 100 std::unique_ptr<WavWriter> file_; 101 std::vector<float> interleaved_; 102 }; 103 104 // Takes a pointer to a vector. Allows appending the samples of channel buffers 105 // to the given vector, by interleaving the samples and converting them to float 106 // S16. 107 class ChannelBufferVectorWriter final { 108 public: 109 explicit ChannelBufferVectorWriter(std::vector<float>* output); 110 ChannelBufferVectorWriter(const ChannelBufferVectorWriter&) = delete; 111 ChannelBufferVectorWriter& operator=(const ChannelBufferVectorWriter&) = 112 delete; 113 ~ChannelBufferVectorWriter(); 114 115 // Creates an interleaved copy of `buffer`, converts the samples to float S16 116 // and appends the result to output_. 117 void Write(const ChannelBuffer<float>& buffer); 118 119 private: 120 std::vector<float> interleaved_buffer_; 121 std::vector<float>* output_; 122 }; 123 124 // Exits on failure; do not use in unit tests. 125 FILE* OpenFile(absl::string_view filename, absl::string_view mode); 126 127 template <typename T> 128 void SetContainerFormat(int sample_rate_hz, 129 size_t num_channels, 130 Int16FrameData* frame, 131 std::unique_ptr<ChannelBuffer<T> >* cb) { 132 frame->SetProperties(sample_rate_hz / 100, num_channels); 133 cb->reset(new ChannelBuffer<T>(frame->samples_per_channel(), num_channels)); 134 } 135 136 template <typename T> 137 float ComputeSNR(const T* ref, const T* test, size_t length, float* variance) { 138 float mse = 0; 139 float mean = 0; 140 *variance = 0; 141 for (size_t i = 0; i < length; ++i) { 142 T error = ref[i] - test[i]; 143 mse += error * error; 144 *variance += ref[i] * ref[i]; 145 mean += ref[i]; 146 } 147 mse /= length; 148 *variance /= length; 149 mean /= length; 150 *variance -= mean * mean; 151 152 float snr = 100; // We assign 100 dB to the zero-error case. 153 if (mse > 0) 154 snr = 10 * log10(*variance / mse); 155 return snr; 156 } 157 158 } // namespace webrtc 159 160 #endif // MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_