summaryrefslogtreecommitdiff
path: root/common_audio/lapped_transform_unittest.cc
diff options
context:
space:
mode:
authorandrew@webrtc.org <andrew@webrtc.org>2014-10-01 17:42:18 +0000
committerandrew@webrtc.org <andrew@webrtc.org>2014-10-01 17:42:18 +0000
commit1bbdf5776970a75ff8c0bf2711723ebccf6cf7bf (patch)
treefdc1e0ad733112875497cfb8f4b1cdc257f5a8a2 /common_audio/lapped_transform_unittest.cc
parentbb0131f601b18a6b83df0ca07a71e535852afc3f (diff)
downloadwebrtc-1bbdf5776970a75ff8c0bf2711723ebccf6cf7bf.tar.gz
Import LappedTransform and friends.
Add code for doing block-based frequency domain processing. Developed and reviewed in isolation. Corresponding export CL: https://chromereviews.googleplex.com/95187013/ R=bercic@google.com, kjellander@webrtc.org, turaj@webrtc.org Review URL: https://webrtc-codereview.appspot.com/31539004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@7359 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'common_audio/lapped_transform_unittest.cc')
-rw-r--r--common_audio/lapped_transform_unittest.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/common_audio/lapped_transform_unittest.cc b/common_audio/lapped_transform_unittest.cc
new file mode 100644
index 00000000..90523822
--- /dev/null
+++ b/common_audio/lapped_transform_unittest.cc
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/common_audio/lapped_transform.h"
+
+#include <cmath>
+#include <cstring>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::complex;
+
+namespace {
+
+class NoopCallback : public webrtc::LappedTransform::Callback {
+ public:
+ NoopCallback() : block_num_(0) {}
+
+ virtual void ProcessAudioBlock(const complex<float>* const* in_block,
+ int in_channels, int frames, int out_channels,
+ complex<float>* const* out_block) {
+ CHECK_EQ(in_channels, out_channels);
+ for (int i = 0; i < out_channels; ++i) {
+ memcpy(out_block[i], in_block[i], sizeof(**in_block) * frames);
+ }
+ ++block_num_;
+ }
+
+ int block_num() {
+ return block_num_;
+ }
+
+ private:
+ int block_num_;
+};
+
+class FftCheckerCallback : public webrtc::LappedTransform::Callback {
+ public:
+ FftCheckerCallback() : block_num_(0) {}
+
+ virtual void ProcessAudioBlock(const complex<float>* const* in_block,
+ int in_channels, int frames, int out_channels,
+ complex<float>* const* out_block) {
+ CHECK_EQ(in_channels, out_channels);
+
+ float full_length = (frames - 1) * 2;
+ ++block_num_;
+
+ if (block_num_ == 1) {
+ for (int i = 0; i < frames; ++i) {
+ ASSERT_NEAR(in_block[0][i].real(), 0.0f, 1e-5f);
+ ASSERT_NEAR(in_block[0][i].imag(), 0.0f, 1e-5f);
+ }
+ } else {
+ ASSERT_NEAR(in_block[0][0].real(), full_length, 1e-5f);
+ ASSERT_NEAR(in_block[0][0].imag(), 0.0f, 1e-5f);
+ for (int i = 1; i < frames; ++i) {
+ ASSERT_NEAR(in_block[0][i].real(), 0.0f, 1e-5f);
+ ASSERT_NEAR(in_block[0][i].imag(), 0.0f, 1e-5f);
+ }
+ }
+ }
+
+ int block_num() {
+ return block_num_;
+ }
+
+ private:
+ int block_num_;
+};
+
+void SetFloatArray(float value, int rows, int cols, float* const* array) {
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < cols; ++j) {
+ array[i][j] = value;
+ }
+ }
+}
+
+} // namespace
+
+namespace webrtc {
+
+TEST(LappedTransformTest, Windowless) {
+ const int kChannels = 3;
+ const int kChunkLength = 512;
+ const int kBlockLength = 64;
+ const int kShiftAmount = 32;
+ NoopCallback noop;
+ LappedTransform trans(kChannels, kChannels, kChunkLength, nullptr,
+ kBlockLength, kShiftAmount, &noop);
+ float in_buffer[kChannels][kChunkLength];
+ float* in_chunk[kChannels];
+ float out_buffer[kChannels][kChunkLength];
+ float* out_chunk[kChannels];
+
+ in_chunk[0] = in_buffer[0];
+ in_chunk[1] = in_buffer[1];
+ in_chunk[2] = in_buffer[2];
+ out_chunk[0] = out_buffer[0];
+ out_chunk[1] = out_buffer[1];
+ out_chunk[2] = out_buffer[2];
+ SetFloatArray(2.0f, kChannels, kChunkLength, in_chunk);
+ SetFloatArray(-1.0f, kChannels, kChunkLength, out_chunk);
+
+ trans.ProcessChunk(in_chunk, out_chunk);
+
+ for (int i = 0; i < kChannels; ++i) {
+ for (int j = 0; j < kChunkLength; ++j) {
+ ASSERT_NEAR(out_chunk[i][j], (j < kBlockLength) ? 0.0f : 2.0f, 1e-5f);
+ }
+ }
+
+ ASSERT_EQ(kChunkLength / kBlockLength, noop.block_num());
+}
+
+TEST(LappedTransformTest, IdentityProcessor) {
+ const int kChunkLength = 512;
+ const int kBlockLength = 64;
+ const int kShiftAmount = 32;
+ NoopCallback noop;
+ float window[kBlockLength];
+ float* window_ptr = window;
+
+ // Identity window for |overlap = block_size / 2|.
+ SetFloatArray(sqrtf(0.5f), 1, kBlockLength, &window_ptr);
+
+ LappedTransform trans(1, 1, kChunkLength, window, kBlockLength, kShiftAmount,
+ &noop);
+ float in_buffer[kChunkLength];
+ float* in_chunk = in_buffer;
+ float out_buffer[kChunkLength];
+ float* out_chunk = out_buffer;
+
+ SetFloatArray(2.0f, 1, kChunkLength, &in_chunk);
+ SetFloatArray(-1.0f, 1, kChunkLength, &out_chunk);
+
+ trans.ProcessChunk(&in_chunk, &out_chunk);
+
+ for (int i = 0; i < kChunkLength; ++i) {
+ ASSERT_NEAR(out_chunk[i], (i < kBlockLength) ? 0.0f : 2.0f, 1e-5f);
+ }
+
+ ASSERT_EQ(kChunkLength / kShiftAmount, noop.block_num());
+}
+
+TEST(LappedTransformTest, Callbacks) {
+ const int kChunkLength = 512;
+ const int kBlockLength = 64;
+ FftCheckerCallback call;
+ LappedTransform trans(1, 1, kChunkLength, nullptr, kBlockLength,
+ kBlockLength, &call);
+ float in_buffer[kChunkLength];
+ float* in_chunk = in_buffer;
+ float out_buffer[kChunkLength];
+ float* out_chunk = out_buffer;
+
+ SetFloatArray(1.0f, 1, kChunkLength, &in_chunk);
+ SetFloatArray(-1.0f, 1, kChunkLength, &out_chunk);
+
+ trans.ProcessChunk(&in_chunk, &out_chunk);
+
+ ASSERT_EQ(kChunkLength / kBlockLength, call.block_num());
+}
+
+} // namespace webrtc
+