DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (8ec2329bef74)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
/*
 *  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.
 */

// MSVC++ requires this to be set before any other includes to get M_PI.
#define _USE_MATH_DEFINES

#include <cmath>

#include "common_audio/channel_buffer.h"
#include "modules/audio_processing/splitting_filter.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

const size_t kSamplesPer16kHzChannel = 160;
const size_t kSamplesPer48kHzChannel = 480;

}  // namespace

// Generates a signal from presence or absence of sine waves of different
// frequencies.
// Splits into 3 bands and checks their presence or absence.
// Recombines the bands.
// Calculates the delay.
// Checks that the cross correlation of input and output is high enough at the
// calculated delay.
TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) {
  static const int kChannels = 1;
  static const int kSampleRateHz = 48000;
  static const size_t kNumBands = 3;
  static const int kFrequenciesHz[kNumBands] = {1000, 12000, 18000};
  static const float kAmplitude = 8192.f;
  static const size_t kChunks = 8;
  SplittingFilter splitting_filter(kChannels,
                                   kNumBands,
                                   kSamplesPer48kHzChannel);
  IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels, kNumBands);
  IFChannelBuffer bands(kSamplesPer48kHzChannel, kChannels, kNumBands);
  IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels, kNumBands);
  for (size_t i = 0; i < kChunks; ++i) {
    // Input signal generation.
    bool is_present[kNumBands];
    memset(in_data.fbuf()->channels()[0],
           0,
           kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channels()[0][0]));
    for (size_t j = 0; j < kNumBands; ++j) {
      is_present[j] = i & (static_cast<size_t>(1) << j);
      float amplitude = is_present[j] ? kAmplitude : 0.f;
      for (size_t k = 0; k < kSamplesPer48kHzChannel; ++k) {
        in_data.fbuf()->channels()[0][k] +=
            amplitude * sin(2.f * M_PI * kFrequenciesHz[j] *
                (i * kSamplesPer48kHzChannel + k) / kSampleRateHz);
      }
    }
    // Three band splitting filter.
    splitting_filter.Analysis(&in_data, &bands);
    // Energy calculation.
    float energy[kNumBands];
    for (size_t j = 0; j < kNumBands; ++j) {
      energy[j] = 0.f;
      for (size_t k = 0; k < kSamplesPer16kHzChannel; ++k) {
        energy[j] += bands.fbuf_const()->channels(j)[0][k] *
                     bands.fbuf_const()->channels(j)[0][k];
      }
      energy[j] /= kSamplesPer16kHzChannel;
      if (is_present[j]) {
        EXPECT_GT(energy[j], kAmplitude * kAmplitude / 4);
      } else {
        EXPECT_LT(energy[j], kAmplitude * kAmplitude / 4);
      }
    }
    // Three band merge.
    splitting_filter.Synthesis(&bands, &out_data);
    // Delay and cross correlation estimation.
    float xcorr = 0.f;
    for (size_t delay = 0; delay < kSamplesPer48kHzChannel; ++delay) {
      float tmpcorr = 0.f;
      for (size_t j = delay; j < kSamplesPer48kHzChannel; ++j) {
        tmpcorr += in_data.fbuf_const()->channels()[0][j - delay] *
                   out_data.fbuf_const()->channels()[0][j];
      }
      tmpcorr /= kSamplesPer48kHzChannel;
      if (tmpcorr > xcorr) {
        xcorr = tmpcorr;
      }
    }
    // High cross correlation check.
    bool any_present = false;
    for (size_t j = 0; j < kNumBands; ++j) {
      any_present |= is_present[j];
    }
    if (any_present) {
      EXPECT_GT(xcorr, kAmplitude * kAmplitude / 4);
    }
  }
}

}  // namespace webrtc