Home | History | Annotate | Download | only in audio_processing
      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 // MSVC++ requires this to be set before any other includes to get M_PI.
     12 #define _USE_MATH_DEFINES
     13 
     14 #include <cmath>
     15 
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "webrtc/common_audio/channel_buffer.h"
     18 #include "webrtc/modules/audio_processing/splitting_filter.h"
     19 
     20 namespace webrtc {
     21 namespace {
     22 
     23 const size_t kSamplesPer16kHzChannel = 160;
     24 const size_t kSamplesPer48kHzChannel = 480;
     25 
     26 }  // namespace
     27 
     28 // Generates a signal from presence or absence of sine waves of different
     29 // frequencies.
     30 // Splits into 3 bands and checks their presence or absence.
     31 // Recombines the bands.
     32 // Calculates the delay.
     33 // Checks that the cross correlation of input and output is high enough at the
     34 // calculated delay.
     35 TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) {
     36   static const int kChannels = 1;
     37   static const int kSampleRateHz = 48000;
     38   static const size_t kNumBands = 3;
     39   static const int kFrequenciesHz[kNumBands] = {1000, 12000, 18000};
     40   static const float kAmplitude = 8192.f;
     41   static const size_t kChunks = 8;
     42   SplittingFilter splitting_filter(kChannels,
     43                                    kNumBands,
     44                                    kSamplesPer48kHzChannel);
     45   IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels, kNumBands);
     46   IFChannelBuffer bands(kSamplesPer48kHzChannel, kChannels, kNumBands);
     47   IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels, kNumBands);
     48   for (size_t i = 0; i < kChunks; ++i) {
     49     // Input signal generation.
     50     bool is_present[kNumBands];
     51     memset(in_data.fbuf()->channels()[0],
     52            0,
     53            kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channels()[0][0]));
     54     for (size_t j = 0; j < kNumBands; ++j) {
     55       is_present[j] = i & (static_cast<size_t>(1) << j);
     56       float amplitude = is_present[j] ? kAmplitude : 0.f;
     57       for (size_t k = 0; k < kSamplesPer48kHzChannel; ++k) {
     58         in_data.fbuf()->channels()[0][k] +=
     59             amplitude * sin(2.f * M_PI * kFrequenciesHz[j] *
     60                 (i * kSamplesPer48kHzChannel + k) / kSampleRateHz);
     61       }
     62     }
     63     // Three band splitting filter.
     64     splitting_filter.Analysis(&in_data, &bands);
     65     // Energy calculation.
     66     float energy[kNumBands];
     67     for (size_t j = 0; j < kNumBands; ++j) {
     68       energy[j] = 0.f;
     69       for (size_t k = 0; k < kSamplesPer16kHzChannel; ++k) {
     70         energy[j] += bands.fbuf_const()->channels(j)[0][k] *
     71                      bands.fbuf_const()->channels(j)[0][k];
     72       }
     73       energy[j] /= kSamplesPer16kHzChannel;
     74       if (is_present[j]) {
     75         EXPECT_GT(energy[j], kAmplitude * kAmplitude / 4);
     76       } else {
     77         EXPECT_LT(energy[j], kAmplitude * kAmplitude / 4);
     78       }
     79     }
     80     // Three band merge.
     81     splitting_filter.Synthesis(&bands, &out_data);
     82     // Delay and cross correlation estimation.
     83     float xcorr = 0.f;
     84     for (size_t delay = 0; delay < kSamplesPer48kHzChannel; ++delay) {
     85       float tmpcorr = 0.f;
     86       for (size_t j = delay; j < kSamplesPer48kHzChannel; ++j) {
     87         tmpcorr += in_data.fbuf_const()->channels()[0][j - delay] *
     88                    out_data.fbuf_const()->channels()[0][j];
     89       }
     90       tmpcorr /= kSamplesPer48kHzChannel;
     91       if (tmpcorr > xcorr) {
     92         xcorr = tmpcorr;
     93       }
     94     }
     95     // High cross correlation check.
     96     bool any_present = false;
     97     for (size_t j = 0; j < kNumBands; ++j) {
     98       any_present |= is_present[j];
     99     }
    100     if (any_present) {
    101       EXPECT_GT(xcorr, kAmplitude * kAmplitude / 4);
    102     }
    103   }
    104 }
    105 
    106 }  // namespace webrtc
    107