HTML5 Web Audio Api 声音登陆

之前最早时候给过一个识别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>


特别注意的是识别完成后请关闭这个网页


 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值