2 testRunner.overridePreference("WebKitWebAudioEnabled", "1");
4 function writeString(s, a, offset) {
5 for (var i = 0; i < s.length; ++i) {
6 a[offset + i] = s.charCodeAt(i);
10 function writeInt16(n, a, offset) {
14 var b2 = (n >> 8) & 255;
20 function writeInt32(n, a, offset) {
23 var b2 = (n >> 8) & 255;
24 var b3 = (n >> 16) & 255;
25 var b4 = (n >> 24) & 255;
33 function writeAudioBuffer(audioBuffer, a, offset) {
34 var n = audioBuffer.length;
35 var channels = audioBuffer.numberOfChannels;
37 for (var i = 0; i < n; ++i) {
38 for (var k = 0; k < channels; ++k) {
39 var buffer = audioBuffer.getChannelData(k);
40 var sample = buffer[i] * 32768.0;
42 // Clip samples to the limitations of 16-bit.
43 // If we don't do this then we'll get nasty wrap-around distortion.
49 writeInt16(sample, a, offset);
55 function createWaveFileData(audioBuffer) {
56 var frameLength = audioBuffer.length;
57 var numberOfChannels = audioBuffer.numberOfChannels;
58 var sampleRate = audioBuffer.sampleRate;
59 var bitsPerSample = 16;
60 var byteRate = sampleRate * numberOfChannels * bitsPerSample/8;
61 var blockAlign = numberOfChannels * bitsPerSample/8;
62 var wavDataByteLength = frameLength * numberOfChannels * 2; // 16-bit audio
63 var headerByteLength = 44;
64 var totalLength = headerByteLength + wavDataByteLength;
66 var waveFileData = new Uint8Array(totalLength);
68 var subChunk1Size = 16; // for linear PCM
69 var subChunk2Size = wavDataByteLength;
70 var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size);
72 writeString("RIFF", waveFileData, 0);
73 writeInt32(chunkSize, waveFileData, 4);
74 writeString("WAVE", waveFileData, 8);
75 writeString("fmt ", waveFileData, 12);
77 writeInt32(subChunk1Size, waveFileData, 16); // SubChunk1Size (4)
78 writeInt16(1, waveFileData, 20); // AudioFormat (2)
79 writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2)
80 writeInt32(sampleRate, waveFileData, 24); // SampleRate (4)
81 writeInt32(byteRate, waveFileData, 28); // ByteRate (4)
82 writeInt16(blockAlign, waveFileData, 32); // BlockAlign (2)
83 writeInt32(bitsPerSample, waveFileData, 34); // BitsPerSample (4)
85 writeString("data", waveFileData, 36);
86 writeInt32(subChunk2Size, waveFileData, 40); // SubChunk2Size (4)
88 // Write actual audio data starting at offset 44.
89 writeAudioBuffer(audioBuffer, waveFileData, 44);
94 function createAudioData(audioBuffer) {
95 return createWaveFileData(audioBuffer);
98 function finishAudioTest(event) {
99 var audioData = createAudioData(event.renderedBuffer);
100 testRunner.setAudioData(audioData);
101 testRunner.notifyDone();
104 // Create an impulse in a buffer of length sampleFrameLength
105 function createImpulseBuffer(context, sampleFrameLength) {
106 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
107 var n = audioBuffer.length;
108 var dataL = audioBuffer.getChannelData(0);
110 for (var k = 0; k < n; ++k) {
118 // Create a buffer of the given length with a linear ramp having values 0 <= x < 1.
119 function createLinearRampBuffer(context, sampleFrameLength) {
120 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
121 var n = audioBuffer.length;
122 var dataL = audioBuffer.getChannelData(0);
124 for (var i = 0; i < n; ++i)
130 // Create a buffer of the given length having a constant value.
131 function createConstantBuffer(context, sampleFrameLength, constantValue) {
132 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
133 var n = audioBuffer.length;
134 var dataL = audioBuffer.getChannelData(0);
136 for (var i = 0; i < n; ++i)
137 dataL[i] = constantValue;
142 // Create a stereo impulse in a buffer of length sampleFrameLength
143 function createStereoImpulseBuffer(context, sampleFrameLength) {
144 var audioBuffer = context.createBuffer(2, sampleFrameLength, context.sampleRate);
145 var n = audioBuffer.length;
146 var dataL = audioBuffer.getChannelData(0);
147 var dataR = audioBuffer.getChannelData(1);
149 for (var k = 0; k < n; ++k) {
159 // Convert time (in seconds) to sample frames.
160 function timeToSampleFrame(time, sampleRate) {
161 return Math.floor(0.5 + time * sampleRate);
164 // Compute the number of sample frames consumed by noteGrainOn with
165 // the specified |grainOffset|, |duration|, and |sampleRate|.
166 function grainLengthInSampleFrames(grainOffset, duration, sampleRate) {
167 var startFrame = timeToSampleFrame(grainOffset, sampleRate);
168 var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate);
170 return endFrame - startFrame;
173 // True if the number is not an infinity or NaN
174 function isValidNumber(x) {
175 return !isNaN(x) && (x != Infinity) && (x != -Infinity);
178 function shouldThrowTypeError(func, text) {
183 if (e instanceof TypeError) {
188 testPassed(text + " threw TypeError.");
190 testFailed(text + " should throw TypeError.");