Node.jsでMIDI

node-midiをWindows10にインストールします。node-midiの説明はnpmjs.comにあります。nodeがインストールされているパソコンであれば、以下のコマンドでインストールできます。ただし、node-midiのインストールは環境にセンシティブで、かなりの確率でエラーになります。


> npm install midi

そんなときは、nodeとnodistをアンインストールし、再度Node.jsを、nodejs.orgからダウンロードし、インストールするのがもっとも簡単です。

このページの下に、私がnode-midiをインストールした時に遭遇したエラーと、もしかすると解決できるかもしれない、と試した方法を書いておきます。成功したとしても、非常に限定的でオールマイティな方法ではありません。

MIDIの受信

まず、midiのモジュールを読み込みます。下のプログラムではPCに接続されているMIDIデバイスをリストアップします。

// モジュールを読む
const midi = require('midi');

// MIDI入力のオブジェクトを生成
const input = new midi.Input();

// MIDIの受信ポートがいくつあるかを調べる
n_in=input.getPortCount();
 
// それぞれのポートの名前を表示する
for(var i=0; i<n_in; i++){
	console.log("IN",i,":",input.getPortName(i));
}

私の場合、以下のように2つのポートが表示しました。

IN 0 : nanoKEY2 0
IN 1 : eVY1 MIDI 1

すでにMIDI入力オブジェクト(input)が生成されているとします。MIDIを受信するにはどのポートから受信するかを指定します。その上で、MIDIを受信した時のコールバック関数を指定します。

// MIDIを受信するポートを指定。この場合はゼロ番
input.openPort(0);

// MIDIを受け取った時のコールバック関数
input.on('message', (deltaTime, message) => {

	let status = message[0];
	let data1  = message[1];
	let data2  = message[2];

	console.log(status.toString(16),data1.toString(16),data2.toString(16));

	switch(status){
		case 0x80:
			console.log("Note Off");
			break;
		case 0x90:
			console.log("Note On");
			break;
		case 0xA0:
			console.log("Poly Pressure");
			break;
		case 0xB0:
			console.log("Control Change");
			break;
		case 0xC0:
			console.log("Program Change");
			break;
		case 0xD0:
			console.log("Channel Pressure");
			break;
		case 0xE0:
			console.log("Pitch Bend");
			break;
		default:
			break;
	}
});

MIDIの送信

midiのモジュールを読み込みます。MIDIの受信で既にmidiモジュールが読み込まれていれば、再読み込みは必要ありません。下のプログラムではPCに接続されているMIDIデバイスをリストアップします。


// モジュールを読む
const midi = require('midi');

// MIDI出力のオブジェクトを生成
const output = new midi.Output();

// MIDIの送信ポートがいくつあるかを調べる
n_out=output.getPortCount();

// それぞれのポートの名前を表示する
for(var i=0; i<n_out; i++){
	console.log("OUT",i,":",output.getPortName(i));
}

私の場合、以下のように3つのポートが表示しました。

OUT 0 : Microsoft GS Wavetable Synth 0
OUT 1 : nanoKEY2 1
OUT 2 : eVY1 MIDI 2

MIDIを送信するには、どのポートに送信するのかを指定します。


// MIDIを送信するポートを指定。この場合はゼロ番
output.openPort(0);
 
// Note On メッセージを送信
output.sendMessage([0x90,0x40,0x70]);

// 1秒後にNote Offメッセージを送信
setTimeout(function() {
	output.sendMessage([0x80,0x40,0x00]);
}, 1000);
私の環境

midiモジュールをインストールした私の環境を記載しておきます。PythonとVisual StudioのBuild Toolは必須です。

  • Windows 10 Home 1909
  • node v14.15.1
  • npm 6.14.8
  • Python 3.9.0
  • Visual Studio Build Tool 2017
npm installのエラー

「cb.apply is not a function」はやたら出合います。

npm ERR! Windows_NT 10.0.18363
npm ERR! argv "C:\\Program Files\\Nodist\\v\\14.15.1\\node.exe" "C:\\Program Files\\Nodist\\npmv\\4.0.5\\bin\\npm-cli.js" "-g" "install" "npm"
npm ERR! node v14.15.1
npm ERR! npm  v4.0.5

npm ERR! cb.apply is not a function
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\mikata\npm-debug.log

「gyp ERR! stack Error: `gyp` failed with exit code: 1」node-gypで起こるエラーのようです。

    versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
KeyError: '2017'
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onCpExit (C:\Program Files\Nodist\npmv\4.0.5\node_modules\node-gyp\lib\configure.js:305:16)
gyp ERR! stack     at ChildProcess.emit (events.js:180:13)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:209:12)
gyp ERR! System Windows_NT 10.0.18363
gyp ERR! command "C:\\Program Files\\Nodist\\v\\9.11.2\\node.exe" "C:\\Program Files\\Nodist\\npmv\\4.0.5\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
gyp ERR! cwd C:\Users\mikata\node_modules\midi
gyp ERR! node -v v9.11.2
gyp ERR! node-gyp -v v3.4.0
gyp ERR! not ok
npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\mikata\package.json'
npm WARN mikata No description
npm WARN mikata No repository field.
npm WARN mikata No README data
npm WARN mikata No license field.
npm ERR! Windows_NT 10.0.18363
npm ERR! argv "C:\\Program Files\\Nodist\\v\\9.11.2\\node.exe" "C:\\Program Files\\Nodist\\npmv\\4.0.5\\bin\\npm-cli.js" "install" "midi"
npm ERR! node v9.11.2
npm ERR! npm  v4.0.5
npm ERR! code ELIFECYCLE

npm ERR! midi@1.0.0 install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the midi@1.0.0 install script 'node-gyp rebuild'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the midi package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node-gyp rebuild
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs midi
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls midi
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\mikata\npm-debug.log

こちらは、たぶん32ビット環境でnodist 0.9.xを使おうとした時に発生するエラーです。

MSBUILD : error MSB4132: ツール バージョン "2.0" が認識されません。使用可能なツール バージョンは "4.0" です。


エラーに対する対応

プロキシ>自動プロキシセットアップ>設定を自動的に検出する、をオフにします。npm ERR! cb.apply is not a functionが解決する場合があります。

npmを更新します。npmのバージョンはnpm -vでチェックできます。

> npm install -g npm
> npm install -g npm@latest

ただし、nodistでインストールしたnodeでは上のコマンドでnpmが更新できない場合があります。この場合は以下のコマンドを試してみてください。

> nodist npm global match

Python 2.7.xもしくは、Python 3.x.xをインストールします。インストールされているPythonのバージョンをnpmのconfigに設定します。python.exeのパスを設定せよ、との記載もありました。どちらが良いのかわかりません。

> npm config set python python2.7
or
> npm config set python c:\python27\python.exe

visual studio build toolをインストールします。2013, 2015, 2017, 2019 いずれのバージョンをインストールするかはnodeのバージョンと関係しているようです。Build Tools for Visual Studio 2017 (version 15.9)が無難かと思います。インストールされているVisual Studioのバージョンをnpm configに設定します。

> npm config set msvs_version 2017

npmのconfigをチェックするには、次のコマンドを使います。

> npm config list

また、npmのconfigの編集は次のコマンドでできます。

> npm config edit
成功した手順

nodistを使って、midiモジュールをインストールが成功した手順を書いておきます。PythonとVisual Studioは既にインストールされているものとします。nodistは0.8.8をインストールしています。

> nodist add 9.11.2
> nodist use 9.11.2
> npm install node-gyp@latest
> npm install npm@latest
> nodist npm (global) match
> npm config set python c:\python27\python.exe
> npm config set msvs_version 2017
> npm -v
5.6.0
> npm install midi
npmのエラー

nodistで作業していると、突然npmがエラーになることがあります。エラーは2通りあります。

> npm -v
Sorry, there's a problem with nodist. Couldn't resolve npm version spec match : Couldn't find any matching version

この場合は、npmのバージョンが合わないと言っているので、以下のコマンドで修復できる可能性があります。

> nodist npm (global) match

上のコマンドで、何もインストールが開始しないことがあります。その時は該当のバージョンのnpmをディレクトリごと削除します。nodistのnpmは次のフォルダに保存されています。

> C:\Program Files\Nodist\npmv のディレクトリ

2020/12/11  07:26    <DIR>          .
2020/12/11  07:26    <DIR>          ..
2020/12/11  07:26    <DIR>          3.10.10
2020/12/06  20:36    <DIR>          5.6.0
2020/12/06  20:56    <DIR>          6.14.8
2020/12/06  20:49    <DIR>          6.7.0

もう一つのエラーは以下です。

> npm -v
internal/modules/cjs/loader.js:582
    throw err;
    ^
Error: Cannot find module 'C:\Program Files\Nodist\npmv\6.7.0\bin\npm-cli.js' 

この場合の快活策は、こちらの記事を参考にさせていただきました。なぜこのような状況になるのかわかりません。

  • C:\Program Files\Nodist\npmv\6.7.0を削除
  • C:\Program Files\Nodist\Nodist\lib\npm.jsというファイルを開き、127行目を修正

修正前

/**
 * Get a download URL for the version
 * @param {string} version
 * @return {string}
 */
NPMIST.downloadUrl = function(version){
    return 'https://codeload.github.com/npm/npm/tar.gz/vVERSION'          
    .replace('VERSION',version.replace('v',''));
};

修正後

/**
 * Get a download URL for the version
 * @param {string} version
 * @return {string}
 */
NPMIST.downloadUrl = function(version){
  return 'https://codeload.github.com/npm/cli/tar.gz/vVERSION'
    .replace('VERSION',version.replace('v',''));
};