减速/延迟频率显示

时间:2016-10-06 03:51:06

标签: javascript php fft web-audio frequency-analysis



window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioContext = null;
var isPlaying = false;
var sourceNode = null;
var analyser = null;
var theBuffer = null;
var DEBUGCANVAS = null;
var mediaStreamSource = null;
var detectorElem, 
	pitchElem ;
var testdelay = null;

window.onload = function() {
	audioContext = new AudioContext();
	
	//test delay
	//testdelay = audioContext.createDelay(5.0);
	//testdelay.delayTime.value = 3.0;
	
	MAX_SIZE = Math.max(4,Math.floor(audioContext.sampleRate/5000));	// corresponds to a 5kHz signal
	var request = new XMLHttpRequest();
	request.open("GET", "../sounds/whistling3.ogg", true);
	request.responseType = "arraybuffer";
	request.onload = function() {
	  audioContext.decodeAudioData( request.response, function(buffer) { 
	    	theBuffer = buffer;
		} );
	}
	request.send();

	detectorElem = document.getElementById( "detector" );
	pitchElem = document.getElementById( "pitch" );


	detectorElem.ondragenter = function () { 
		this.classList.add("droptarget"); 
		return false; };
	detectorElem.ondragleave = function () { this.classList.remove("droptarget"); return false; };
	detectorElem.ondrop = function (e) {
  		this.classList.remove("droptarget");
  		e.preventDefault();
		theBuffer = null;

	  	var reader = new FileReader();
	  	reader.onload = function (event) {
	  		audioContext.decodeAudioData( event.target.result, function(buffer) {
	    		theBuffer = buffer;
	  		}, function(){alert("error loading!");} ); 

	  	};
	  	reader.onerror = function (event) {
	  		alert("Error: " + reader.error );
		};
	  	reader.readAsArrayBuffer(e.dataTransfer.files[0]);
	  	return false;
	};
}

function error() {
    alert('Stream generation failed.');
}

function getUserMedia(dictionary, callback) {
    try {
        navigator.getUserMedia = 
        	navigator.getUserMedia ||
        	navigator.webkitGetUserMedia ||
        	navigator.mozGetUserMedia;
        navigator.getUserMedia(dictionary, callback, error);
    } catch (e) {
        alert('getUserMedia threw exception :' + e);
    }
}

function gotStream(stream) {
    // Create an AudioNode from the stream.
    mediaStreamSource = audioContext.createMediaStreamSource(stream);
	
    // Connect it to the destination.
    analyser = audioContext.createAnalyser();

	//test delay
	//testdelay = audioContext.createDelay(5.0);
	//testdelay.delayTime.value = 3.0;
	
	
	//analyser.smoothingTimeConstant = 0.8;
	
    analyser.fftSize = 8192;
    mediaStreamSource.connect( analyser );
	
    updatePitch();
}

function toggleLiveInput() {
    if (isPlaying) {
        //stop playing and return
        sourceNode.stop( 0 );
        sourceNode = null;
        analyser = null;
        isPlaying = false;
		if (!window.cancelAnimationFrame)
			window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
        window.cancelAnimationFrame( rafID );
    }
    getUserMedia(
    	{
            "audio": {
                "mandatory": {
                    "googEchoCancellation": "false",
                    "googAutoGainControl": "false",
                    "googNoiseSuppression": "false",
                    "googHighpassFilter": "false"
                },
                "optional": []
            },
        }, gotStream);
}


var buf = new Float32Array( 1024 );


var MIN_SAMPLES = 0;  // will be initialized when AudioContext is created.

function autoCorrelate( buf, sampleRate ) {
	var SIZE = buf.length;
	var MAX_SAMPLES = Math.floor(SIZE/2);
	var best_offset = -1;
	var best_correlation = 0;
	var rms = 0;
	var foundGoodCorrelation = false;
	var correlations = new Array(MAX_SAMPLES);

	for (var i=0;i<SIZE;i++) {
		var val = buf[i];
		rms += val*val;
	}
	
	rms = Math.sqrt(rms/SIZE);
	if (rms<0.01) // not enough signal
		return -1;

	
	var lastCorrelation=1;
	for (var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
		var correlation = 0;

		for (var i=0; i<MAX_SAMPLES; i++) {
			correlation += Math.abs((buf[i])-(buf[i+offset]));
		}
		
		correlation = 1 - (correlation/MAX_SAMPLES);
		
		// store it, for the tweaking we need to do below.
		correlations[offset] = correlation; 
		
		if ((correlation>0.9) && (correlation > lastCorrelation)) {
			foundGoodCorrelation = true;
			if (correlation > best_correlation) {
				best_correlation = correlation;
				best_offset = offset;
			}
		} else if (foundGoodCorrelation) {
			var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];  
			return sampleRate/(best_offset+(8*shift));
		}
		
		lastCorrelation = correlation;
	}
	if (best_correlation > 0.01) {
		// console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")")
		return sampleRate/best_offset;
	}
	return -1;
//	var best_frequency = sampleRate/best_offset;
}


//Fungsi untuk melakukan Update/perubahan data frequensi
function updatePitch( time ) {
	var cycles = new Array;
	analyser.getFloatTimeDomainData( buf );
	analyser.smoothingTimeConstant = 0.8;
	var ac = autoCorrelate( buf, audioContext.sampleRate );
	
	//menampilkan data pada form
	//jika tidak ditemukanya gelombang maka data akan kosong, dan warna tampilan akan abu2
 	if (ac == -1) {
 		detectorElem.className = "vague";
	 	pitchElem.innerText = "";

	//jika ditemukanya gelombang maka data akan kosong, dan warna tampilan akan hitam dan data akan ditampilkan
 	} else {
	 	detectorElem.className = "confident";
	 	pitch = ac;
		
		//menampilkan data "pitch" (--Hz) pada halaman Web
	 	pitchElem.innerText = Math.round( pitch ) ;
	}

	if (!window.requestAnimationFrame)
		window.requestAnimationFrame = window.webkitRequestAnimationFrame;
	rafID = window.requestAnimationFrame( updatePitch );
}
&#13;
<!doctype html>
<html>
<head>
<title>Pitch Detector</title>
<link href='http://fonts.googleapis.com/css?family=Alike' rel='stylesheet' type='text/css'>
<style>
body { font: 14pt 'Alike', sans-serif;}
#note { font-size: 164px; }
.droptarget { background-color: #348781}
div.confident { color: black; }
div.vague { color: lightgrey; }
#note { display: inline-block; height:180px; text-align: left;}

#detector { width: 300px; height: 300px; border: 4px solid gray; border-radius: 8px; text-align: center; padding-top: 10px;}
#output { width: 300px; height: 42px; }
#flat { display: none; }
#sharp { display: none; }
.flat #flat { display: inline; }
.sharp #sharp { display: inline; }
</style>

</head>
<body>
<script src="js/pitchdetect.js"></script>
 
<!--  <button onclick="this.innerText = togglePlayback()">use demo audio</button> -->
<center>
<button onclick="toggleLiveInput()">use live input</button>

<!--<button onclick="updatePitch(0);">sample</button>-->

<div id="detector" class="vague">
	<div class="pitch"><span id="pitch">--</span>Hz</div>
	<div class="note"><span id="note">--</span></div>   
	<canvas id="output" width=300 height=42></canvas>
	<div id="detune"><span id="detune_amt">--</span><span id="flat">cents &#9837;</span><span id="sharp">cents &#9839;</span></div>
</div>


<!-- just used for debugging
<canvas id="waveform" width="512" height="256"></canvas>
-->

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-35593052-1']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>
</center>
</body>
</html>
&#13;
&#13;
&#13;

有没有人有使用麦克风在网上制作实时频率计(php,javascript)的经验?

我有一个制作在线实时频率计的项目。显示频率编号,以便我们记录产品是否良好。 但频率数字运行得太快..

任何人都可以帮助我,如何跳过一些updatePicht()或某种方式来延迟显示,以便更容易看? 或平滑价值的方式......

1 个答案:

答案 0 :(得分:0)

我认为你基本上必须平滑你自己从updatePitch()获得的频率估计。要么不那么频繁地调用updatePitch,这可能不是你想要的,也不是对updatePitch返回的值进行某种运行平均。