замедлить/задержки отображения частоты
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,
\t pitchElem ;
var testdelay = null;
window.onload = function() {
\t audioContext = new AudioContext();
\t
\t //test delay
\t //testdelay = audioContext.createDelay(5.0);
\t //testdelay.delayTime.value = 3.0;
\t
\t MAX_SIZE = Math.max(4,Math.floor(audioContext.sampleRate/5000)); \t // corresponds to a 5kHz signal
\t var request = new XMLHttpRequest();
\t request.open("GET", "../sounds/whistling3.ogg", true);
\t request.responseType = "arraybuffer";
\t request.onload = function() {
\t audioContext.decodeAudioData(request.response, function(buffer) {
\t \t theBuffer = buffer;
\t \t });
\t }
\t request.send();
\t detectorElem = document.getElementById("detector");
\t pitchElem = document.getElementById("pitch");
\t detectorElem.ondragenter = function() {
\t \t this.classList.add("droptarget");
\t \t return false; };
\t detectorElem.ondragleave = function() { this.classList.remove("droptarget"); return false; };
\t detectorElem.ondrop = function (e) {
\t \t this.classList.remove("droptarget");
\t \t e.preventDefault();
\t \t theBuffer = null;
\t \t var reader = new FileReader();
\t \t reader.onload = function (event) {
\t \t \t audioContext.decodeAudioData(event.target.result, function(buffer) {
\t \t \t theBuffer = buffer;
\t \t \t }, function(){alert("error loading!");});
\t \t };
\t \t reader.onerror = function (event) {
\t \t \t alert("Error: " + reader.error);
\t \t };
\t \t reader.readAsArrayBuffer(e.dataTransfer.files[0]);
\t \t return false;
\t };
}
function error() {
alert('Stream generation failed.');
}
function getUserMedia(dictionary, callback) {
try {
navigator.getUserMedia =
\t navigator.getUserMedia ||
\t navigator.webkitGetUserMedia ||
\t 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);
\t
// Connect it to the destination.
analyser = audioContext.createAnalyser();
\t //test delay
\t //testdelay = audioContext.createDelay(5.0);
\t //testdelay.delayTime.value = 3.0;
\t
\t
\t //analyser.smoothingTimeConstant = 0.8;
\t
analyser.fftSize = 8192;
mediaStreamSource.connect(analyser);
\t
updatePitch();
}
function toggleLiveInput() {
if (isPlaying) {
//stop playing and return
sourceNode.stop(0);
sourceNode = null;
analyser = null;
isPlaying = false;
\t \t if (!window.cancelAnimationFrame)
\t \t \t window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
window.cancelAnimationFrame(rafID);
}
getUserMedia(
\t {
"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) {
\t var SIZE = buf.length;
\t var MAX_SAMPLES = Math.floor(SIZE/2);
\t var best_offset = -1;
\t var best_correlation = 0;
\t var rms = 0;
\t var foundGoodCorrelation = false;
\t var correlations = new Array(MAX_SAMPLES);
\t for (var i=0;i<SIZE;i++) {
\t \t var val = buf[i];
\t \t rms += val*val;
\t }
\t
\t rms = Math.sqrt(rms/SIZE);
\t if (rms<0.01) // not enough signal
\t \t return -1;
\t
\t var lastCorrelation=1;
\t for (var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
\t \t var correlation = 0;
\t \t for (var i=0; i<MAX_SAMPLES; i++) {
\t \t \t correlation += Math.abs((buf[i])-(buf[i+offset]));
\t \t }
\t \t
\t \t correlation = 1 - (correlation/MAX_SAMPLES);
\t \t
\t \t // store it, for the tweaking we need to do below.
\t \t correlations[offset] = correlation;
\t \t
\t \t if ((correlation>0.9) && (correlation > lastCorrelation)) {
\t \t \t foundGoodCorrelation = true;
\t \t \t if (correlation > best_correlation) {
\t \t \t \t best_correlation = correlation;
\t \t \t \t best_offset = offset;
\t \t \t }
\t \t } else if (foundGoodCorrelation) {
\t \t \t var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
\t \t \t return sampleRate/(best_offset+(8*shift));
\t \t }
\t \t
\t \t lastCorrelation = correlation;
\t }
\t if (best_correlation > 0.01) {
\t \t // console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")")
\t \t return sampleRate/best_offset;
\t }
\t return -1;
// \t var best_frequency = sampleRate/best_offset;
}
//Fungsi untuk melakukan Update/perubahan data frequensi
function updatePitch(time) {
\t var cycles = new Array;
\t analyser.getFloatTimeDomainData(buf);
\t analyser.smoothingTimeConstant = 0.8;
\t var ac = autoCorrelate(buf, audioContext.sampleRate);
\t
\t //menampilkan data pada form
\t //jika tidak ditemukanya gelombang maka data akan kosong, dan warna tampilan akan abu2
\t if (ac == -1) {
\t \t detectorElem.className = "vague";
\t \t pitchElem.innerText = "";
\t //jika ditemukanya gelombang maka data akan kosong, dan warna tampilan akan hitam dan data akan ditampilkan
\t } else {
\t \t detectorElem.className = "confident";
\t \t pitch = ac;
\t \t
\t \t //menampilkan data "pitch" (--Hz) pada halaman Web
\t \t pitchElem.innerText = Math.round(pitch) ;
\t }
\t if (!window.requestAnimationFrame)
\t \t window.requestAnimationFrame = window.webkitRequestAnimationFrame;
\t rafID = window.requestAnimationFrame(updatePitch);
}
<!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">
\t <div class="pitch"><span id="pitch">--</span>Hz</div>
\t <div class="note"><span id="note">--</span></div>
\t <canvas id="output" width=300 height=42></canvas>
\t <div id="detune"><span id="detune_amt">--</span><span id="flat">cents ♭</span><span id="sharp">cents ♯</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>
ли кто-нибудь есть опыт делает живой частотомер на веб (PHP, JavaScript) с помощью микрофона?
У меня есть проект, чтобы сделать онлайн-частотомер. для отображения номера частоты, чтобы мы могли записать, был ли продукт хорошим или нет. , но частотное число работает слишком быстро.
Может ли кто-нибудь мне помочь, как пропустить некоторое обновлениеPicht() или каким-то образом отложить отображение, чтобы упростить просмотр? или способ сглаживания значения ...
Я попробовал, но это не сработало ... Можете ли вы исправить мой код? Или вы можете привести пример для этого? –
Ну, один простой подход. Пусть 'f' будет выводиться из' updatePitch() '. Вместо отображения 'updatePitch()', вычислите 'f = a * updatePitch() + (1-a) * f', где' a' - некоторое небольшое число, возможно, 0.25? Вам придется немного поэкспериментировать, но чем меньше 'a', тем меньше вариаций будет на поле, но вы также не поймаете внезапные изменения высоты тона. –