Add WAV and arbitrary geometry support to nlbf test.
This adds functionality from audioproc_float. The geometry parsing code
is now shared from test_utils.h. I removed the "mic_spacing" flag from
audioproc_float because it's a redundancy that I suspect isn't very
useful.
Includes a cleanup of the audio_processing test utils. They're now
packaged in targets, with the protobuf-using ones split out to avoid
requiring users to depend on protobufs.
pcm_utils is no longer needed and removed.
The primary motivation for this CL is that AudioProcessing currently
doesn't support more than two channels and we'd like a way to pass
more channels to the beamformer.
R=aluebs@webrtc.org, mgraczyk@chromium.org
Review URL: https://webrtc-codereview.appspot.com/50899004
Cr-Commit-Position: refs/heads/master@{#9157}
diff --git a/webrtc/modules/audio_processing/test/test_utils.h b/webrtc/modules/audio_processing/test/test_utils.h
index 52274d7..7ad462c 100644
--- a/webrtc/modules/audio_processing/test/test_utils.h
+++ b/webrtc/modules/audio_processing/test/test_utils.h
@@ -8,13 +8,18 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include <math.h>
-#include <limits>
+#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_
+#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_
-#include "webrtc/audio_processing/debug.pb.h"
+#include <math.h>
+#include <iterator>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_audio/channel_buffer.h"
-#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/wav_file.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/interface/module_common_types.h"
@@ -24,84 +29,38 @@
static const AudioProcessing::Error kNoErr = AudioProcessing::kNoError;
#define EXPECT_NOERR(expr) EXPECT_EQ(kNoErr, (expr))
-class RawFile {
+class RawFile final {
public:
- RawFile(const std::string& filename)
- : file_handle_(fopen(filename.c_str(), "wb")) {}
+ explicit RawFile(const std::string& filename);
+ ~RawFile();
- ~RawFile() {
- fclose(file_handle_);
- }
-
- void WriteSamples(const int16_t* samples, size_t num_samples) {
-#ifndef WEBRTC_ARCH_LITTLE_ENDIAN
-#error "Need to convert samples to little-endian when writing to PCM file"
-#endif
- fwrite(samples, sizeof(*samples), num_samples, file_handle_);
- }
-
- void WriteSamples(const float* samples, size_t num_samples) {
- fwrite(samples, sizeof(*samples), num_samples, file_handle_);
- }
+ void WriteSamples(const int16_t* samples, size_t num_samples);
+ void WriteSamples(const float* samples, size_t num_samples);
private:
FILE* file_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(RawFile);
};
-static inline void WriteIntData(const int16_t* data,
- size_t length,
- WavWriter* wav_file,
- RawFile* raw_file) {
- if (wav_file) {
- wav_file->WriteSamples(data, length);
- }
- if (raw_file) {
- raw_file->WriteSamples(data, length);
- }
-}
+void WriteIntData(const int16_t* data,
+ size_t length,
+ WavWriter* wav_file,
+ RawFile* raw_file);
-static inline void WriteFloatData(const float* const* data,
- size_t samples_per_channel,
- int num_channels,
- WavWriter* wav_file,
- RawFile* raw_file) {
- size_t length = num_channels * samples_per_channel;
- rtc::scoped_ptr<float[]> buffer(new float[length]);
- Interleave(data, samples_per_channel, num_channels, buffer.get());
- if (raw_file) {
- raw_file->WriteSamples(buffer.get(), length);
- }
- // TODO(aluebs): Use ScaleToInt16Range() from audio_util
- for (size_t i = 0; i < length; ++i) {
- buffer[i] = buffer[i] > 0 ?
- buffer[i] * std::numeric_limits<int16_t>::max() :
- -buffer[i] * std::numeric_limits<int16_t>::min();
- }
- if (wav_file) {
- wav_file->WriteSamples(buffer.get(), length);
- }
-}
+void WriteFloatData(const float* const* data,
+ int samples_per_channel,
+ int num_channels,
+ WavWriter* wav_file,
+ RawFile* raw_file);
// Exits on failure; do not use in unit tests.
-static inline FILE* OpenFile(const std::string& filename, const char* mode) {
- FILE* file = fopen(filename.c_str(), mode);
- if (!file) {
- printf("Unable to open file %s\n", filename.c_str());
- exit(1);
- }
- return file;
-}
+FILE* OpenFile(const std::string& filename, const char* mode);
-static inline int SamplesFromRate(int rate) {
- return AudioProcessing::kChunkSizeMs * rate / 1000;
-}
+int SamplesFromRate(int rate);
-static inline void SetFrameSampleRate(AudioFrame* frame,
- int sample_rate_hz) {
- frame->sample_rate_hz_ = sample_rate_hz;
- frame->samples_per_channel_ = AudioProcessing::kChunkSizeMs *
- sample_rate_hz / 1000;
-}
+void SetFrameSampleRate(AudioFrame* frame,
+ int sample_rate_hz);
template <typename T>
void SetContainerFormat(int sample_rate_hz,
@@ -113,47 +72,7 @@
cb->reset(new ChannelBuffer<T>(frame->samples_per_channel_, num_channels));
}
-static inline AudioProcessing::ChannelLayout LayoutFromChannels(
- int num_channels) {
- switch (num_channels) {
- case 1:
- return AudioProcessing::kMono;
- case 2:
- return AudioProcessing::kStereo;
- default:
- assert(false);
- return AudioProcessing::kMono;
- }
-}
-
-// Allocates new memory in the scoped_ptr to fit the raw message and returns the
-// number of bytes read.
-static inline size_t ReadMessageBytesFromFile(
- FILE* file,
- rtc::scoped_ptr<uint8_t[]>* bytes) {
- // The "wire format" for the size is little-endian. Assume we're running on
- // a little-endian machine.
- int32_t size = 0;
- if (fread(&size, sizeof(size), 1, file) != 1)
- return 0;
- if (size <= 0)
- return 0;
-
- bytes->reset(new uint8_t[size]);
- return fread(bytes->get(), sizeof((*bytes)[0]), size, file);
-}
-
-// Returns true on success, false on error or end-of-file.
-static inline bool ReadMessageFromFile(FILE* file,
- ::google::protobuf::MessageLite* msg) {
- rtc::scoped_ptr<uint8_t[]> bytes;
- size_t size = ReadMessageBytesFromFile(file, &bytes);
- if (!size)
- return false;
-
- msg->Clear();
- return msg->ParseFromArray(bytes.get(), size);
-}
+AudioProcessing::ChannelLayout LayoutFromChannels(int num_channels);
template <typename T>
float ComputeSNR(const T* ref, const T* test, int length, float* variance) {
@@ -177,4 +96,28 @@
return snr;
}
+// Returns a vector<T> parsed from whitespace delimited values in to_parse,
+// or an empty vector if the string could not be parsed.
+template<typename T>
+std::vector<T> ParseList(const std::string& to_parse) {
+ std::vector<T> values;
+
+ std::istringstream str(to_parse);
+ std::copy(
+ std::istream_iterator<T>(str),
+ std::istream_iterator<T>(),
+ std::back_inserter(values));
+
+ return values;
+}
+
+// Parses the array geometry from the command line.
+//
+// If a vector with size != num_mics is returned, an error has occurred and an
+// appropriate error message has been printed to stdout.
+std::vector<Point> ParseArrayGeometry(const std::string& mic_positions,
+ size_t num_mics);
+
} // namespace webrtc
+
+#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_TEST_UTILS_H_