Мне интересно, как интегрировать Webmidi.js, p5.js и мой миди-контроллер Akai mPK49? Это итоговый проект для школы.
Прочитав Основы Webmidi.js, я смог включить программу в список моего MIDI-контроллера. Несмотря на то, что веб-сайт p5 выдавал ошибку «TypeError: невозможно прочитать свойства неопределенных (чтение «каналов»)», имена заметок печатались в консоли. Затем я попытался проверить, смогу ли я воспроизводить миди-ноты в своей DAW Logic Pro X. Я заметил, что и логика, и программа P5.js/Webmidi.js признавали, что я нажимаю клавиши на контроллере.
Я перешел к следующему шагу, чтобы добавить базовый синтезатор и попытаться сыграть настоящую ноту. Консоль перестала показывать, что я играю ноты, а показывала только порты Akai и что Logic Pro является входом и выходом.
Кроме того, я закомментировал новые строки кода синтезатора, и консоль по-прежнему не отображала миди-ноты в консоли. Так что я немного в замешательстве. Вот ссылка на скетч P5.js.Любая помощь приветствуется!
function setup() {
createCanvas(400, 400);
WebMidi
.enable()
//.then(() => console.info("WebMidi enabled!"))
.then(onEnabled)
.catch(err => alert(err));
}
function draw() {
background(220);
}
function onEnabled() {
// Inputs
WebMidi.inputs.forEach(input => console.info(input.manufacturer, input.name));
// Outputs
WebMidi.outputs.forEach(output => console.info(output.manufacturer, output.name));
const myInput = WebMidi.getInputByName("Akai MPK 49");
const mySynth = myInput.channels[1]; // <-- the MIDI channel (10)
myInput.addListener("noteon", e => {
console.info(e.note.identifier);
})
mySynth.addListener("noteon", e => {
console.info(e.note.identifier, e.message.channel);
})
let output = WebMidi.outputs[0];
let channel = output.channels[1];
channel.playNote("C3");
}
@K-PopCorn, возможно, произошел сбой WebMidi.getInputByName("Akai MPK 49")
(возможно, устройство отключено, опечатка в имени и т. д.). и myInput
не определено, поэтому доступ к каналам невозможен. Раньше не пробовал WebMidi, но попробуйте console.info(WebMidi.inputs)
перед звонком getInputByName
и дважды проверьте имя/идентификатор. (также попробуйте WebMidi.getInputById
с правильным идентификатором вместо getInputByName
на всякий случай).
В моей системе работает следующее. p5.TriOsc() используется для воспроизведения нот с помощью этой техники. Вам нужно будет изменить имя вашего устройства; вам не нужен производитель, только название устройства. Вам также потребуется добавить следующий скрипт в index.html:
<script src = "https://cdn.jsdelivr.net/npm/webmidi@latest/dist/iife/webmidi.iife.js"></script>
function setup() {
createCanvas(200, 200);
osc = new p5.TriOsc(); // Need this to play the notes
env = new p5.Envelope();
WebMidi.enable()
.then(() => console.info("WebMidi enabled!"))
.then(onEnabled)
.catch((err) => alert(err));
}
function draw() {
background(220);
}
function playSound(midiVal) {
osc.start();
freq = midiToFreq(midiVal);
osc.freq(freq);
env.ramp(osc, 0, 1.0, 0);
}
function onEnabled() {
// Inputs
WebMidi.inputs.forEach((input) =>
console.info(input.manufacturer, input.name)
);
// Outputs
WebMidi.outputs.forEach((output) =>
console.info(output.manufacturer, output.name)
);
const myInput = WebMidi.getInputByName("Q Mini");
myInput.addListener("noteon", (e) => {
console.info(e.note.identifier);
console.info("value = ", e.message.data[1]);
playSound(e.message.data[1]);
});
}
Альтернативный метод:
Ниже приведен альтернативный метод, который не требует добавления какого-либо дополнительного кода в index.html или запроса «прослушивателя». Его недостатком является то, что onmidimessage сообщается дважды и, следовательно, нота воспроизводится дважды. Чтобы обойти эту проблему, добавляется счетчик, который сбрасывается в ноль после первой итерации, в результате чего нота воспроизводится только один раз.
let counter = 0;
function setup() {
createCanvas(100, 100);
osc = new p5.TriOsc(); // Need this to play the notes
env = new p5.Envelope();
}
function playSound(midiVal) {
osc.start();
freq = midiToFreq(midiVal);
osc.freq(freq);
env.ramp(osc, 0, 1.0, 0);
}
navigator.requestMIDIAccess().then((midiAccess) => {
console.info(midiAccess.inputs);
Array.from(midiAccess.inputs).forEach((input) => {
input[1].onmidimessage = (msg) => {
if (counter == 0) {
console.info("value = ", msg.data[1]);
playSound(msg.data[1]);
}
counter++;
if (counter > 1) counter = 0;
};
});
});
function draw() {
background(220);
}
Спасибо за ваш совет. Я попробовал ваш код. Я постоянно получаю следующее сообщение об ошибке: «TypeError: невозможно прочитать свойства неопределенного значения (чтение «addListener»)». Я предполагал, что assListener является частью библиотеки. Я попытался создать переменную addListener, но безуспешно.
Должно работать без ошибок. Вы добавили показанную выше библиотеку webmidi в index.html? Я видел подобное сообщение об ошибке при попытке использовать функцию до вызова класса. Скопируйте/вставьте код «как есть» в веб-редактор p5.js; не пытайтесь переставить его. Я запустил его в браузере Chrome.
Я попробовал еще раз и снова поместил ссылку выше в html, но она все равно выдает ошибку. Но ошибка в виде всплывающего окна. в консоли не отображается ошибка. Программа распознает мою клавиатуру, и если я открываю Logic Pro, она даже распознает Logic как выходной сигнал. Но он не распознает, когда я нажимаю какие-либо клавиши. В какой-то момент вчера он распознавал ключи, а потом внезапно перестал, и я в таком тупике. Спасибо за помощь!
Вы видите заметку и ее значение в консоли? Чтобы сыграть ноту, вам нужно значение каждой клавиши. Если вы не видите букву заметки и ее значение, значит, прослушиватель WebMidi по какой-то причине не работает. Мне также не удалось использовать функцию playNote(), которую вы изначально опубликовали. Есть ли еще другое приложение Midi, которое вы могли бы попробовать? Вот еще одна ссылка, если вы ее не видели: smashingmagazine.com/2018/03/web-midi-api
Пожалуйста, попробуйте второй метод в отредактированном ответе.
Пожалуйста, исправьте ошибку в коде
[![]
. Спасибо.