如何提高有问题手机的麦克风采样率

How to increase the microphone sample rate on problematic phones

我正在开发一个基于麦克风样本显示图表的网络应用程序。我每隔 ~15 毫秒从 getByteTimeDomainData 中获取向量 return 的最高值,并将其放在图表上。

问题是,在某些手机(例如小米手机)中,我得到了假的麦克风样本 - return它使用相同的向量 10 次(~150 毫秒),然后才再次对麦克风进行采样并且 return 是另外 10 次的新向量。

标准手机:

从 30 次调用 getByteTimeDomainData 中收集的最高值: 230,237,237,236,236,220,220,232,232,218,218,214,214,217,217,227,227,222,222,224,224,222,222,216,216,202,202,223,223,205

小米手机:

从 30 次调用 getByteTimeDomainData 中收集的最高值: 132,132,132,132,132,132,132,129,129,129,129,129,129,129,129,129,129,130,130,130,130,130,130,130,130,130,13=131,[3=3],[3=3]

我的问题是- 我如何改进它并在小米中获得更多样本?


var start_amp = function () {
    'use strict';

    var soundAllowed = function (stream) {
        window.persistAudioStream = stream;
        var audioContext = new AudioContext();
        var audioStream = audioContext.createMediaStreamSource(stream);
        var analyser = audioContext.createAnalyser();

        audioStream.connect(analyser);

        analyser.smoothingTimeConstant = 0; // = 1 doesn't fix the samples problem
        analyser.fftSize = 1024;

        var frequencyArray = new Uint8Array(analyser.frequencyBinCount);

        var doDraw = function () {
            requestAnimationFrame(doDraw);
            analyser.getByteTimeDomainData(frequencyArray);

            var max = 0;
            for (var i = 0; i < frequencyArray.length; i++) {
                if (max < frequencyArray[i]) {
                    max = frequencyArray[i];
                }
            }

            boardArray.push(max);

            if (boardArray.length >= document.body.clientWidth * 0.7) {
                boardArray.shift();
                totalSamples += 1;
                if (totalSamples == 60) {
                    totalSamples = 0;
                }
            }

            draw(boardArray);
        }
        doDraw();
    }

    var soundNotAllowed = function (error) {
        alert('Please check your microphone connectivity and allow this site to access it');
        console.log(error);
    }

    navigator.getUserMedia({ audio: true }, soundAllowed, soundNotAllowed);
}

经过一些研究,我发现创建另一个 AudioContext 和 Analyzer 会给我不同的样本。看起来每个节点都有一些采样率限制。 所以我创建了 3 个 AudioContext 并使用它们的平均值:

var start_amp = function () {
    'use strict';

    var soundAllowed = function (stream) {
        window.persistAudioStream = stream;

        // Node 1
        var audioContext = new AudioContext();
        var audioStream = audioContext.createMediaStreamSource(stream);
        var analyser = audioContext.createAnalyser();

        audioStream.connect(analyser);

        analyser.smoothingTimeConstant = 0; // = 1 doesn't fix the samples problem
        analyser.fftSize = 1024;

        // Node 2
        var audioContext2 = new AudioContext();
        var audioStream2 = audioContext2.createMediaStreamSource(stream);
        var analyser2 = audioContext2.createAnalyser();

        audioStream2.connect(analyser2);

        analyser2.smoothingTimeConstant = 0; // = 1 doesn't fix the samples problem
        analyser2.fftSize = 1024;

        // Node 3
        var audioContext3 = new AudioContext();
        var audioStream3 = audioContext3.createMediaStreamSource(stream);
        var analyser3 = audioContext3.createAnalyser();

        audioStream3.connect(analyser3);

        analyser3.smoothingTimeConstant = 0; // = 1 doesn't fix the samples problem
        analyser3.fftSize = 1024;

        var frequencyArray = new Uint8Array(analyser.frequencyBinCount);
        var frequencyArray2 = new Uint8Array(analyser2.frequencyBinCount);
        var frequencyArray3 = new Uint8Array(analyser3.frequencyBinCount);

        var doDraw = function () {
            requestAnimationFrame(doDraw);
            analyser.getByteTimeDomainData(frequencyArray);
            analyser2.getByteTimeDomainData(frequencyArray2);
            analyser3.getByteTimeDomainData(frequencyArray3);

            var max = 0;
            for (var i = 0; i < frequencyArray.length; i++) {
                if (max < frequencyArray[i]) {
                    max = frequencyArray[i];
                }
            }

            var max2 = 0;
            for (var i = 0; i < frequencyArray2.length; i++) {
                if (max2 < frequencyArray2[i]) {
                    max2 = frequencyArray2[i];
                }
            }

            var max3 = 0;
            for (var i = 0; i < frequencyArray3.length; i++) {
                if (max3 < frequencyArray3[i]) {
                    max3 = frequencyArray3[i];
                }
            }

            boardArray.push((max + max2 + max3) / 3);

            if (boardArray.length >= document.body.clientWidth * 0.7) {
                boardArray.shift();
                totalSamples += 1;
                if (totalSamples == 60) {
                    totalSamples = 0;
                }
            }

            draw(boardArray);
        }
        doDraw();
    }

    var soundNotAllowed = function (error) {
        alert('Please check your microphone connectivity and allow this site to access it');
        console.log(error);
    }

    navigator.getUserMedia({ audio: true }, soundAllowed, soundNotAllowed);
}