blob: b0f898a2bdcf42d7a635af7e3044f32eb0e4c913 [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/modules/webaudio/audio_context.h"
#include <memory>
#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/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
namespace blink {
namespace {
class MockWebAudioDeviceForAudioContext : public WebAudioDevice {
public:
explicit MockWebAudioDeviceForAudioContext(double sample_rate,
int frames_per_buffer)
: sample_rate_(sample_rate), frames_per_buffer_(frames_per_buffer) {}
~MockWebAudioDeviceForAudioContext() override = default;
void Start() override {}
void Stop() override {}
double SampleRate() override { return sample_rate_; }
int FramesPerBuffer() override { return frames_per_buffer_; }
private:
double sample_rate_;
int frames_per_buffer_;
};
class AudioContextTestPlatform : 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 {
double buffer_size = 0;
const double interactive_size = AudioHardwareBufferSize();
const double balanced_size = AudioHardwareBufferSize() * 2;
const double playback_size = AudioHardwareBufferSize() * 4;
switch (latency_hint.Category()) {
case WebAudioLatencyHint::kCategoryInteractive:
buffer_size = interactive_size;
break;
case WebAudioLatencyHint::kCategoryBalanced:
buffer_size = balanced_size;
break;
case WebAudioLatencyHint::kCategoryPlayback:
buffer_size = playback_size;
break;
case WebAudioLatencyHint::kCategoryExact:
buffer_size =
clampTo(latency_hint.Seconds() * AudioHardwareSampleRate(),
static_cast<double>(AudioHardwareBufferSize()),
static_cast<double>(playback_size));
break;
default:
NOTREACHED();
break;
}
return std::make_unique<MockWebAudioDeviceForAudioContext>(
AudioHardwareSampleRate(), buffer_size);
}
double AudioHardwareSampleRate() override { return 44100; }
size_t AudioHardwareBufferSize() override { return 128; }
};
} // anonymous namespace
class AudioContextTest : public PageTestBase {
protected:
AudioContextTest() :
platform_(new ScopedTestingPlatformSupport<AudioContextTestPlatform>) {}
~AudioContextTest() override { platform_.reset(); }
void SetUp() override { PageTestBase::SetUp(IntSize()); }
private:
std::unique_ptr<ScopedTestingPlatformSupport<AudioContextTestPlatform>>
platform_;
};
TEST_F(AudioContextTest, AudioContextOptions_WebAudioLatencyHint) {
AudioContextOptions interactive_options;
interactive_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
"interactive"));
AudioContext* interactive_context = AudioContext::Create(
GetDocument(), interactive_options, ASSERT_NO_EXCEPTION);
AudioContextOptions balanced_options;
balanced_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
"balanced"));
AudioContext* balanced_context = AudioContext::Create(
GetDocument(), balanced_options, ASSERT_NO_EXCEPTION);
EXPECT_GT(balanced_context->baseLatency(),
interactive_context->baseLatency());
AudioContextOptions playback_options;
playback_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromAudioContextLatencyCategory(
"playback"));
AudioContext* playback_context = AudioContext::Create(
GetDocument(), playback_options, ASSERT_NO_EXCEPTION);
EXPECT_GT(playback_context->baseLatency(), balanced_context->baseLatency());
AudioContextOptions exact_too_small_options;
exact_too_small_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromDouble(
interactive_context->baseLatency() / 2));
AudioContext* exact_too_small_context = AudioContext::Create(
GetDocument(), exact_too_small_options, ASSERT_NO_EXCEPTION);
EXPECT_EQ(exact_too_small_context->baseLatency(),
interactive_context->baseLatency());
const double exact_latency_sec =
(interactive_context->baseLatency() + playback_context->baseLatency()) /
2;
AudioContextOptions exact_ok_options;
exact_ok_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromDouble(exact_latency_sec));
AudioContext* exact_ok_context = AudioContext::Create(
GetDocument(), exact_ok_options, ASSERT_NO_EXCEPTION);
EXPECT_EQ(exact_ok_context->baseLatency(), exact_latency_sec);
AudioContextOptions exact_too_big_options;
exact_too_big_options.setLatencyHint(
AudioContextLatencyCategoryOrDouble::FromDouble(
playback_context->baseLatency() * 2));
AudioContext* exact_too_big_context = AudioContext::Create(
GetDocument(), exact_too_big_options, ASSERT_NO_EXCEPTION);
EXPECT_EQ(exact_too_big_context->baseLatency(),
playback_context->baseLatency());
}
} // namespace blink