15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The format of these tests are to enqueue a known amount of data and then
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// request the exact amount we expect in order to dequeue the known amount of
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data.  This ensures that for any rate we are consuming input data at the
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// correct rate.  We always pass in a very large destination buffer with the
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expectation that FillBuffer() will fill as much as it can but no more.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <algorithm>  // For std::min().
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <vector>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "media/base/audio_buffer.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "media/base/audio_bus.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "media/base/buffers.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_layout.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "media/base/test_helpers.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/audio_renderer_algorithm.h"
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "media/filters/wsola_internals.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kFrameSize = 250;
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kSamplesPerSecond = 3000;
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kOutputDurationInSec = 10;
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static void FillWithSquarePulseTrain(
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int half_pulse_width, int offset, int num_samples, float* data) {
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_GE(offset, 0);
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_LE(offset, num_samples);
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Fill backward from |offset| - 1 toward zero, starting with -1, alternating
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // between -1 and 1 every |pulse_width| samples.
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float pulse = -1.0f;
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (int n = offset - 1, k = 0; n >= 0; --n, ++k) {
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (k >= half_pulse_width) {
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pulse = -pulse;
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      k = 0;
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data[n] = pulse;
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Fill forward from |offset| towards the end, starting with 1, alternating
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // between 1 and -1 every |pulse_width| samples.
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pulse = 1.0f;
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (int n = offset, k = 0; n < num_samples; ++n, ++k) {
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (k >= half_pulse_width) {
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pulse = -pulse;
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      k = 0;
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data[n] = pulse;
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static void FillWithSquarePulseTrain(
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int half_pulse_width, int offset, int channel, AudioBus* audio_bus) {
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(half_pulse_width, offset, audio_bus->frames(),
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                           audio_bus->channel(channel));
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioRendererAlgorithmTest : public testing::Test {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererAlgorithmTest()
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      : frames_enqueued_(0),
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        channels_(0),
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        channel_layout_(CHANNEL_LAYOUT_NONE),
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        sample_format_(kUnknownSampleFormat),
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        samples_per_second_(0),
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        bytes_per_sample_(0) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~AudioRendererAlgorithmTest() {}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Initialize() {
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 3000);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void Initialize(ChannelLayout channel_layout,
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  SampleFormat sample_format,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  int samples_per_second) {
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    channels_ = ChannelLayoutToChannelCount(channel_layout);
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    samples_per_second_ = samples_per_second;
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    channel_layout_ = channel_layout;
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    sample_format_ = sample_format;
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bytes_per_sample_ = SampleFormatToBytesPerChannel(sample_format);
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AudioParameters params(media::AudioParameters::AUDIO_PCM_LINEAR,
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           channel_layout,
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           samples_per_second,
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           bytes_per_sample_ * 8,
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           samples_per_second / 100);
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    algorithm_.Initialize(params);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FillAlgorithmQueue();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FillAlgorithmQueue() {
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // The value of the data is meaningless; we just want non-zero data to
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // differentiate it from muted data.
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_refptr<AudioBuffer> buffer;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (!algorithm_.IsQueueFull()) {
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      switch (sample_format_) {
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        case kSampleFormatU8:
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          buffer = MakeAudioBuffer<uint8>(
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              sample_format_,
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              channel_layout_,
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              ChannelLayoutToChannelCount(channel_layout_),
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              samples_per_second_,
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kFrameSize,
116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kNoTimestamp());
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          break;
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        case kSampleFormatS16:
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          buffer = MakeAudioBuffer<int16>(
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              sample_format_,
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              channel_layout_,
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              ChannelLayoutToChannelCount(channel_layout_),
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              samples_per_second_,
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kFrameSize,
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kNoTimestamp());
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          break;
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        case kSampleFormatS32:
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          buffer = MakeAudioBuffer<int32>(
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              sample_format_,
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              channel_layout_,
133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              ChannelLayoutToChannelCount(channel_layout_),
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              samples_per_second_,
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              1,
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kFrameSize,
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              kNoTimestamp());
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          break;
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        default:
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          NOTREACHED() << "Unrecognized format " << sample_format_;
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      algorithm_.EnqueueBuffer(buffer);
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      frames_enqueued_ += kFrameSize;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool AudioDataIsMuted(AudioBus* audio_data, int frames_written) {
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (int ch = 0; ch < channels_; ++ch) {
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      for (int i = 0; i < frames_written; ++i) {
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (audio_data->channel(ch)[i] != 0.0f)
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          return false;
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return true;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int ComputeConsumedFrames(int initial_frames_enqueued,
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                            int initial_frames_buffered) {
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int frame_delta = frames_enqueued_ - initial_frames_enqueued;
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered;
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int consumed = frame_delta - buffered_delta;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(consumed, 0);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return consumed;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestPlaybackRate(double playback_rate) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const int kDefaultBufferSize = algorithm_.samples_per_second() / 100;
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kDefaultFramesRequested = kOutputDurationInSec *
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        algorithm_.samples_per_second();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    TestPlaybackRate(
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        playback_rate, kDefaultBufferSize, kDefaultFramesRequested);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestPlaybackRate(double playback_rate,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int buffer_size_in_frames,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int total_frames_requested) {
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int initial_frames_enqueued = frames_enqueued_;
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int initial_frames_buffered = algorithm_.frames_buffered();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<AudioBus> bus =
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        AudioBus::Create(channels_, buffer_size_in_frames);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (playback_rate == 0.0) {
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      int frames_written = algorithm_.FillBuffer(
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          bus.get(), buffer_size_in_frames, playback_rate);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, frames_written);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool expect_muted = (playback_rate < 0.5 || playback_rate > 4);
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames_remaining = total_frames_requested;
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bool first_fill_buffer = true;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (frames_remaining > 0) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int frames_requested = std::min(buffer_size_in_frames, frames_remaining);
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      int frames_written =
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          algorithm_.FillBuffer(bus.get(), frames_requested, playback_rate);
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ASSERT_GT(frames_written, 0) << "Requested: " << frames_requested
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                   << ", playing at " << playback_rate;
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Do not check data if it is first pull out and only one frame written.
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // The very first frame out of WSOLA is always zero because of
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // overlap-and-add window, which is zero for the first sample. Therefore,
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // if at very first buffer-fill only one frame is written, that is zero
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // which might cause exception in CheckFakeData().
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!first_fill_buffer || frames_written > 1)
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ASSERT_EQ(expect_muted, AudioDataIsMuted(bus.get(), frames_written));
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      first_fill_buffer = false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frames_remaining -= frames_written;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FillAlgorithmQueue();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int frames_consumed =
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ComputeConsumedFrames(initial_frames_enqueued, initial_frames_buffered);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If playing back at normal speed, we should always get back the same
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // number of bytes requested.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (playback_rate == 1.0) {
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      EXPECT_EQ(total_frames_requested, frames_consumed);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise, allow |kMaxAcceptableDelta| difference between the target and
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // actual playback rate.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When |kSamplesPerSecond| and |total_frames_requested| are reasonably
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // large, one can expect less than a 1% difference in most cases. In our
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // current implementation, sped up playback is less accurate than slowed
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // down playback, and for playback_rate > 1, playback rate generally gets
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // less and less accurate the farther it drifts from 1 (though this is
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // nonlinear).
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    double actual_playback_rate =
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        1.0 * frames_consumed / total_frames_requested;
2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  void WsolaTest(float playback_rate) {
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kSampleRateHz = 48000;
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kBytesPerSample = 2;
242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kNumFrames = kSampleRateHz / 100;  // 10 milliseconds.
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    channels_ = ChannelLayoutToChannelCount(kChannelLayout);
245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                           kSampleRateHz, kBytesPerSample * 8, kNumFrames);
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    algorithm_.Initialize(params);
248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // A pulse is 6 milliseconds (even number of samples).
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kPulseWidthSamples = 6 * kSampleRateHz / 1000;
251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kHalfPulseWidthSamples = kPulseWidthSamples / 2;
252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // For the ease of implementation get 1 frame every call to FillBuffer().
254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<AudioBus> output = AudioBus::Create(channels_, 1);
255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
256424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Input buffer to inject pulses.
25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    scoped_refptr<AudioBuffer> input =
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        AudioBuffer::CreateBuffer(kSampleFormatPlanarF32,
25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                  kChannelLayout,
260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  channels_,
26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                  kSampleRateHz,
26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                  kPulseWidthSamples);
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<uint8*>& channel_data = input->channel_data();
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Fill |input| channels.
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FillWithSquarePulseTrain(kHalfPulseWidthSamples, 0, kPulseWidthSamples,
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             reinterpret_cast<float*>(channel_data[0]));
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FillWithSquarePulseTrain(kHalfPulseWidthSamples, kHalfPulseWidthSamples,
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             kPulseWidthSamples,
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             reinterpret_cast<float*>(channel_data[1]));
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // A buffer for the output until a complete pulse is created. Then
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // reference pulse is compared with this buffer.
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_ptr<AudioBus> pulse_buffer = AudioBus::Create(
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        channels_, kPulseWidthSamples);
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const float kTolerance = 0.000001f;
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Equivalent of 4 seconds.
280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const int kNumRequestedPulses = kSampleRateHz * 4 / kPulseWidthSamples;
281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    for (int n = 0; n < kNumRequestedPulses; ++n) {
282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      int num_buffered_frames = 0;
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      while (num_buffered_frames < kPulseWidthSamples) {
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int num_samples = algorithm_.FillBuffer(output.get(), 1, playback_rate);
285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        ASSERT_LE(num_samples, 1);
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (num_samples > 0) {
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          output->CopyPartialFramesTo(0, num_samples, num_buffered_frames,
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      pulse_buffer.get());
289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          num_buffered_frames++;
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        } else {
291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          algorithm_.EnqueueBuffer(input);
292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        }
293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
294424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Pulses in the first half of WSOLA AOL frame are not constructed
296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // perfectly. Do not check them.
297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (n > 3) {
298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)         for (int m = 0; m < channels_; ++m) {
299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          const float* pulse_ch = pulse_buffer->channel(m);
300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          // Because of overlap-and-add we might have round off error.
302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          for (int k = 0; k < kPulseWidthSamples; ++k) {
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ASSERT_NEAR(reinterpret_cast<float*>(channel_data[m])[k],
304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                        pulse_ch[k], kTolerance) << " loop " << n
305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                << " channel/sample " << m << "/" << k;
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          }
307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        }
308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Zero out the buffer to be sure the next comparison is relevant.
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pulse_buffer->Zero();
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioRendererAlgorithm algorithm_;
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int frames_enqueued_;
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int channels_;
31923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ChannelLayout channel_layout_;
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SampleFormat sample_format_;
32123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int samples_per_second_;
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int bytes_per_sample_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalFasterRate) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestPlaybackRate(1.0001);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalSlowerRate) {
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Initialize();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestPlaybackRate(0.9999);
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAQuarterRate) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.25);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAHalfRate) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.5);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_DoubleRate) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(2.0);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_EightTimesRate) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(8.0);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_ThreeQuartersRate) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.75);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_HalfRate) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_QuarterRate) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.25);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_Pause) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.0);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_SlowDown) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(4.5);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(3.0);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(2.0);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.25);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_SpeedUp) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.25);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(2.0);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(3.0);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(4.5);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_JumpAroundSpeeds) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(2.1);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.9);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.6);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.4);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.3);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Initialize();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kBufferSizeInFrames = 1;
412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  static const int kFramesRequested = kOutputDurationInSec * kSamplesPerSecond;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) {
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestPlaybackRate(1.0);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestPlaybackRate(0.5);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestPlaybackRate(1.5);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) {
4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.5);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) {
4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.0);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(0.5);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestPlaybackRate(1.5);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, DotProduct) {
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kChannels = 3;
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kFrames = 20;
442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kHalfPulseWidth = 2;
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<AudioBus> b = AudioBus::Create(kChannels, kFrames);
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<float[]> dot_prod(new float[kChannels]);
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, a.get());
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 1, 1, a.get());
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 2, 2, a.get());
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, b.get());
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 0, 1, b.get());
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FillWithSquarePulseTrain(kHalfPulseWidth, 0, 2, b.get());
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::MultiChannelDotProduct(a.get(), 0, b.get(), 0, kFrames,
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   dot_prod.get());
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(kFrames, dot_prod[0]);
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(0, dot_prod[1]);
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(-kFrames, dot_prod[2]);
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::MultiChannelDotProduct(a.get(), 4, b.get(), 8, kFrames / 2,
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   dot_prod.get());
466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
467424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(kFrames / 2, dot_prod[0]);
468424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(0, dot_prod[1]);
469424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(-kFrames / 2, dot_prod[2]);
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, MovingBlockEnergy) {
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kChannels = 2;
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kFrames = 20;
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kFramesPerBlock = 3;
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kNumBlocks = kFrames - (kFramesPerBlock - 1);
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<float[]> energies(new float[kChannels * kNumBlocks]);
479424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float* ch_left = a->channel(0);
480424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float* ch_right = a->channel(1);
481424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
482424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Fill up both channels.
483424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (int n = 0; n < kFrames; ++n) {
484424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ch_left[n] = n;
485424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ch_right[n] = kFrames - 1 - n;
486424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
487424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::MultiChannelMovingBlockEnergies(a.get(), kFramesPerBlock,
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                            energies.get());
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Check if the energy of candidate blocks of each channel computed correctly.
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (int n = 0; n < kNumBlocks; ++n) {
493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    float expected_energy = 0;
494424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    for (int k = 0; k < kFramesPerBlock; ++k)
495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      expected_energy += ch_left[n + k] * ch_left[n + k];
496424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
497424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Left (first) channel.
498424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_FLOAT_EQ(expected_energy, energies[2 * n]);
499424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
500424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    expected_energy = 0;
501424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    for (int k = 0; k < kFramesPerBlock; ++k)
502424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      expected_energy += ch_right[n + k] * ch_right[n + k];
503424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
504424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Second (right) channel.
505424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_FLOAT_EQ(expected_energy, energies[2 * n + 1]);
506424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
507424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
508424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
509424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, FullAndDecimatedSearch) {
510424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kFramesInSearchRegion = 12;
511424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kChannels = 2;
512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float ch_0[] = {
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f };
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float ch_1[] = {
515424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.1f, 1.0f, 0.1f, 0.0f, 0.0f };
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(sizeof(ch_0), sizeof(ch_1));
517424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(static_cast<size_t>(kFramesInSearchRegion),
518424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            sizeof(ch_0) / sizeof(*ch_0));
519424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<AudioBus> search_region = AudioBus::Create(kChannels,
520424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                        kFramesInSearchRegion);
521424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float* ch = search_region->channel(0);
522424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(ch, ch_0, sizeof(float) * kFramesInSearchRegion);
523424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ch = search_region->channel(1);
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(ch, ch_1, sizeof(float) * kFramesInSearchRegion);
525424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
526424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kFramePerBlock = 4;
527424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float target_0[] = { 1.0f, 1.0f, 1.0f, 0.0f };
528424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float target_1[] = { 0.0f, 1.0f, 0.1f, 1.0f };
529424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(sizeof(target_0), sizeof(target_1));
530424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(static_cast<size_t>(kFramePerBlock),
531424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            sizeof(target_0) / sizeof(*target_0));
532424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
533424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<AudioBus> target = AudioBus::Create(kChannels,
534424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                 kFramePerBlock);
535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ch = target->channel(0);
536424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(ch, target_0, sizeof(float) * kFramePerBlock);
537424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ch = target->channel(1);
538424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(ch, target_1, sizeof(float) * kFramePerBlock);
539424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
540424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<float[]> energy_target(new float[kChannels]);
541424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
542424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::MultiChannelDotProduct(target.get(), 0, target.get(), 0,
543424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   kFramePerBlock, energy_target.get());
544424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
545424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(3.f, energy_target[0]);
546424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(2.01f, energy_target[1]);
547424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
548424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kNumCandidBlocks = kFramesInSearchRegion - (kFramePerBlock - 1);
549424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<float[]> energy_candid_blocks(new float[kNumCandidBlocks *
550424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                     kChannels]);
551424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
552424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::MultiChannelMovingBlockEnergies(
553424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      search_region.get(), kFramePerBlock, energy_candid_blocks.get());
554424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
555424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Check the energy of the candidate blocks of the first channel.
556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[0]);
557424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[2]);
558424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1, energy_candid_blocks[4]);
559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(2, energy_candid_blocks[6]);
560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(3, energy_candid_blocks[8]);
561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(3, energy_candid_blocks[10]);
562424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(2, energy_candid_blocks[12]);
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1, energy_candid_blocks[14]);
564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[16]);
565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Check the energy of the candidate blocks of the second channel.
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[1]);
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[3]);
569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[5]);
570424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0, energy_candid_blocks[7]);
571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(0.01f, energy_candid_blocks[9]);
572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1.01f, energy_candid_blocks[11]);
573424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1.02f, energy_candid_blocks[13]);
574424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1.02f, energy_candid_blocks[15]);
575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_FLOAT_EQ(1.01f, energy_candid_blocks[17]);
576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
577424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // An interval which is of no effect.
578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  internal::Interval exclude_interval = std::make_pair(-100, -10);
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(5, internal::FullSearch(
580424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      0, kNumCandidBlocks - 1, exclude_interval, target.get(),
581424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      search_region.get(), energy_target.get(), energy_candid_blocks.get()));
582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
583424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Exclude the the best match.
584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  exclude_interval = std::make_pair(2, 5);
585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(7, internal::FullSearch(
586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      0, kNumCandidBlocks - 1, exclude_interval, target.get(),
587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      search_region.get(), energy_target.get(), energy_candid_blocks.get()));
588424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // An interval which is of no effect.
590424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  exclude_interval = std::make_pair(-100, -10);
591424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(4, internal::DecimatedSearch(
592424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      4, exclude_interval, target.get(), search_region.get(),
593424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      energy_target.get(), energy_candid_blocks.get()));
594424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
595424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(5, internal::OptimalIndex(search_region.get(), target.get(),
596424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      exclude_interval));
597424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
598424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
599e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochTEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation) {
600424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Arbitrary coefficients.
601424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const float kA = 0.7f;
602424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const float kB = 1.2f;
603424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const float kC = 0.8f;
604424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
605424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float y_values[3];
606424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  y_values[0] = kA - kB + kC;
607424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  y_values[1] = kC;
608424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  y_values[2] = kA + kB + kC;
609424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
610424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float extremum;
611424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float extremum_value;
612424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
613e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  internal::QuadraticInterpolation(y_values, &extremum, &extremum_value);
614424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
615424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float x_star = -kB / (2.f * kA);
616424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  float y_star = kA * x_star * x_star + kB * x_star + kC;
617424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
618424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(x_star, extremum);
619424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_FLOAT_EQ(y_star, extremum_value);
620424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
621424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
622e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochTEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation_Colinear) {
623e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  float y_values[3];
624e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  y_values[0] = 1.0;
625e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  y_values[1] = 1.0;
626e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  y_values[2] = 1.0;
627e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
628e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  float extremum;
629e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  float extremum_value;
630e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
631e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  internal::QuadraticInterpolation(y_values, &extremum, &extremum_value);
632e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
633e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_FLOAT_EQ(extremum, 0.0);
634e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_FLOAT_EQ(extremum_value, 1.0);
635e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
636e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
637424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, WsolaSlowdown) {
638424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  WsolaTest(0.6f);
639424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
640424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
641424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(AudioRendererAlgorithmTest, WsolaSpeedup) {
642424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  WsolaTest(1.6f);
643424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
644424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
646