preserves-pitch.html (4634B)
1 <!DOCTYPE html> 2 <title>Test preservesPitch.</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/resources/testdriver.js"></script> 6 <script src="/resources/testdriver-vendor.js"></script> 7 <script src="pitch-detector.js"></script> 8 <script> 9 10 // Remove when media-elements/historical.html's preservePitch prefix tests are are passing. 11 function getPreservesPitch(audio) { 12 if ("preservesPitch" in HTMLAudioElement.prototype) { 13 return audio.preservesPitch; 14 } 15 if ("webkitPreservesPitch" in HTMLAudioElement.prototype) { 16 return audio.webkitPreservesPitch; 17 } 18 return undefined; 19 } 20 21 // Remove when media-elements/historical.html's preservePitch prefix tests are are passing. 22 function setPreservesPitch(audio, value) { 23 if ("preservesPitch" in HTMLAudioElement.prototype) { 24 audio.preservesPitch = value; 25 } else if ("webkitPreservesPitch" in HTMLAudioElement.prototype) { 26 audio.webkitPreservesPitch = value; 27 } 28 } 29 30 test(function(t) { 31 assert_true("preservesPitch" in HTMLAudioElement.prototype); 32 }, "Test that preservesPitch is present and unprefixed."); 33 34 test(function(t) { 35 let defaultAudio = document.createElement('audio'); 36 assert_true(getPreservesPitch(defaultAudio)); 37 38 setPreservesPitch(defaultAudio, false); 39 assert_false(getPreservesPitch(defaultAudio)); 40 }, "Test that preservesPitch is on by default"); 41 42 43 var audio; 44 45 function addTestCleanups(t, detector) { 46 t.add_cleanup(() => { 47 audio.pause(); 48 audio.currentTime = 0; 49 }); 50 t.add_cleanup(() => detector.cleanup()); 51 } 52 53 function testPreservesPitch(preservesPitch, playbackRate, expectedPitch, description) { 54 promise_test(async t => { 55 let detector = getPitchDetector(audio); 56 addTestCleanups(t, detector); 57 58 audio.playbackRate = playbackRate; 59 setPreservesPitch(audio, preservesPitch); 60 61 function waitUntil(time) { 62 return new Promise((resolve) => { 63 audio.ontimeupdate = () => { 64 if (audio.currentTime >= time) { 65 resolve(); 66 } 67 }; 68 }); 69 } 70 71 // Wait until we have played some audio. Otherwise, the detector 72 // might return a pitch of 0Hz. 73 audio.play(); 74 await waitUntil(0.5); 75 76 var pitch = detector.detect(); 77 78 // 25Hz is larger than the margin we get from 48kHz and 44.1kHz 79 // audio being analyzed by a FFT of size 2048. If we get something 80 // different, there is an error within the test's calculations (or 81 // we might be dealing a larger sample rate). 82 assert_less_than(pitch.margin, 25, 83 "Test error: the margin should be reasonably small.") 84 85 // Allow for a 15% margin of error in the pitch detector, to reduce test 86 // flakiness. Since our tests speed up and slow down by a factor of 2, 87 // this should be plenty of leeway, without causing false negatives. 88 assert_approx_equals(pitch.value, expectedPitch, expectedPitch*0.15, 89 "The actual pitch should be close to the expected pitch."); 90 91 }, description); 92 } 93 94 var REFERENCE_PITCH = 440; 95 96 promise_test(async t => { 97 // Create the audio element only once, in order to lower the chances of 98 // tests timing out. 99 audio = document.createElement('audio'); 100 101 // This file contains 5 seconds of a 440hz sine wave. 102 audio.src = "/media/sine440.mp3"; 103 104 let detector = getPitchDetector(audio); 105 addTestCleanups(t, detector); 106 107 // The first time we run the test, we need to interact with the 108 // AudioContext and Audio element via user gestures. 109 await test_driver.bless("Play audio element", () => { 110 return Promise.all([audio.play(), detector.ensureStart()]); 111 }); 112 }, "Setup Audio element and AudioContext") 113 114 testPreservesPitch(true, 1.0, REFERENCE_PITCH, 115 "The default playbackRate should not affect pitch") 116 117 testPreservesPitch(false, 1.0, REFERENCE_PITCH, 118 "The default playbackRate should not affect pitch, even with preservesPitch=false") 119 120 testPreservesPitch(true, 2.0, REFERENCE_PITCH, 121 "Speed-ups should not change the pitch when preservesPitch=true") 122 123 testPreservesPitch(true, 0.5, REFERENCE_PITCH, 124 "Slow-downs should not change the pitch when preservesPitch=true") 125 126 testPreservesPitch(false, 2.0, REFERENCE_PITCH*2.0, 127 "Speed-ups should change the pitch when preservesPitch=false") 128 129 testPreservesPitch(false, 0.5, REFERENCE_PITCH*0.5, 130 "Slow-downs should change the pitch when preservesPitch=false") 131 132 </script>