GithubHelp home page GithubHelp logo

djipco / webmidi Goto Github PK

View Code? Open in Web Editor NEW
1.5K 43.0 115.0 63.04 MB

Tame the Web MIDI API. Send and receive MIDI messages with ease. Control instruments with user-friendly functions (playNote, sendPitchBend, etc.). React to MIDI input with simple event listeners (noteon, pitchbend, controlchange, etc.).

License: Apache License 2.0

JavaScript 97.46% Handlebars 0.65% SCSS 1.79% CSS 0.10%
web-midi-api web-midi midi webmidi jazz-plugin sysex midi-messages node browser

webmidi's Introduction

WebMidi.js Logo

npm npm npm

Introduction

WEBMIDI.js makes it easy to interact with MIDI instruments directly from a web browser or from Node.js. It simplifies the control of physical or virtual MIDI instruments with user-friendly functions such as playNote(), sendPitchBend() or sendControlChange(). It also allows reacting to inbound MIDI messages by adding listeners for events such as "noteon", "pitchbend" or "programchange".

In short, the goal behind WEBMIDI.js is to get you started with your web-based MIDI project as quickly and efficiently as possible.

Getting Started

The official website site is the best place to get started. Over there, you will find, amongst others, two key resources:

To exchange with fellow users and myself, you can visit our Forum which is hosted on the GitHub Discussions platform:

If you want to stay up-to-date, here are your best sources:

Sponsors

WEBMIDI.js is a passion project but it still takes quite a bit of time, effort and money to develop and maintain. That's why I would like to sincerely thank 👏 these sponsors for their support:

    Anonymous Sponsor     Anonymous Sponsor   Anonymous Sponsor

If you use the library and find it useful, please 💜 sponsor the project.

Feature Request

If you would like to request a new feature, enhancement or API change, please first check that it is not already planned. Then, discuss it in the Enhancement Proposals section of the forum.

Citing this Software in Research

If you use this software for research or academic purposes, please cite the project in your references (or wherever appropriate). Here's an example of how to cite it (APA Style):

Côté, J. P. (2021). WebMidi.js v3.0.0 [Computer Software]. Retrieved from https://github.com/djipco/webmidi

Cheers!

-- Jean-Philippe

webmidi's People

Contributors

archonic944 avatar beaugunderson avatar belm0 avatar bgins avatar cotejp avatar dahegyi avatar danigb avatar dependabot[bot] avatar diegoherranz avatar disambiguator avatar djipco avatar drewm avatar francoisgeorgy avatar j-mg21 avatar jessepinho avatar jjeff avatar kant avatar misterinterrupt avatar mmmveggies avatar normanfeltz avatar oceansize avatar tbazin avatar tehbrian avatar thovden avatar timsusa avatar tobyhede avatar vexcited avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webmidi's Issues

WebMidi.enable() callback never invoked

I'm trying to debug odd behavior when using webmidi and the iOS Web MIDI Browser.

If I connect my MIDI input device (happens to be bluetooth) after starting the app, webmidi behaves as expected. However if I start the app with the MIDI device already connected, WebMidi.enable() never invokes its callback function.

It's hard to debug since the Safari remote inspector isn't working for me (Web MIDI Browser author claims it should), but I've confirmed that a JS exception is not occurring. Roughly, the following code will only log "done":

WebMidi.enable(function(err) { log('enable'); });
log('done');

details:
webmidi v2.0.0-rc.11
Web MIDI browser v1.0.6
iOS 11.2.1 iPad Air 2

Wrong octave system-wide

When I press Middle C, then noteon event reports it as C3 while it should be C4.

I'm using event listening code from README.md:

 // Listen for a 'note on' message on all channels
  input.addListener('noteon', "all",
    function (e) {
      console.log("Received 'noteon' message (" + e.note.name + e.note.octave + ").");
    }
  );

Same happens, the other way around: attempt to play C3 actually plays C4:

output.playNote('C3', 'all', {duration: 2000, velocity: 0.25});

Here are octaves shown by Synthesia and it clearly shows that when C3 is reported by noteon event, then Synthesia (and other programs) display it as C4:

2018-06-08_0853

I'm suspecting an issue when in math, when decoding/encoding midi messages.

When I press 1st key on the keyboard (A0) it's reported as A-1, which according to README.md is a special code for stop playing note on all channels (see output.stopNote("C-1"); in there).

MIDI CC

I know that we can set NRPN, but is there an API to change CC?

Rescan devices

Hi! I would to update devices when they changed. To do this I followed this steps:

  1. On Mac go to Audio/Midi setup and add, for examples, an IAC driver and a Network device.
  2. At the startup of my app I started MIDI with WebMidi.enable(e => etc...) and I correctly have 2 inputs and 2 outputs (Network and IAC)
  3. Go to Audio/Midi setup and delete one MIDI device (ex: Network device)
  4. In my app I fired a function that stop and re-start WebMidi with WebMidi.disable(); WebMidi.enable(e => etc...);
  5. I always got two devices instead of one.

EXPECTED: When I stop and re-start WebMidi I expected to have the update devices list.

I'm doing wrong?

Thanks! :-)

Use `import` or `require` syntax for node module.

Hi, I am building an application with React and Webpack, and I used NPM to install webmidi.

I see from the README that I need to include a <script> tag:

<script src="node_modules/webmidi/webmidi.min.js"></script>

Is there a way to do this in javascript via an import or require statement?

Velocity > 1

Hi, i am using your excellent library to send a recieve signals from my APC Mini.

In order to debug and play around with it I have mapped all of my pads to a virtual interface of checkboxes and range sliders, and have it set up to detect the 'noteoff' event when i press any of the pads. I managed to find some basic docs for the mini which show the pad IDs which saved me a bit of time, and also noticed that i can send a signal back to the pad to tell the pad to stay lit once pressed, but in order to do this i need to be able to send a velocity signal > 1 back to it. I got it working by removing the check on line 2652 in your library but just wondered if theres a cleaner way to do it? my code to set the LEDs on the pads is provided below for clarity, and the original graphic i found which steered me in the right direction.

APC mini mappings

output.playNote(56, 'all', {velocity:0});  // off
output.playNote(56, 'all', {velocity:1});  // green
output.playNote(56, 'all', {velocity:2});  // green_blink
output.playNote(56, 'all', {velocity:3});  // red
output.playNote(56, 'all', {velocity:4});  // red_blink
output.playNote(56, 'all', {velocity:5});  // yellow
output.playNote(56, 'all', {velocity:6});  // yellow_blink

any ideas?

any if anyone is interested i can upload my virtual APC mini interface, preumably it would only require slight modifications to be used with other similar devices.

note objects in WebMIdi

Here's my suggestion of how
we could make note objects without being disruptive to
existing WebMidi.
Each method that takes an "options" argument, would
simply take the other args as fields in the "options" argument.
Here's the beginning of playNote that could accomodate this
with transforming a call like:
input1.playNote("C#4", 1, {duration: 1000})
to
input1.playNote({pitch: "C#4", channel: 1, duration: 1000})

enabling:
var my_note = {pitch: "C#4", channel: 1, duration: 1000}
input1.playNote(my_note)

Via:

Output.prototype.playNote = function(note, channel, options) { //same params as now
if (typeof(note) == "object"){
if(channel) { throw error }
else {
channel = note.channel
options = note
note = options.pitch
}
}
... rest of existing implementation of playNote

Observe that the MIDI convention of using the
word "note" to mean "pitch" is a disaster,
so I don't recommend using it.
So I'd prefer:
Output.prototype.playNote = function(pitch, channel, options) {
if (typeof(pitch) == "object"){
if(channel) { throw error }
else {
channel = pitch.channel
options = pitch
pitch = options.pitch
}
}

In any case, using this style to extend the
methods that take "options"
as an argument gives you the capacity
to make and pass around notes as one literal
JS object, and maintains backwards compatibility.

I have a class called Note.
If we had the above def for playNote,
I think I could just pass an instance of my Note class
into playNote, and it would work.
Furthermore, anyone could build their own Note-like class
and as long as they used the same names and
value types & ranges as your code, (which I did!)
they can add whatever extra fields and methods
to their class and things should work out.

Creating a device selector dropdown causes an Uncaught TypeError

Last week, I created a website to visualize an art project using MIDI. In order for everybody on the team to be able to use it, I made a dropdown to select the MIDI device. Last week, this was all functioning all-right, without any errors (Win10, Google Chrome, most recent version).

Today, with identical code, I keep getting this error on running the generateDeviceDropdown() function, which runs on pageload in my application. The error and function can be found below.

Uncaught TypeError: Cannot read property 'inputs' of undefined
at WebMidi._updateInputs (webmidi.min.js:30)
at WebMidi._updateInputsAndOutputs (webmidi.min.js:30)
at WebMidi._processStateChange (webmidi.min.js:30)
at WebMidi._onInterfaceStateChange (webmidi.min.js:30)

function generateDeviceDropdown(){
	WebMidi.enable(function(err) { 
	//error collector
    if (err) console.log("WebMidi could not be enabled");
	//generate dropdown with MIDI inputs	
	var dropdown = document.getElementById("midiDeviceSelector");
	for (var i=0; i<(WebMidi.inputs.length); i++)
	{
		var option = document.createElement("option");
		option.text=WebMidi.inputs[i].name;
		option.value=i;
		dropdown.add(option);
	}
	WebMidi.disable();
  }
);
}

A way to prevent this error, is to add a breakpoint for debugging literally anywhere in the WebMidi.enable() function inside the generateDeviceDropDown() function. After resuming script execution there is no error. Any idea what could be causing this behaviour?

Provide a default export to load the module via ES6 imports

In order to load the module using ES6 imports and without a bundler like webpack, it would be nice to provide a export default, so WebMidi.js can be loaded like this:

import WebMidi from '/node_modules/webmidi/webmidi.min.js'

What happens instead

The following error is thrown:

Uncaught (in promise) SyntaxError: The requested module '/node_modules/webmidi/webmidi.min.js' does not provide an export named 'default'

Show sent/received mesages in hex/dec

Would be nice to show the full hex string omitted by the output port as well as what is received on the input port for SYSEX. This would help in diagnosing transmitted and received messages.

Parse received NRPN messages

I'm planning to port this max/msp javascript so it will work on "webmidi" library.

While I don't get to this part of my project, I would like to share the current parser I have on a Max/MSP prototype ( the core functionality was borrowed from an article written by Chris Hector from Dave Smith Instruments ) available here so if anyone else is interested in working this out there would be a great starting point ( basically the algorithm is entirely written, just need to be ported really ).

https://gist.github.com/hems/8246279cf28e8607fb0167da8b3deb9a

Unfortunately, I only have 1 synth that sends and receives NRPN so it's the only synth I managed to test this and it works like a charm ( i'm able to send and receive 4096 ticks per knob ).

I'm not sure if there are details to it, the only thing I know other synths will use NRPN but have less resolution, so if anyone knows about any other NRPN particularity please go ahead and post it here.

Not receiving input events

Hi, I was able to call .playNote method on the output, but attempting to read note being pressed via noteon event doesn't produce any results for me.

I'm using this code:

$(document).ready(function () {
   WebMidi.enable(function (err) {
       var $input = WebMidi.getInputByName('MIDI Device Name');

       $input.addListener('noteon', 'all', function($e) {
           console.log('The "noteon" event: ', $e);
       });
   });
});

I do have same MIDI device shown in WebMidi.inputs and WebMidi.outputs. Any ideas?

I'm connecting MIDI device via Bluetooth, but I have no idea how to test, that connection actually worked. I think, that if device is shown in inputs, then it's connected properly.

I've used https://owow.io/faq/connecting-midi-bluetooth-osx-devices/ instruction for connecting.

port information on midi message event data

Hi cotejp,

thank you for your sharing code about Web MIDI API. I don't see (or understand) if your library get the port information on the midi message event ? I would like to know where do the midi message from. If I have 4 midi port activate with eventListener for catch midi message I would like to know (and see in console.log) which device I have send a midi message not just the midi message.

Your libray do that ? If no do you think that is possible dealing with Web MIDI API ?

thank for your advice

How to idiomatically stop playback?

Hi -- Suppose I schedule multiple playNote & stopNotes across various channels at future time points. What is the best way to allow the user to abort the all scheduled events -- is it to disable and then reenable WebMidi? (I'm looking for a solution that is similar to what is possible with webaudio where it is not possible to cancel individual events (i think), but it is simple enough to stop all sound with one command, and then start over from scratch.

thanks, nehal

bank select korg x50

First of all, congratulations for your work !!
I am a musician and passionate about programming.
I'm trying to control a korg x50.
I managed to change instrument (with program change) but I can't change the sound bank (bank select) is it possible?

Thanks in advance Enrico

Export TS interfaces so they can be used for compile-time type checking

Hello, lovely library! Thanks for all the work on this.

I'm working on a general timing library for Web Audio / Web MIDI applications, and would like to have intellisense and type checking for Interfaces that make up the webmidi package.

As an example, I can say const input = webmidi.inputs[0]. TypeScript indicates that input is of type Input, but I cannot write functions which accept the Input type as a parameter, and have to either manually copy the webmidi.d.ts to my source directory, or use the any type annotation.

I'm happy to submit a pull request if this is not a current priority!

toMidiChannels() should be able to return empty array by parameter 'none'

Hey,

I would like to create a PR, but I am not allowed to push to your branch.

At the moment the 'toMidiChannels()' function returns full set of midi-channels for undefined input, which is ok.

I would like to request a feature. It would be nice to have the 'toMidiChannels()' returning an empty array by giving in parameter 'none' with type string. In that manner, it would be possible to chose empty selections for UI-Menus in a more simple way.

  WebMidi.prototype.toMIDIChannels = function(channel) {

    var channels;

    if (channel === 'all' || channel === undefined) {
      channels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
    } else if (channel === 'none') {
      channels = [];
    } else if (!Array.isArray(channel)) {
      channels = [channel];
    } else {
      channels = channel;
    }

    // You could save that line, see above
    //if (channels.indexOf('all') > -1) {
    //  channels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
    //}

    return channels
      .map(function(ch) {
        return parseInt(ch);
      })
      .filter(function(ch) {
        return (ch >= 1 && ch <= 16)
      });

  };

Node ReferenceError: navigator is not defined

I'm running this code and it throws "ReferenceError: navigator is not defined"

var WebMidi = require('webmidi')
WebMidi.enable(function (err) {

  if (err) {
    console.log("WebMidi could not be enabled.", err);
  } else {
    console.log("WebMidi enabled!");
  }
  
});

Nothing sends/receives with SysEx enabled

I am trying to send SysEx to a Novation launchpad.

var output = WebMidi.getOutputByName("Launchpad MK2");
output = WebMidi.outputs[0];
output.sendSysex([0x00, 0x20, 0x29], [1, 2, 3, 4, 5]);

Results in Error: SysEx message support must first be activated.

I set { sysex: true } in WebMidi.enable(). (This was a guess) Chrome prompted me to enable the permission which I did. Now MIDI doesn't work at all until I remove the option.

Full code:

WebMidi.enable({ sysex: true }, function (err) {
  if (err) {
    console.log("WebMidi could not be enabled.", err);
  } else {
    var input = WebMidi.getInputByName("Launchpad MK2");
    input = WebMidi.inputs[0];
    input.addListener('noteon', "all", function (e) {
      console.log(e);
    });
    input.addListener('noteoff', "all", function (e) {
      console.log(e);
    });
    var output = WebMidi.getOutputByName("Launchpad MK2");
    output = WebMidi.outputs[0];
    output.sendSysex([0x00, 0x20, 0x29], [1, 2, 3, 4, 5]);
  }
});

Maybe am I just not using this correctly?

Fails in Chrome

I tried this sample code:

        <script>
        WebMidi.enable(
  function() { 
    // Send control change value 127 to controller 1 (modulation) on channel 
    // 12 of all devices
    WebMidi.sendControlChange(1, 127, "all", 12);
 },
  function(m) {
    console.log("Could not enable MIDI interface: " + m);
  }
);
        </script>

but in a fresh Chrome (v49.0) it fails with the following message: Uncaught (in promise) ReferenceError: There is no such output device. webmidi.js 1380

playNote with duration option isn't sending a stop note event

I'm having an issue where calling playNote with the duration option as specified in the readme doesn't appear to send a stop note event. I'm using MIDI Monitor to monitor the events.

When I run:

midiOut.playNote("Gb2", 10, {duration: 2000, velocity: 0.25});

I only get the one Note On event, there's never a Note Off event:

12:23:27.458	To MIDI Monitor (Untitled)	Note On	1	F♯2	32

System info: chrome 66.0.3359.139 on mac os 10.13.4.

Thanks!

Trouble with sendClock()

I'm having trouble getting sendClock to work.

I'm sure that it's an issue on my formatting but I can't seem to get it to work.

I've had success with sending control changes and program changes though.

Here's what I've tried to help set me straight:

output.sendClock(output={time="+1000"})
output.sendClock(output={"time"="+1000"})
output.sendClock(output={"time": "+1000"})
output.sendClock({time="+1000"})
output.sendClock(output={"+1000"})

I just need some help getting the syntax right. I'm attempting to get convert BPM to MS to set the value on a delay pedal.

Love this project! I'm trying to make an editor for my midi devices that I can save settings on my laptop and then dump them onto my devices as needed.

Search inputs/outputs by id ignoring type

Currently the WebMidi.getInputById and WebMidi.getOutputById methods use exact match (the === operator), when comparing given input/output ID to discovered ones.

In theory that sounds perfect. However in real-life scenario usually we have some sort of UI (e.g. dropdown) for selecting MIDI device and then we use that dropdown to get ID of device, that user wants.

On the iPad the ID of an output device (but applies to input as well) looked like this:

-2112946881

Not sure why, but after storing inside <option value="..."> or maybe due some other operation it was converted to string. The WebMidi.getOutputById no longer found desired MIDI device, because type wasn't matching.

I of course can do parseInt on the option's value, but I'm not 100% sure, that input/output ID will always be an integer.

Octave number inconsistent

//It appears that when WebMidi sends a noteon message to itself,
//the octave in the listened for note is 2 octaves below
//the octave that was sent.
//Code to reproduce:
//eval the commented out last line to send C3.

var wmin, wmout //WebMidiInput and WebMidiOutput ports
WebMidi = require("webmidi")
WebMidi.enable(function(err) {
 	if (err) {out("WebMidi couldn't be enabled: " + err)}
    else {
     out(WebMidi.inputs)
     out(WebMidi.outputs)
     wmin  = WebMidi.inputs[0] 
     wmout = WebMidi.outputs[0] //use same output as the output so you can "hear" what's "played"
   
     wmin.addListener('noteon',  "all",
                    function(event){
                    		debugger
                    		console.log(event.note.octave)})
  }})

// webMidi: C3 == 60 == middle C. GarageBand also plays 60 as middle C
// wmout.playNote("C3", 1, {duration: 2000})

/*setting up a Mac or PC to be able to do this without a hardware midi controller
is difficult. Here's how:
To get a MIDI app on your computer to talk to
another MIDI app on your computer,
you must set up a "Virtual Port".

On Mac 10.12 (Sierra)
Launch Applications/Utilities/Audio Midi Setup.app
Choose menubar/Window/Show Midi Studio
In the dialog box that comes up, double click "IAC Driver".
In the new dialog box that comes up,
click on the port "Bus 1" to select it.
Above that, check "Device is online"
Click the "Apply" button.

For creating virtual ports on windows:
http://www.tobias-erichsen.de/software/loopmidi.html
looks promising.

Eval the below to enable webmidi and create an input and output.

Eval the last line (playNote call) to send a note from WebMidi, through
the "Bus 1" port, and back to WebMidi.
You should see in the output pane:
"Got MIDI event: Input, IAC Driver Bus 1, channel:1, type: noteon, C1, vel: 0.5039370078740157"

To hear this on a "software synthesizer" you have to
get it to listen to midi
output on the appropriate device, on the appropriate channel.

One such software synthesizer is in GarageBand,
which is now free for Mac and Windows.

On Mac, In your Applications folder
you should see GarageBand.app (comes with the OS)
Double click on it. This will cause its full contents
to download and takes 15 minutes or so (its very large).
Once this is complete, launch it if it isn't already up.

On Windows, see https://garagebandforwindowspc.org/ for a more
complex installation, but looks promising.

With GB launched, double click on "Keyboard Collection"
Back in DDE, Eval the call to playNote and you should hear a sound.
Select a different instrument in GarageBand for a different sound.
Debugging Garage Band:
If no sound, EVAL playnote in DDE again. Sometimes the first one
just doesn't work.
If that doesn't work, check that sound is up on your computer.
(On Mac, hit the F12 key a few times.)
If that didn't help, verify that Garage Band can
make a sound by choosing its menu bar/Show Keyboard
Then click on the piano keys and you should hear a sound.
If that didn't help, check GB's "Master Slider"
(unlabeled horizontal slider in the upper right of GB main window.)
If that didn't help, check the midi connections in
Garage Band: menu bar/GarageBand/Preferences.
Select "Audio/Midi"
In the bottom of the dialog you should see
"Midi Status: X MIDI inputs detected."
(if X == 0, try clicking the "Reset Midi Drivers" button.)

Even though GB has a soft keyboard, it can't send out Midi.
You can download http://vmpk.sourceforge.net/
for a virtual midi controller,
for Mac/Windows/Linux. It has no synthesizers in it.
In the VMPK menu bar, choose "MIDI Connections".
For "MIDI OUT Driver", choose "CoreMIDI".
For "Output MIDI Connection" Choose "IAC Driver Bus 1"
(the default on the Mac, it will be something else on Windows.)
Click the OK button.
Choose VMPK menu bar/Tools/Note Input/Comuter Keyboard,
and also in the same sub menu, "Mouse".
Now click on the keyboard or hit a key (like "q")
and you should see "Got Midi event..." in DDE.
You should also hear the note played in Garage Band.

VMPK has a nice feature for labeling the keys on its
piano keyboard: Choose menu bar/View/Note names
Unfortunately this labels Middle C as C4, whereas
WebMidi uses Middle C as C3. Octave nomenclature is
inconsistent in conventional music as well as MIDI.
*/

Small error in readme example.

There is small typo in the second example (a parenthesis is missing)

WebMidi.enable(function (err) {
    console.log(WebMidi.inputs);
    console.log(WebMidi.outputs);
}
WebMidi.enable(function (err) {
    console.log(WebMidi.inputs);
    console.log(WebMidi.outputs);
});

output.playNote("C3") doesn't make any ksound

I am trying to see if this works on Chrome, and I did following

    WebMidi.enable(function (err) {
      if (err) {
        console.log("WebMidi could not be enabled.", err);
      } else {
        console.log("WebMidi enabled!");
        var mout = WebMidi.outputs[0];
        var mout.playNote("C3");
      }
    });

It doesn't make any sound. Do I need to set volume, instrument, etc?

  • I don't have any MIDI instrument attached to my computer. I am trying to play sounds just using a browser.

allnotesoff not working

http://cotejp.github.io/webmidi/latest/classes/Output.html
and its crucial content says:
sendChannelMode (command, value, [channel=all], [options={}])
Output chainable

Defined in src/webmidi.js:3793

Sends a MIDI channel mode message to the specified channel(s).

The channel mode message to send can be specified numerically or by using one of the following common names:

allsoundoff (#120)
resetallcontrollers (#121)
localcontrol (#122)
allnotesoff (#123)
omnimodeoff (#124)
omnimodeon (#125)
monomodeon (#126)
polymodeon (#127)

First attempt:
WebMidi.outputs[0].sendChannelMode("allnotesoff")
yields error: RangeError: Value must be integers between 0 and 127.
Hmm, why does allnotesoff need a value and what would iit be?
Can't it default?

In any case, attempt 2:
WebMidi.outputs[0].sendChannelMode("allnotesoff", 0)
doesn't error but doesn't shut off ongoing notes either.
I've tried the variation of using
WebMidi.outputs[0].sendChannelMode("allsoundoff", 0)
as well as using the command numbers instead of strings,
and passing the value of 127.
Didn't turn off ongoing notes playing on GarageBand on Mac.
It's possible that GarageBand doesn't respond to allnotesoff.

Create a new release with typings

Thanks for the awesome plugin.
I see that the typings are present on GitHub but not on npm. Can you make a new release with them?

Issue with MidiNote 0 (does not have octave attribute)

I just wrote a script to test WebMIDI with my devices and noticed that the event.note.octave attribute of MidiNote{value:0, name:C, octave:-2} returns undefined when accessed from the listener callback.

Tested with:

  • Akai APC Mini
  • Akai MPK 249 with octave modifier set to minimum
    webmidi apc issue

 

demo.ts

WebMidi.enable( function(error){
  if(error)
    {console.log("WebMidi Error:", error)}

  for(input of WebMidi.inputs){
    input.addListener(
      /* type     */ "noteon",
      /* channel  */ "all",
      /* callback */  function(event){console.log(`NoteOn:  ${event.note.name}${event.note.octave}`)}
    )
    input.addListener(
      /* type     */ "noteoff",
      /* channel  */ "all",
      /* callback */  function(event){console.log(`NoteOff: ${event.note.name}${event.note.octave}`)}
    )
    input.addListener(
      /* type     */ "controlchange",
      /* channel  */ "all",
      /* callback */  function(event){console.log(`CC:      ${event.controller.number}.${event.value}`)}
    )
  }
})

 

Output

NoteOn:  Cundefined
NoteOff: Cundefined
NoteOn:  C#-2
NoteOff: C#-2
NoteOn:  D-2
NoteOff: D-2

WebMidi not initialized

I've tried installing the library via NPM and manually, and the file doesn't seem to be initializing the WebMidi object correctly. See below.

<script src="node_modules/webmidi/webmidi.min.js" type="text/javascript"></script>
<script>
    console.log(WebMidi);
    // Uncaught ReferenceError: WebMidi is not defined
</script> 

I'm using Electron 1.7.5 on OS X Sierra.

Method to remove all listener

Currently is there any method to remove all registered listener from an event type? Now the function reference must be provided before one can remove the listener. It will be helpful if one can clear all the listeners of a particular event type without providing the references, e.g. in angular.js, this can allow one to assign different listener to WebMidi based on the current view.

Thank you!

sendPitchBend() causes MIDI feedback in LoopBe1

Background info

Setup:

  • Windows 10
  • Chrome 55.0.2883.87 (Official Build) m (32-bit)
  • LoopBe1

I'm sending a constant stream of MIDI messages from a trigger() function which runs continuously.

sendControlChange() works, but sendPitchBend() causes LoopBe1 to be muted due to MIDI feedback.

I'm running them separately, and there's no other MIDI being output.

Code examples

This code successfully changes my software synth's modwheel:

function trigger() {
    i++
    output.sendControlChange(1, i%127, 1)
}

When I try to do a similar thing with pitchbend, LoopBe1 shuts down after a second or so.

function trigger() {
    i+=0.01
    output.sendPitchBend(i%1)
}

The weird thing is, with vvvv I can send random pitchbend values to LoopBe1 at ~115fps, with no problems at all.

Test code

Pitchbend MIDI feedback starts occuring at around 50ms on my machine.
sendControlChange() works fine at any speed, even 1.

The code below produces feedback, but works fine if setInterval() is set to 60 or higher:

WebMidi.enable(function(err) {
    output = WebMidi.outputs[0]
    setInterval(() => {
        i += 0.1
        output.sendPitchBend(i % 1)
    }, 50)
});

(To unmute LoopBe1 again, right-click the tray icon.)

How to cause a SYSEX permission request on Chromium?

Thanks for this awesome library! I've been working on a patch editor that requires SYSEX access. The examples work for channel messages but when I try enable with SYSEX support in Chromium I just get an error. I've turned on the option to allow requests for SYSEX access.

I've tried both WebMidi.enable() as well as navigator.requestMIDIAccess() which I saw somewhere else and neither seem to work.

Any help would be greatly appreciated! My project is basically impossible if I can't send SYSEX.

I tried to play a note like in the sample code

<!DOCTYPE html>
<html>
<head>
	<title>oscillator.js</title>
	<script src="http://localhost/webmidi/webmidi.min.js"></script>
</head>
<body>
<script type="text/javascript">
WebMidi.enable( function() {
    WebMidi.playNote("C3", 1, 1000, WebMidi.outputs[0], 3);
  }, 
  function(error) {
    console.log("Could not enable WebMidi.");
  });

</script>
</body>
</html>

What am I missing?

time parameter doesn't send outputs

works:

output.playNote("C2", 1, {time: WebMidi.time});

doesn't work:

output.playNote("C2", 1, {time: WebMidi.time + 1000});

how to play several notes one after another? right now only the first one plays.

not receiving initial connected event for an output port

I have a MIDI controller which happens to also posses an output port for configuration.

When I enable WebMidi I only receive a connected event for the input port. Subsequently disconnecting the device, I do received disconnected events for input & output, and again receive both when I reconnect.

Following is logging of WebMidi events.

[enable WebMidi with device already connected]
{timestamp: 74.58000000000001, type: "connected", id: "-1075253572", manufacturer: "AKAI", name: "MPKmini2", …}id: "-1075253572"input: Input {_userHandlers: {…}, _midiInput: MIDIInput, …}manufacturer: "AKAI"name: "MPKmini2"timestamp: 74.58000000000001type: "connected"__proto__: Object

[disconnect device]
{timestamp: 2325.8300000000004, type: "disconnected", id: "-1075253572", manufacturer: "AKAI", name: "MPKmini2"}id: "-1075253572"manufacturer: "AKAI"name: "MPKmini2"timestamp: 2325.8300000000004type: "disconnected"__proto__: Object
{timestamp: 2327.4900000000002, type: "disconnected", id: "898669612", manufacturer: "AKAI", name: "MPKmini2"}id: "898669612"manufacturer: "AKAI"name: "MPKmini2"timestamp: 2327.4900000000002type: "disconnected"__proto__: Object

[reconnect device]
{timestamp: 39933.12, type: "connected", id: "898669612", manufacturer: "AKAI", name: "MPKmini2", …}
{timestamp: 39934.82, type: "connected", id: "-1075253572", manufacturer: "AKAI", name: "MPKmini2", …}

Port statechange events?

Is that TODO in reference to a listener for MIDI inputs and outputs coming online and offline? Working on a project using that lib and would be interested in contributing.

connect to the bluetooth

When I use the Macbook to conect the bluetooth MIDI, then I open the browser and connect the webmidi.
Just like the code below:
function Connect(){
WebMidi.enable(function (err) {
if (err) {
console.log("WebMidi could not be enabled.", err);
} else {
console.log(WebMidi.sysexEnabled);
output = WebMidi.outputs[0];
......
Finally,I had connected the bluetooth device successfully. Also I could communicate wite the bluetooth device by use the Webmidi.js. However, when I send a Sysex messsge or a Note on or Note off message to the bluetooth device. And the I found the message send out pass through the bluetooth adapter will insert an unanticipated message code.
Just like : if i send a Sysex message [0xf0 0x01 0x02 0x03 0xf7], Actually i will receive hte message is [0xf0 0x01 0x02 0x03 0xfa 0xf7] or [0xf0 0x01 0x02 0x03 0xfc 0xf7] or others;

For more information, please check my source code:https://github.com/Wingoc/BLE_USBMIDI
Thank you.

Make "Middle C" configurable/transposable

The concept of "Middle C" in MIDI is a mess. Various manufacturers treat it differently, placing it at C3, C4 or C5. The MIDI standard does not address this.

To make it easier to transition from one environment to another, WebMidi.js should allow the user to transpose MIDI note numbers to match what they require.

Here are some references on the subject:

I'm scheduling this for a later release. If you think it's worhwhile, give it a thumbs up. This will give me an idea of how much people need it.

Add 'all' note option to Output.prototype.stopNote

The first param to Output.prototype.stopNote is a note number or name. It would be convenient to have an all option which effectively would be the same as

output.stopNote([0, 1, 2, ..., 127]);

The all option is used elsewhere for channels, so it would feel consistent.

This option would be useful when you've got yourself into a mess with lots of notes on and need to switch them off, perhaps due to buggy code.

If you like the idea, I'm happy to implement and submit a pull request.

Firefox v52+

Hi!
Just wanted to mention that the current version of WebMIDIAPIShim does not work in Firefox v.52+.
Though there is a jazz-midi extension for Firefox, it's API is different from Jazz-Plugin and it will require quite a lot of JavaScript coding for the workaround. You can see some of that code in JZZ.js

Detecting chords using WebMIDI

I have a general question. How would you detect a chord using WebMIDI? From what I read in the API docs, you can use the noteon for single note/key events. If I want to detect a chord event, say when 3 or more notes are played together. Do I have to detect separate events for each note? Any suggestions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.