Интеграция Webmidi.js и p5.js

Мне интересно, как интегрировать 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");
}

Пожалуйста, исправьте ошибку в коде [![]. Спасибо.

ggorlen 29.04.2024 06:51

@K-PopCorn, возможно, произошел сбой WebMidi.getInputByName("Akai MPK 49") (возможно, устройство отключено, опечатка в имени и т. д.). и myInput не определено, поэтому доступ к каналам невозможен. Раньше не пробовал WebMidi, но попробуйте console.info(WebMidi.inputs) перед звонком getInputByName и дважды проверьте имя/идентификатор. (также попробуйте WebMidi.getInputById с правильным идентификатором вместо getInputByName на всякий случай).

George Profenza 29.04.2024 08:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В моей системе работает следующее. 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, но безуспешно.

K-PopCorn 30.04.2024 22:49

Должно работать без ошибок. Вы добавили показанную выше библиотеку webmidi в index.html? Я видел подобное сообщение об ошибке при попытке использовать функцию до вызова класса. Скопируйте/вставьте код «как есть» в веб-редактор p5.js; не пытайтесь переставить его. Я запустил его в браузере Chrome.

apodidae 01.05.2024 02:00

Я попробовал еще раз и снова поместил ссылку выше в html, но она все равно выдает ошибку. Но ошибка в виде всплывающего окна. в консоли не отображается ошибка. Программа распознает мою клавиатуру, и если я открываю Logic Pro, она даже распознает Logic как выходной сигнал. Но он не распознает, когда я нажимаю какие-либо клавиши. В какой-то момент вчера он распознавал ключи, а потом внезапно перестал, и я в таком тупике. Спасибо за помощь!

K-PopCorn 01.05.2024 02:47

Вы видите заметку и ее значение в консоли? Чтобы сыграть ноту, вам нужно значение каждой клавиши. Если вы не видите букву заметки и ее значение, значит, прослушиватель WebMidi по какой-то причине не работает. Мне также не удалось использовать функцию playNote(), которую вы изначально опубликовали. Есть ли еще другое приложение Midi, которое вы могли бы попробовать? Вот еще одна ссылка, если вы ее не видели: smashingmagazine.com/2018/03/web-midi-api

apodidae 01.05.2024 03:48

Пожалуйста, попробуйте второй метод в отредактированном ответе.

apodidae 01.05.2024 17:09

Другие вопросы по теме