blob: ffab6ad5144ee35cc2ebf15ef30afc07578711c8 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/audio/audio_destination.h"
#include <memory>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_audio_device.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
#include "third_party/blink/renderer/platform/audio/audio_io_callback.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
namespace blink {
namespace {
class MockWebAudioDevice : public WebAudioDevice {
public:
explicit MockWebAudioDevice(double sample_rate, int frames_per_buffer)
: sample_rate_(sample_rate), frames_per_buffer_(frames_per_buffer) {}
void Start() override {}
void Stop() override {}
void Pause() override {}
void Resume() override {}
double SampleRate() override { return sample_rate_; }
int FramesPerBuffer() override { return frames_per_buffer_; }
private:
double sample_rate_;
int frames_per_buffer_;
};
class TestPlatform : public TestingPlatformSupport {
public:
std::unique_ptr<WebAudioDevice> CreateAudioDevice(
unsigned number_of_input_channels,
unsigned number_of_channels,
const WebAudioLatencyHint& latency_hint,
WebAudioDevice::RenderCallback*,
const WebString& device_id) override {
return std::make_unique<MockWebAudioDevice>(AudioHardwareSampleRate(),
AudioHardwareBufferSize());
}
double AudioHardwareSampleRate() override { return 44100; }
size_t AudioHardwareBufferSize() override { return 512; }
unsigned AudioHardwareOutputChannels() override { return 2; }
};
class AudioCallback : public blink::AudioIOCallback {
public:
void Render(AudioBus* destination_bus,
uint32_t frames_to_process,
const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric) override {
frames_processed_ += frames_to_process;
}
AudioCallback() : frames_processed_(0) {}
int frames_processed_;
};
void CountWASamplesProcessedForRate(base::Optional<float> sample_rate) {
WebAudioLatencyHint latency_hint(WebAudioLatencyHint::kCategoryInteractive);
AudioCallback callback;
const int channel_count = Platform::Current()->AudioHardwareOutputChannels();
const size_t request_frames = Platform::Current()->AudioHardwareBufferSize();
scoped_refptr<AudioDestination> destination = AudioDestination::Create(
callback, channel_count, latency_hint, sample_rate);
std::vector<float> channels[channel_count];
WebVector<float*> dest_data(static_cast<size_t>(channel_count));
for (int i = 0; i < channel_count; ++i) {
channels[i].resize(request_frames);
dest_data[i] = channels[i].data();
}
destination->Render(dest_data, request_frames, 0, 0, 0);
int exact_frames_required =
std::ceil(request_frames * destination->SampleRate() /
Platform::Current()->AudioHardwareSampleRate());
int expected_frames_processed =
std::ceil(exact_frames_required /
static_cast<double>(audio_utilities::kRenderQuantumFrames)) *
audio_utilities::kRenderQuantumFrames;
EXPECT_EQ(expected_frames_processed, callback.frames_processed_);
}
TEST(AudioDestinationTest, ResamplingTest) {
ScopedTestingPlatformSupport<TestPlatform> platform;
CountWASamplesProcessedForRate(base::Optional<float>());
CountWASamplesProcessedForRate(8000);
CountWASamplesProcessedForRate(24000);
CountWASamplesProcessedForRate(44100);
CountWASamplesProcessedForRate(48000);
CountWASamplesProcessedForRate(384000);
}
} // namespace
} // namespace blink