Несколько экземпляров в веб-аудио - PullRequest
1 голос
/ 04 марта 2020

Я пытаюсь создать простое программное обеспечение для фортепиано, используя HTML и JavaScript, которое может играть только одну октаву только с клавишами клавиатуры. Раскладка клавиш выглядит примерно так:
enter image description here
Хотя звук не похож на пианино, я рассмотрю эту часть позже. Я написал этот код:

<html>

<body onkeydown="play(event)" onkeyup="stop(event)">
    <span style="font-size:10em;">Piano</span>
    <script>
        var context, o, g;

        function play(event) {
            context = new AudioContext();
            o = context.createOscillator();
            var key = event.which || event.keyCode;
            if (key == 49) o.frequency.value = 116.54;
            if (key == 81) o.frequency.value = 123.47;
            if (key == 87) o.frequency.value = 130.81;
            if (key == 51) o.frequency.value = 138.59;
            if (key == 69) o.frequency.value = 146.83;
            if (key == 52) o.frequency.value = 155.56;
            if (key == 82) o.frequency.value = 164.81;
            if (key == 84) o.frequency.value = 174.61;
            if (key == 54) o.frequency.value = 185.00;
            if (key == 89) o.frequency.value = 196.00;
            if (key == 55) o.frequency.value = 207.65;
            if (key == 85) o.frequency.value = 220.00;
            if (key == 56) o.frequency.value = 233.08;
            if (key == 73) o.frequency.value = 246.94;
            if (key == 79) o.frequency.value = 261.63;
            if (key == 48) o.frequency.value = 277.18;
            if (key == 80) o.frequency.value = 293.66;
            if (key == 189) o.frequency.value = 311.13;
            if (key == 219) o.frequency.value = 329.63;
            if (key == 221) o.frequency.value = 349.23;
            g = context.createGain();
            o.connect(g);
            g.connect(context.destination);
            o.start(0);
        }

        function stop(event) {
            g.gain.exponentialRampToValueAtTime(0.00001, context.currentTime + 0.1);
            o.disconnect(context.destination);
        }
    </script>
</body>

</html>

Теперь проблема в том, что, если я удерживаю клавишу нажатой, есть несколько экземпляров этой конкретной частоты. По этой причине я не могу нажимать несколько клавиш одновременно. Чтобы преодолеть это, я немного изменил код:



var context, o, g;

    function play(event) {
        context = new AudioContext();
        o = context.createOscillator();
        var key = event.which || event.keyCode;
        if (key == 49) o.frequency.value = 116.54;
        if (key == 81) o.frequency.value = 123.47;
        if (key == 87) o.frequency.value = 130.81;
        if (key == 51) o.frequency.value = 138.59;
        if (key == 69) o.frequency.value = 146.83;
        if (key == 52) o.frequency.value = 155.56;
        if (key == 82) o.frequency.value = 164.81;
        if (key == 84) o.frequency.value = 174.61;
        if (key == 54) o.frequency.value = 185.00;
        if (key == 89) o.frequency.value = 196.00;
        if (key == 55) o.frequency.value = 207.65;
        if (key == 85) o.frequency.value = 220.00;
        if (key == 56) o.frequency.value = 233.08;
        if (key == 73) o.frequency.value = 246.94;
        if (key == 79) o.frequency.value = 261.63;
        if (key == 48) o.frequency.value = 277.18;
        if (key == 80) o.frequency.value = 293.66;
        if (key == 189) o.frequency.value = 311.13;
        if (key == 219) o.frequency.value = 329.63;
        if (key == 221) o.frequency.value = 349.23;
        g = context.createGain();
        o.connect(g);
        g.connect(context.destination);
        o.start(0);
        document.body.removeEventListener("keydown", play(event)); //Added this part
    }

    function stop(event) {
        g.gain.exponentialRampToValueAtTime(0.00001, context.currentTime + 0.1);
        o.disconnect(context.destination);
        document.body.addEventListener("keydown", play(event)); //Added this part
    }

Теперь, если я загружу это в браузер Chrome и нажму клавишу, браузер вместе с моей ОС Ubuntu зависнет !!! Почему это происходит и как я могу достичь того, чего хочу?

1 Ответ

1 голос
/ 04 марта 2020

Подумайте о том, чтобы отделить логи c от данных, с которыми они работают:

<html>

<body onkeydown="play(event)" onkeyup="stop(event)">
    <span style="font-size:10em;">Piano</span>
    <script>

        const keyToFrequencyMap = {
            49: 116.54,
            81: 123.47,
            87: 130.81,
            51: 138.59,
            69: 146.83,
            52: 155.56,
            82: 164.81,
            84: 174.61,
            54: 185.00,
            89: 196.00,
            55: 207.65,
            85: 220.00,
            56: 233.08,
            73: 246.94,
            79: 261.63,
            48: 277.18,
            80: 293.66,
            189: 311.13,
            219: 329.63,
            221: 349.23
        }
        var context, o, g;

        function play(event) {
            context = new AudioContext();
            o = context.createOscillator();
            var key = event.which || event.keyCode;
            o.frequency.value = keyToFrequencyMap[key]
            console.log(`Playing ${o.frequency.value}`)
            g = context.createGain();
            o.connect(g);
            g.connect(context.destination);
            o.start(0);
        }

        function stop(event) {
            g.gain.exponentialRampToValueAtTime(0.00001, context.currentTime + 0.1);
            console.log('Disconnecting')
            o.disconnect(context.destination);
        }
    </script>
</body>

</html>

console.log - ваш друг. Либо воспроизводятся несколько нот, либо нота не останавливается, когда вы считаете, что это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...