summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html')
-rw-r--r--testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html132
1 files changed, 132 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html
new file mode 100644
index 0000000000..ba76f51d47
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/media-elements/preserves-pitch.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<title>Test preservesPitch.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="pitch-detector.js"></script>
+<script>
+
+// Remove when media-elements/historical.html's preservePitch prefix tests are are passing.
+function getPreservesPitch(audio) {
+ if ("preservesPitch" in HTMLAudioElement.prototype) {
+ return audio.preservesPitch;
+ }
+ if ("webkitPreservesPitch" in HTMLAudioElement.prototype) {
+ return audio.webkitPreservesPitch;
+ }
+ return undefined;
+}
+
+// Remove when media-elements/historical.html's preservePitch prefix tests are are passing.
+function setPreservesPitch(audio, value) {
+ if ("preservesPitch" in HTMLAudioElement.prototype) {
+ audio.preservesPitch = value;
+ } else if ("webkitPreservesPitch" in HTMLAudioElement.prototype) {
+ audio.webkitPreservesPitch = value;
+ }
+}
+
+test(function(t) {
+ assert_true("preservesPitch" in HTMLAudioElement.prototype);
+}, "Test that preservesPitch is present and unprefixed.");
+
+test(function(t) {
+ let defaultAudio = document.createElement('audio');
+ assert_true(getPreservesPitch(defaultAudio));
+
+ setPreservesPitch(defaultAudio, false);
+ assert_false(getPreservesPitch(defaultAudio));
+}, "Test that preservesPitch is on by default");
+
+
+var audio;
+
+function addTestCleanups(t, detector) {
+ t.add_cleanup(() => {
+ audio.pause();
+ audio.currentTime = 0;
+ });
+ t.add_cleanup(() => detector.cleanup());
+}
+
+function testPreservesPitch(preservesPitch, playbackRate, expectedPitch, description) {
+ promise_test(async t => {
+ let detector = getPitchDetector(audio);
+ addTestCleanups(t, detector);
+
+ audio.playbackRate = playbackRate;
+ setPreservesPitch(audio, preservesPitch);
+
+ function waitUntil(time) {
+ return new Promise((resolve) => {
+ audio.ontimeupdate = () => {
+ if (audio.currentTime >= time) {
+ resolve();
+ }
+ };
+ });
+ }
+
+ // Wait until we have played some audio. Otherwise, the detector
+ // might return a pitch of 0Hz.
+ audio.play();
+ await waitUntil(0.5);
+
+ var pitch = detector.detect();
+
+ // 25Hz is larger than the margin we get from 48kHz and 44.1kHz
+ // audio being analyzed by a FFT of size 2048. If we get something
+ // different, there is an error within the test's calculations (or
+ // we might be dealing a larger sample rate).
+ assert_less_than(pitch.margin, 25,
+ "Test error: the margin should be reasonably small.")
+
+ // Allow for a 15% margin of error in the pitch detector, to reduce test
+ // flakiness. Since our tests speed up and slow down by a factor of 2,
+ // this should be plenty of leeway, without causing false negatives.
+ assert_approx_equals(pitch.value, expectedPitch, expectedPitch*0.15,
+ "The actual pitch should be close to the expected pitch.");
+
+ }, description);
+}
+
+var REFERENCE_PITCH = 440;
+
+promise_test(async t => {
+ // Create the audio element only once, in order to lower the chances of
+ // tests timing out.
+ audio = document.createElement('audio');
+
+ // This file contains 5 seconds of a 440hz sine wave.
+ audio.src = "/media/sine440.mp3";
+
+ let detector = getPitchDetector(audio);
+ addTestCleanups(t, detector);
+
+ // The first time we run the test, we need to interact with the
+ // AudioContext and Audio element via user gestures.
+ await test_driver.bless("Play audio element", () => {
+ return Promise.all([audio.play(), detector.ensureStart()]);
+ });
+}, "Setup Audio element and AudioContext")
+
+testPreservesPitch(true, 1.0, REFERENCE_PITCH,
+ "The default playbackRate should not affect pitch")
+
+testPreservesPitch(false, 1.0, REFERENCE_PITCH,
+ "The default playbackRate should not affect pitch, even with preservesPitch=false")
+
+testPreservesPitch(true, 2.0, REFERENCE_PITCH,
+ "Speed-ups should not change the pitch when preservesPitch=true")
+
+testPreservesPitch(true, 0.5, REFERENCE_PITCH,
+ "Slow-downs should not change the pitch when preservesPitch=true")
+
+testPreservesPitch(false, 2.0, REFERENCE_PITCH*2.0,
+ "Speed-ups should change the pitch when preservesPitch=false")
+
+testPreservesPitch(false, 0.5, REFERENCE_PITCH*0.5,
+ "Slow-downs should change the pitch when preservesPitch=false")
+
+</script>