OLD | NEW |
1 // Notes about generated waveforms: | 1 // Notes about generated waveforms: |
2 // | 2 // |
3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges)
? | 3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges)
? |
4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten
t. | 4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten
t. |
5 // Since a digital audio signal must be band-limited based on the nyquist freque
ncy (half the sample-rate) | 5 // Since a digital audio signal must be band-limited based on the nyquist freque
ncy (half the sample-rate) |
6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in
the | 6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in
the |
7 // appearance of the waveform. See Nyquist-Shannon sampling theorem: | 7 // appearance of the waveform. See Nyquist-Shannon sampling theorem: |
8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem | 8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem |
9 // | 9 // |
10 // QUESTION: Why does the very end of the generated signal appear to get slightl
y weaker? | 10 // QUESTION: Why does the very end of the generated signal appear to get slightl
y weaker? |
11 // ANSWER: This is an artifact of the algorithm to avoid aliasing. | 11 // ANSWER: This is an artifact of the algorithm to avoid aliasing. |
12 | 12 |
13 var sampleRate = 44100.0; | 13 var sampleRate = 44100.0; |
14 var nyquist = 0.5 * sampleRate; | 14 var nyquist = 0.5 * sampleRate; |
15 var lengthInSeconds = 4; | 15 var lengthInSeconds = 4; |
16 var lowFrequency = 10; | 16 var lowFrequency = 10; |
17 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s
ure we generate silence there | 17 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s
ure we generate silence there |
18 var context = 0; | 18 var context = 0; |
19 | 19 |
20 function generateExponentialOscillatorSweep(oscillatorType) { | 20 function generateExponentialOscillatorSweep(context, oscillatorType) { |
21 // Create offline audio context. | |
22 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRat
e); | |
23 | |
24 var osc = context.createOscillator(); | 21 var osc = context.createOscillator(); |
25 if (oscillatorType == "custom") { | 22 if (oscillatorType == "custom") { |
26 // Create a simple waveform with three Fourier coefficients. | 23 // Create a simple waveform with three Fourier coefficients. |
27 // Note the first values are expected to be zero (DC for coeffA and Nyqu
ist for coeffB). | 24 // Note the first values are expected to be zero (DC for coeffA and Nyqu
ist for coeffB). |
28 var coeffA = new Float32Array([0, 1, 0.5]); | 25 var coeffA = new Float32Array([0, 1, 0.5]); |
29 var coeffB = new Float32Array([0, 0, 0]); | 26 var coeffB = new Float32Array([0, 0, 0]); |
30 var wave = context.createPeriodicWave(coeffA, coeffB); | 27 var wave = context.createPeriodicWave(coeffA, coeffB); |
31 osc.setPeriodicWave(wave); | 28 osc.setPeriodicWave(wave); |
32 } else { | 29 } else { |
33 osc.type = oscillatorType; | 30 osc.type = oscillatorType; |
34 } | 31 } |
35 | 32 |
36 // Scale by 1/2 to better visualize the waveform and to avoid clipping past
full scale. | 33 // Scale by 1/2 to better visualize the waveform and to avoid clipping past
full scale. |
37 var gainNode = context.createGain(); | 34 var gainNode = context.createGain(); |
38 gainNode.gain.value = 0.5; | 35 gainNode.gain.value = 0.5; |
39 osc.connect(gainNode); | 36 osc.connect(gainNode); |
40 gainNode.connect(context.destination); | 37 gainNode.connect(context.destination); |
41 | 38 |
42 osc.start(0); | 39 osc.start(0); |
43 | 40 |
44 var nyquist = 0.5 * sampleRate; | 41 var nyquist = 0.5 * sampleRate; |
45 osc.frequency.setValueAtTime(10, 0); | 42 osc.frequency.setValueAtTime(10, 0); |
46 osc.frequency.exponentialRampToValueAtTime(highFrequency, lengthInSeconds); | 43 osc.frequency.exponentialRampToValueAtTime(highFrequency, lengthInSeconds); |
47 | |
48 context.oncomplete = finishAudioTest; | |
49 context.startRendering(); | |
50 | |
51 testRunner.waitUntilDone(); | |
52 } | 44 } |
OLD | NEW |