chromium/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMECAST_MEDIA_CMA_BACKEND_MIXER_POST_PROCESSORS_POST_PROCESSOR_UNITTEST_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_MIXER_POST_PROCESSORS_POST_PROCESSOR_UNITTEST_H_

#include <string>
#include <vector>

#include "chromecast/media/base/aligned_buffer.h"
#include "chromecast/public/media/audio_post_processor2_shlib.h"
#include "chromecast/public/media/audio_post_processor_shlib.h"
#include "testing/gtest/include/gtest/gtest.h"

// This file contains basic tests for AudioPostProcessors.
// All AudioPostProcessors should run (and pass) the following tests:
//  TestDelay (tests return value from ProcessFrames)
//  TestRingingTime (from GetRingingTimeFrames)
// Additionally, if it is possible to configure the PostProcessor to be a
// passthrough (no-op), then you should also run
//  TestPassthrough (tests data in = data out, accounting for delay).
//
// Usage:
// TEST_P(PostProcessorTest, DelayTest) {
//   std::unique_ptr<AudioPostProcessor> my_post_processor(
//       AudioPostProcessorShlib_Create(my_config, 2));
//   TestDelay(my_post_processor, sample_rate_);
// }
// (Repeat for TestRingingTime, TestPassthrough).
//
// This will run your test with 44100 and 48000 sample rates.
// You can also make your own tests using the provided helper functions.

namespace chromecast {
namespace media {
namespace post_processor_test {

const int kBufSizeFrames = 256;
const int kNumChannels = 2;

AudioPostProcessor2::Config MakeProcessorConfig(int sample_rate_hz);

void TestDelay(AudioPostProcessor2* pp,
               int sample_rate,
               int num_input_channels = 2);
void TestRingingTime(AudioPostProcessor2* pp,
                     int sample_rate,
                     int num_input_channels = 2);

// Requires that num_output_channels == |input_channels|
void TestPassthrough(AudioPostProcessor2* pp,
                     int sample_rate,
                     int num_input_channels = 2);

// Legacy tests for AudioPostProcessor(1).
void TestDelay(AudioPostProcessor* pp, int sample_rate);
void TestRingingTime(AudioPostProcessor* pp, int sample_rate);
void TestPassthrough(AudioPostProcessor* pp, int sample_rate);

// Measure amount of CPU time |pp| takes to run [x] seconds of stereo audio at
// |sample_rate|.
void AudioProcessorBenchmark(AudioPostProcessor2* pp,
                             int sample_rate,
                             int num_input_channels = kNumChannels);
void AudioProcessorBenchmark(AudioPostProcessor* pp, int sample_rate);

// Returns the maximum number of frames a PostProcessor may be asked to handle
// in a single call.
int GetMaximumFrames(int sample_rate);

// Tests that the first |size| elements of |expected| and |actual| are the same.
template <typename T>
void CheckArraysEqual(const T* expected, const T* actual, size_t size);

// Returns a list of indexes at which |expected| and |actual| differ.
template <typename T>
std::vector<int> CompareArray(const T* expected, const T* actual, size_t size);

// Print the first |size| elemenents of |array| to a string.
template <typename T>
std::string ArrayToString(const T* array, size_t size);

// Compute the amplitude of a sinusoid as power * sqrt(2)
// This is more robust that looking for the maximum value.
float SineAmplitude(const float* data, int num_samples);

// Return a vector of |frames| frames of |num_channels| interleaved data.
// |frequency| is in hz.
// Each channel, ch,  will be sin(2 *pi * frequency / sample_rate * (n + ch)).
AlignedBuffer<float> GetSineData(int frames,
                                 float frequency,
                                 int sample_rate,
                                 int num_channels = kNumChannels);

// Returns a vector of interleaved chirp waveforms with |frames| frames and
// number of channels equal to |start_frequencies.size()|.
// |start_frequencies| and |end_frequencies| must be the same size.
// Each channel, ch, will have frequency linearly interpolated from
// |start_frequencies[ch]| to |end_frequencies[ch]|
// Frequencies are normalized to (2 * freq_in_hz / sample_rate); 0 = DC, 1 =
// nyquist.
AlignedBuffer<float> LinearChirp(int frames,
                                 const std::vector<double>& start_frequencies,
                                 const std::vector<double>& end_frequencies);

// Returns a vector of interleaved stereo chirp waveform with |frames| frames
// from |start_frequency_left| to |start_frequency_left| for left channel and
// from |start_frequency_right| to |end_frequency_right| for right channel,
// where |start_frequency_x| and |end_frequency_x| are normalized frequencies
// (2 * freq_in_hz / sample_rate) i.e. 0 - DC, 1 - nyquist.
// Equivalent to LinearChirp(frames,
//                          {start_frequency_left, start_frequency_right},
//                          {end_frequency_left, end_frequency_right})
AlignedBuffer<float> GetStereoChirp(int frames,
                                    float start_frequency_left,
                                    float end_frequency_left,
                                    float start_frequency_right,
                                    float end_frequency_right);

class PostProcessorTest : public ::testing::TestWithParam<int> {
 protected:
  PostProcessorTest();
  ~PostProcessorTest() override;

  int sample_rate_;
};

}  // namespace post_processor_test
}  // namespace media
}  // namespace chromecast

#endif  // CHROMECAST_MEDIA_CMA_BACKEND_MIXER_POST_PROCESSORS_POST_PROCESSOR_UNITTEST_H_