之前最早时候给过一个识别hz的demo 今天讲那个demo结合上一篇说的振荡器,做了个声音登录的小demo
原理就是2w+hz人听不见。(其实1w9左右就很轻微了)
直接上代码
识别器(限电脑)
<span style="font-size:18px;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="full-screen" content="yes"/>
<meta content="telephone=no" name="format-detection" />
<meta name="screen-orientation" content="portrait"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="360-fullscreen" content="true"/>
<title>动态加载</title>
<script src="js/get-float-time-domain-data.min.js"></script>
<style type="text/css">
.center {
margin-right: auto;margin-left: auto;
}
#button {
width: 30%;height: 50px;background-color: cornflowerblue;text-align: center;font-size: 18px;border-radius: 10px;line-height: 50px
}
#canvas {
margin-top: 10px;
}
</style>
</head>
<body style="text-align: center">
<h1>动态加载</h1>
<br>
<h2 id="hz">点击开始</h2>
<div οnclick="buttonClicked()" id="button" class="center">开始</div>
<iframe style="margin-left: auto;margin-right: auto;margin-top: 30px;display: none" frameborder="0" width="640" height="498" src="" allowfullscreen></iframe>
<script type="application/javascript">
var body = document.body,
// canvas = document.getElementById("canvas"),
// ctx = canvas.getContext("2d"),
hz = document.getElementById("hz"),
width = 0,
height = 0,
src = "http://v.qq.com/iframe/player.html?vid=z01978vcjoa&tiny=0&auto=0",
button = document.getElementById("button");
var onRecord = false,//是否在录音
currentHz = 0, //当前频率
historyHz = [];//用来记录历史hz (为了canvas)
//这个是主角 WebAudio
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = null,
sourceNode = null,
analyser = null,
theBuffer = null,
mediaStreamSource = null;
window.onload = function(){
// canvas.width = body.clientWidth*0.5;
// canvas.height = body.clientWidth*0.5;
width = body.clientWidth*0.5;
height = body.clientWidth*0.5;
// ctx.fillStyle = "#B0E2FF"
// ctx.fillRect(0,0,canvas.width,canvas.height);
initWebAudioApi();
}
function initWebAudioApi(){
try {
audioContext = new AudioContext();
}catch(e) {
alert("您的设备不支持Web Audi Api");
}
}
function error() {
alert('Stream generation failed.');
}
function initMovie(){
var iframe = document.getElementsByTagName("iframe")[0];
iframe.src = src;
iframe.style.display = "block";
}
function buttonClicked(){
if (!onRecord){
onRecord = true;
button.innerText = "停止";
hz.innerText = "";
getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}, gotStream);
}else{
onRecord = false;
button.innerText = "开始";
hz.innerText = "点击开始";
}
}
function getUserMedia(dictionary, callback) {
try {
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia(dictionary, callback, error);
} catch (e) {
//常见错误原因是因为使用了http协议 (这个接口需要https)
console.log(e)
alert("抱歉GetUserMedia调用失败");
}
}
function gotStream(stream) {
mediaStreamSource = audioContext.createMediaStreamSource(stream);
analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
mediaStreamSource.connect( analyser );
updatePitch();
}
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)
return -1;
var lastCorrelation=1;
for (var offset = 0; 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);
correlations[offset] = correlation; // store it, for the tweaking we need to do below.
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) {
return sampleRate/best_offset;
}
return -1;
}
var buflen = 1024,
startDetect = false,
canChange = true;
frequency = 0;
var buf = new Float32Array(buflen);
function updatePitch(){
frequency++;
analyser.getFloatTimeDomainData(buf);
var ac = autoCorrelate(buf,audioContext.sampleRate);
var current_hz = 0;
if (ac != -1){
pitch = ac;
current_hz = (Math.round( pitch ));
}
if (current_hz>20000){
startDetect = true;
}
// if (startDetect){
// if (historyHz.length<50){
// historyHz
// }
// }
//
// if (historyHz.length>100){
// if (historyHz.indexOf(20000)==0){
// console.log(historyHz);
// }
// historyHz.length = 0;
// }
// currentHz = current_hz;
if (current_hz>20000){
hz.innerText = "识别到你啦";
initMovie();
canChange = false;
}
historyHz.push((current_hz>20000)?20000:current_hz);
animate()
if (canChange){
// hz.innerText = current_hz+"Hz";
loop = window.requestAnimationFrame(updatePitch);
}
}
</script>
</body>
</html></span>
基本就是在demo上进行了一点点修改
下面是发声器 可以是手机也可以是电脑
<span style="font-size:18px;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
.button {
margin-left: auto;margin-right: auto;width: 40%;height: 50px;background-color: aqua;border-radius: 5px;text-align: center;line-height: 50px;
}
</style>
</head>
<body>
<div οnclick="makeNoise()" class="button">点击发声</div>
<script type="application/javascript">
var AudioContext=AudioContext||webkitAudioContext,
context=new AudioContext,
canClick = true,
timeOut;
function makeNoise(){
var oscillator = context.createOscillator();
oscillator.connect(context.destination);
oscillator.frequency.value = 18500;
oscillator.start(0);
}
</script>
</body>
</html></span>