102 lines
2.7 KiB
HTML
102 lines
2.7 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<!--
|
|
Tests that AudioBufferSourceNode can playback at different rates properly.
|
|
Render 72 notes over a 6 octave range.
|
|
-->
|
|
|
|
<html>
|
|
<head>
|
|
<script type="text/javascript" src="resources/audio-testing.js"></script>
|
|
<script type="text/javascript" src="resources/buffer-loader.js"></script>
|
|
|
|
</head>
|
|
<body>
|
|
|
|
<script>
|
|
|
|
window.onload = init;
|
|
|
|
var sampleRate = 44100.0;
|
|
var numberOfNotes = 72; // play over a 6 octave range
|
|
var noteDuration = 0.050;
|
|
var noteSpacing = noteDuration + 0.005; // leave 5ms of silence between each "note"
|
|
var lengthInSeconds = numberOfNotes * noteSpacing;
|
|
|
|
var context = 0;
|
|
var sinWaveBuffer = 0;
|
|
|
|
function createOneCycleSinWaveBuffer(frequency, sampleRate) {
|
|
var duration = 1 / frequency;
|
|
var sampleFrameLength = duration * sampleRate;
|
|
|
|
var audioBuffer = context.createBuffer(2, sampleFrameLength, sampleRate);
|
|
|
|
var n = audioBuffer.length;
|
|
var channelL = audioBuffer.getChannelData(0);
|
|
var channelR = audioBuffer.getChannelData(1);
|
|
|
|
for (var i = 0; i < n; ++i) {
|
|
channelL[i] = Math.sin(frequency * 2.0*Math.PI * i / sampleRate);
|
|
channelR[i] = channelL[i];
|
|
}
|
|
|
|
return audioBuffer;
|
|
}
|
|
|
|
function playNote(time, duration, playbackRate) {
|
|
var source = context.createBufferSource();
|
|
source.buffer = sinWaveBuffer;
|
|
source.playbackRate.value = playbackRate;
|
|
|
|
var gainNode = context.createGain();
|
|
source.connect(gainNode);
|
|
gainNode.connect(context.destination);
|
|
|
|
// Loop and play for the given duration.
|
|
source.loop = true;
|
|
source.start(time);
|
|
source.stop(time + duration);
|
|
|
|
// Apply quick fade-in and fade-out to avoid clicks.
|
|
gainNode.gain.value = 0;
|
|
gainNode.gain.setValueAtTime(0, time);
|
|
gainNode.gain.linearRampToValueAtTime(1, time + 0.005);
|
|
gainNode.gain.setValueAtTime(1, time + duration - 0.005);
|
|
gainNode.gain.linearRampToValueAtTime(0, time + duration);
|
|
}
|
|
|
|
function init() {
|
|
if (!window.testRunner)
|
|
return;
|
|
|
|
// Create offline audio context.
|
|
context = new OfflineAudioContext(2, sampleRate * lengthInSeconds, sampleRate);
|
|
|
|
// Create a single cycle of a sine wave.
|
|
// We'll loop this to play notes of a given duration, at a given playback rate.
|
|
sinWaveBuffer = createOneCycleSinWaveBuffer(440.0, sampleRate);
|
|
|
|
// Play 48 notes over a 4 octave range.
|
|
for (var i = 0; i < numberOfNotes; ++i) {
|
|
var time = i * noteSpacing;
|
|
|
|
var semitone = i - numberOfNotes/2; // start three octaves down
|
|
|
|
// Convert from semitone to rate.
|
|
var playbackRate = Math.pow(2, semitone / 12);
|
|
|
|
playNote(time, noteDuration, playbackRate);
|
|
}
|
|
|
|
context.oncomplete = finishAudioTest;
|
|
context.startRendering();
|
|
|
|
testRunner.waitUntilDone();
|
|
}
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|