pitch-detector.js (1628B)
1 // This should be removed when the webaudio/historical.html tests are passing. 2 // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=204719 3 window.AudioContext = window.AudioContext || window.webkitAudioContext; 4 5 var FFT_SIZE = 2048; 6 7 var audioContext; 8 var sourceNode; 9 10 function getPitchDetector(media) { 11 if(!audioContext) { 12 audioContext = new AudioContext(); 13 sourceNode = audioContext.createMediaElementSource(media); 14 } 15 16 var analyser = audioContext.createAnalyser(); 17 analyser.fftSize = FFT_SIZE; 18 19 sourceNode.connect(analyser); 20 analyser.connect(audioContext.destination); 21 22 return { 23 ensureStart() { return audioContext.resume(); }, 24 detect() { return getPitch(analyser); }, 25 cleanup() { 26 sourceNode.disconnect(); 27 analyser.disconnect(); 28 }, 29 }; 30 } 31 32 function getPitch(analyser) { 33 // Returns the frequency value for the nth FFT bin. 34 var binConverter = (bin) => 35 (audioContext.sampleRate/2)*((bin)/(analyser.frequencyBinCount-1)); 36 37 var buf = new Uint8Array(analyser.frequencyBinCount); 38 analyser.getByteFrequencyData(buf); 39 return findDominantFrequency(buf, binConverter); 40 } 41 42 // Returns the dominant frequency, +/- a certain margin. 43 function findDominantFrequency(buf, binConverter) { 44 var max = 0; 45 var bin = 0; 46 47 for (var i=0;i<buf.length;i++) { 48 if(buf[i] > max) { 49 max = buf[i]; 50 bin = i; 51 } 52 } 53 54 // The spread of frequencies within bins is constant and corresponds to 55 // (1/(FFT_SIZE-1))th of the sample rate. Use the value of bin #1 as a 56 // shorthand for that value. 57 return { value:binConverter(bin), margin:binConverter(1) }; 58 }