一些关键事件阻止其他人开火

Some key events prevent others from firing

首先,这是我正在研究的实时应用程序:turbo_synth

我正在使用 VueJS 制作它,但是,我认为这个问题与 Vue 无关。

问题: 一切正常,花花公子,除非尝试弹奏某些音符组合,例如,尝试弹奏 Q、W 键,然后弹奏 2。您会注意到最后一个音符没有被弹奏,甚至没有显示为已按下,而您可以同时玩 Q、W、E、R 和 Y。所以好像没有我之前想的那样是有限制的?

代码:我正在使用vue-keypress来轻松全局处理按键事件。

模板部分

<template>
    <div id="app">
        <h1>Basic oscillator test</h1>
        <label for="waveType">Choose a wave type:</label>

        <select
            name="waveType"
            id="waveType"
            v-model="wave"
        >
            <option value="sine">sine</option>
            <option value="square">square</option>
            <option value="triangle">triangle</option>
            <option value="sawtooth">sawtooth</option>
        </select>

        <hr>

        <ul class="keyboard">
            <li
                v-for="note in testBoard"
                :key="note.id"
                :class="[note.class, getKeyByValue(testBoard, note).charAt(0), {'pressed': pressedNotes.includes(note.freq)}]"
                @mousedown="playSound(note.freq, 1)"
            >
                <p>{{getKeyByValue(testBoard, note).replace('s', '#')}}</p>
                <p>{{String.fromCharCode(note.keycode)}}</p>
            </li>
        </ul>

        <Keypress
            v-for="note in testBoard"
            :key="note.id"
            key-event="keydown"
            :key-code="note.keycode"
            @success="playSound(note.freq)"
        />
        <Keypress
            v-for="note in testBoard"
            :key="note.id"
            key-event="keyup"
            :key-code="note.keycode"
            @success="removeNote(note.freq)"
        />
    </div>
</template>

脚本部分:

<script>
import { noteValues, testBoard } from './assets/notevalues.js';
export default {
    name: 'App',
    data() {
        return {
            noteValues,
            testBoard,
            selectedNote: null,
            wave: 'sine',
            pressedNotes: [],
        }
    },
    components: {
        Keypress: () => import('vue-keypress')
    },
    methods: {
        getKeyByValue(object, value) {
            return Object.keys(object).find(key => object[key] === value);
        }
        ,
        playSound(note, clicked) {
            if (this.pressedNotes.includes(note)) {
                return;
            } else {
                this.pressedNotes.push(note);
                const context = new AudioContext();
                const o = context.createOscillator();
                const g = context.createGain();
                o.connect(g);
                g.connect(context.destination);
                o.type = this.wave;
                const frequency = note;
                o.frequency.value = frequency;
                o.start(0);
                o.stop(context.currentTime + 1)
                g.gain.exponentialRampToValueAtTime(
                    0.00001, context.currentTime + 2.5
                );
                setTimeout(() => {
                    context.close();
                }, 1000);
                if (clicked === 1) {
                    setTimeout(() => {
                        this.removeNote(note);
                    }, 50)
                }
            }
        },
        removeNote(note) {
            const index = this.pressedNotes.indexOf(note);
            if (index > -1) {
                this.pressedNotes.splice(index, 1);
            }
        }
    },
}
</script>

这是注释列表:

export let testBoard = {
  'C3': { keycode: 81, freq: 130.81, class: 'white' },
  'Cs3': { keycode: 50, freq: 138.59, class: 'black' },
  'D3': { keycode: 87, freq: 146.83, class: 'white' },
  'Ds3': { keycode: 51, freq: 155.56, class: 'black' },
  'E3': { keycode: 69, freq: 164.81, class: 'white' },
  'F3': { keycode: 82, freq: 174.61, class: 'white' },
  'Fs3': { keycode: 53, freq: 185.00, class: 'black' },
  'G3': { keycode: 84, freq: 196.00, class: 'white' },
  'Gs3': { keycode: 54, freq: 207.65, class: 'black' },
  'A3': { keycode: 89, freq: 220.00, class: 'white' },
  'As3': { keycode: 55, freq: 233.08, class: 'black' },
  'B3': { keycode: 85, freq: 246.94, class: 'white' },
  'C4': { keycode: 90, freq: 261.63, class: 'white' },
  'Cs4': { keycode: 83, freq: 277.18, class: 'black' },
  'D4': { keycode: 88, freq: 293.66, class: 'white' },
  'Ds4': { keycode: 68, freq: 311.13, class: 'black' },
  'E4': { keycode: 67, freq: 329.63, class: 'white' },
  'F4': { keycode: 86, freq: 349.23, class: 'white' },
  'Fs4': { keycode: 71, freq: 369.99, class: 'black' },
  'G4': { keycode: 66, freq: 392.00, class: 'white' },
  'Gs4': { keycode: 72, freq: 415.30, class: 'black' },
  'A4': { keycode: 78, freq: 440.00, class: 'white' },
  'As4': { keycode: 74, freq: 466.16, class: 'black' },
  'B4': { keycode: 77, freq: 493.88, class: 'white' }
}

我也试过别人用vue或其他技术做的钢琴,总是有类似的问题。 我可能遗漏了一些重要的东西,谁知道呢,但我找不到我需要的信息。

非常感谢

您的代码没有任何问题,您也无法修复它 — 这是许多键盘的硬件限制。

首先,假设键盘布局为矩形网格(换句话说,1Q AZ 在同一列中,尽管它们通常不在彼此的正上方)。

限制是不能同时识别构成矩形三个角的三个键。如果您连续按住两个键,则第三个键不能与前两个键在同一列中。如果您在一列中按住两个键,则第三个键不能与前两个键位于同一行。如果您按住 QZ,那么以 A 开头的行上的任何键都可以正常工作, 但 W, E, X, C,等等都将被锁定。

或者,有些机器可能会在矩形的第四个角给你“幽灵”按键——按住 QZ 和按 E 会为 E 注册一个按键,同时也会为 C 注册一个按键,即使虽然没有人按下 C.

所有这些都与电子键盘的构建方式有关,您无法通过软件对此做任何事情。有一些键盘没有这个限制,但你不能指望你的用户有它们。