Как увеличить частоту дискретизации микрофона на проблемных c телефонах - PullRequest
0 голосов
/ 29 января 2020

Я работаю над веб-приложением, которое показывает график на основе образцов микрофонов. Я беру наибольшее значение вектора возврата из getByteTimeDomainData каждые ~ 15 мс и помещаю его на график.

Проблема в том, что в некоторых телефонах (например, в телефонах Xiaomi) я получаю поддельные сэмплы микрофона - он возвращает то же самое вектор 10 раз (~ 150 мс), и только после этого он снова сэмплирует микрофон и возвращает новый вектор еще 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

Standart phones graph

1015 * телефон Xiaomi:

высокие значения собраны из 30 вызовов to 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,130 , 131,131,131

1027

1025 * 1025 улучшить его и получить больше образцов в Xiaomi?


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);
}

1 Ответ

0 голосов
/ 02 февраля 2020

После некоторых исследований я обнаружил, что создание другого AudioContext и Analyzer дает мне разные сэмплы. Похоже, что для каждого узла существует ограничение частоты дискретизации. Поэтому я создал 3 AudioContext и использовал их среднее значение:

enter image description here

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);
}
...