audiobuffersource-testing.js (3310B)
1 function createTestBuffer(context, sampleFrameLength) { 2 let audioBuffer = 3 context.createBuffer(1, sampleFrameLength, context.sampleRate); 4 let channelData = audioBuffer.getChannelData(0); 5 6 // Create a simple linear ramp starting at zero, with each value in the buffer 7 // equal to its index position. 8 for (let i = 0; i < sampleFrameLength; ++i) 9 channelData[i] = i; 10 11 return audioBuffer; 12 } 13 14 function checkSingleTest(renderedBuffer, i, should) { 15 let renderedData = renderedBuffer.getChannelData(0); 16 let offsetFrame = i * testSpacingFrames; 17 18 let test = tests[i]; 19 let expected = test.expected; 20 let description; 21 22 if (test.description) { 23 description = test.description; 24 } else { 25 // No description given, so create a basic one from the given test 26 // parameters. 27 description = 28 'loop from ' + test.loopStartFrame + ' -> ' + test.loopEndFrame; 29 if (test.offsetFrame) 30 description += ' with offset ' + test.offsetFrame; 31 if (test.playbackRate && test.playbackRate != 1) 32 description += ' with playbackRate of ' + test.playbackRate; 33 } 34 35 let framesToTest; 36 37 if (test.renderFrames) 38 framesToTest = test.renderFrames; 39 else if (test.durationFrames) 40 framesToTest = test.durationFrames; 41 42 // Verify that the output matches 43 let prefix = 'Case ' + i + ': '; 44 should( 45 renderedData.slice(offsetFrame, offsetFrame + framesToTest), 46 prefix + description) 47 .beEqualToArray(expected); 48 49 // Verify that we get all zeroes after the buffer (or duration) has passed. 50 should( 51 renderedData.slice( 52 offsetFrame + framesToTest, offsetFrame + testSpacingFrames), 53 prefix + description + ': tail') 54 .beConstantValueOf(0); 55 } 56 57 function checkAllTests(renderedBuffer, should) { 58 for (let i = 0; i < tests.length; ++i) 59 checkSingleTest(renderedBuffer, i, should); 60 } 61 62 63 // Create the actual result by modulating playbackRate or detune AudioParam of 64 // ABSN. |modTarget| is a string of AudioParam name, |modOffset| is the offset 65 // (anchor) point of modulation, and |modRange| is the range of modulation. 66 // 67 // createSawtoothWithModulation(context, 'detune', 440, 1200); 68 // 69 // The above will perform a modulation on detune within the range of 70 // [1200, -1200] around the sawtooth waveform on 440Hz. 71 function createSawtoothWithModulation(context, modTarget, modOffset, modRange) { 72 let lfo = context.createOscillator(); 73 let amp = context.createGain(); 74 75 // Create a sawtooth generator with the signal range of [0, 1]. 76 let phasor = context.createBufferSource(); 77 let phasorBuffer = context.createBuffer(1, sampleRate, sampleRate); 78 let phasorArray = phasorBuffer.getChannelData(0); 79 let phase = 0, phaseStep = 1 / sampleRate; 80 for (let i = 0; i < phasorArray.length; i++) { 81 phasorArray[i] = phase % 1.0; 82 phase += phaseStep; 83 } 84 phasor.buffer = phasorBuffer; 85 phasor.loop = true; 86 87 // 1Hz for audible (human-perceivable) parameter modulation by LFO. 88 lfo.frequency.value = 1.0; 89 90 amp.gain.value = modRange; 91 phasor.playbackRate.value = modOffset; 92 93 // The oscillator output should be amplified accordingly to drive the 94 // modulation within the desired range. 95 lfo.connect(amp); 96 amp.connect(phasor[modTarget]); 97 98 phasor.connect(context.destination); 99 100 lfo.start(); 101 phasor.start(); 102 }