blob: 28eecb60dc232d27c6502aa4f4d0290b2399a75e [file] [log] [blame]
if (window.testRunner)
testRunner.overridePreference("WebKitWebAudioEnabled", "1");
function writeString(s, a, offset) {
for (var i = 0; i < s.length; ++i) {
a[offset + i] = s.charCodeAt(i);
}
}
function writeInt16(n, a, offset) {
n = Math.floor(n);
var b1 = n & 255;
var b2 = (n >> 8) & 255;
a[offset + 0] = b1;
a[offset + 1] = b2;
}
function writeInt32(n, a, offset) {
n = Math.floor(n);
var b1 = n & 255;
var b2 = (n >> 8) & 255;
var b3 = (n >> 16) & 255;
var b4 = (n >> 24) & 255;
a[offset + 0] = b1;
a[offset + 1] = b2;
a[offset + 2] = b3;
a[offset + 3] = b4;
}
function writeAudioBuffer(audioBuffer, a, offset) {
var n = audioBuffer.length;
var channels = audioBuffer.numberOfChannels;
for (var i = 0; i < n; ++i) {
for (var k = 0; k < channels; ++k) {
var buffer = audioBuffer.getChannelData(k);
var sample = buffer[i] * 32768.0;
// Clip samples to the limitations of 16-bit.
// If we don't do this then we'll get nasty wrap-around distortion.
if (sample < -32768)
sample = -32768;
if (sample > 32767)
sample = 32767;
writeInt16(sample, a, offset);
offset += 2;
}
}
}
function createWaveFileData(audioBuffer) {
var frameLength = audioBuffer.length;
var numberOfChannels = audioBuffer.numberOfChannels;
var sampleRate = audioBuffer.sampleRate;
var bitsPerSample = 16;
var byteRate = sampleRate * numberOfChannels * bitsPerSample/8;
var blockAlign = numberOfChannels * bitsPerSample/8;
var wavDataByteLength = frameLength * numberOfChannels * 2; // 16-bit audio
var headerByteLength = 44;
var totalLength = headerByteLength + wavDataByteLength;
var waveFileData = new Uint8Array(totalLength);
var subChunk1Size = 16; // for linear PCM
var subChunk2Size = wavDataByteLength;
var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size);
writeString("RIFF", waveFileData, 0);
writeInt32(chunkSize, waveFileData, 4);
writeString("WAVE", waveFileData, 8);
writeString("fmt ", waveFileData, 12);
writeInt32(subChunk1Size, waveFileData, 16); // SubChunk1Size (4)
writeInt16(1, waveFileData, 20); // AudioFormat (2)
writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2)
writeInt32(sampleRate, waveFileData, 24); // SampleRate (4)
writeInt32(byteRate, waveFileData, 28); // ByteRate (4)
writeInt16(blockAlign, waveFileData, 32); // BlockAlign (2)
writeInt32(bitsPerSample, waveFileData, 34); // BitsPerSample (4)
writeString("data", waveFileData, 36);
writeInt32(subChunk2Size, waveFileData, 40); // SubChunk2Size (4)
// Write actual audio data starting at offset 44.
writeAudioBuffer(audioBuffer, waveFileData, 44);
return waveFileData;
}
function createAudioData(audioBuffer) {
return createWaveFileData(audioBuffer);
}
function finishAudioTest(event) {
var audioData = createAudioData(event.renderedBuffer);
testRunner.setAudioResult(audioData);
testRunner.notifyDone();
}
// Create an impulse in a buffer of length sampleFrameLength
function createImpulseBuffer(context, sampleFrameLength) {
var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length;
var dataL = audioBuffer.getChannelData(0);
for (var k = 0; k < n; ++k) {
dataL[k] = 0;
}
dataL[0] = 1;
return audioBuffer;
}
// Create a buffer of the given length with a linear ramp having values 0 <= x < 1.
function createLinearRampBuffer(context, sampleFrameLength) {
var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length;
var dataL = audioBuffer.getChannelData(0);
for (var i = 0; i < n; ++i)
dataL[i] = i / n;
return audioBuffer;
}
// Create a buffer of the given length having a constant value.
function createConstantBuffer(context, sampleFrameLength, constantValue) {
var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length;
var dataL = audioBuffer.getChannelData(0);
for (var i = 0; i < n; ++i)
dataL[i] = constantValue;
return audioBuffer;
}
// Create a stereo impulse in a buffer of length sampleFrameLength
function createStereoImpulseBuffer(context, sampleFrameLength) {
var audioBuffer = context.createBuffer(2, sampleFrameLength, context.sampleRate);
var n = audioBuffer.length;
var dataL = audioBuffer.getChannelData(0);
var dataR = audioBuffer.getChannelData(1);
for (var k = 0; k < n; ++k) {
dataL[k] = 0;
dataR[k] = 0;
}
dataL[0] = 1;
dataR[0] = 1;
return audioBuffer;
}
// Convert time (in seconds) to sample frames.
function timeToSampleFrame(time, sampleRate) {
return Math.floor(0.5 + time * sampleRate);
}
// Compute the number of sample frames consumed by start with
// the specified |grainOffset|, |duration|, and |sampleRate|.
function grainLengthInSampleFrames(grainOffset, duration, sampleRate) {
var startFrame = timeToSampleFrame(grainOffset, sampleRate);
var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate);
return endFrame - startFrame;
}
// True if the number is not an infinity or NaN
function isValidNumber(x) {
return !isNaN(x) && (x != Infinity) && (x != -Infinity);
}
function shouldNotThrowException(func, text) {
var ok = true;
try {
func();
} catch (e) {
ok = false;
}
if (ok) {
testPassed(text + " did not throw an exception.");
} else {
testFailed(text + " did throw an exception.");
}
}
function shouldThrowTypeError(func, text) {
var ok = false;
try {
func();
} catch (e) {
if (e instanceof TypeError) {
ok = true;
}
}
if (ok) {
testPassed(text + " threw TypeError.");
} else {
testFailed(text + " should throw TypeError.");
}
}
function runWithKeyDown(fn)
{
// FIXME: WKTR does not yet support the keyDown() message. Do a mouseDown here
// instead until keyDown support is added.
var eventName = !window.testRunner || eventSender.keyDown ? 'keypress' : 'mousedown'
function thunk() {
document.removeEventListener(eventName, thunk, false);
fn();
}
document.addEventListener(eventName, thunk, false);
if (window.testRunner) {
if (eventSender.keyDown)
eventSender.keyDown(" ", []);
else
eventSender.mouseDown();
}
}