Node for Max 上で tonal ライブラリを利用して Key Scaler を試作 #max8 #n4m

Midi NoteのPitchを特定のスケールに矯正

cycling’74のN4Mサンプルにも入っていた tonal をnode objectで使ってみたのでメモです。

鍵盤の音を特定のスケール(とりあえずC Major)に矯正するスクリプトとなっております。Node for Maxのご参考にどうぞ。

tonal.js

引用 “tonal is a music theory library. Contains functions to manipulate tonal elements of music (note, intervals, chords, scales, modes, keys). It deals with abstractions (not actual music or sound).

tonal is implemented in Typescript and published as a collection of Javascript npm packages.

It uses a functional programing style: all functions are pure, there is no data mutation, and entities are represented by data structures instead of objects.”

https://github.com/tonaljs/tonal ※導入方法はこちら参照

keyscaler.js


const MAX_API = require("max-api");
const { Scale } = require("@tonaljs/tonal");
const { Key } = require("@tonaljs/tonal");
const { Mode } = require("@tonaljs/tonal");
const { Midi } = require("@tonaljs/tonal");
const { Note } = require("@tonaljs/tonal");
const { Chord } = require("@tonaljs/tonal");

const notes = Scale.get("C major").notes;
console.log("notes:"+notes);

let midiNotes = notes.map((value) => {
    return Note.midi(value+"0")
});
console.log("midiNotes:"+midiNotes);

const handlers = {
    "getScaledPitch" : (pitch) => {

        let returnPitch = pitch;

        while(
            midiNotes.every(value => {
                return ((value % 12) != (returnPitch % 12))
            })   
        ){
            returnPitch++;            
        };

        //MAX_API.post(pitch + "->" + returnPitch);

        MAX_API.outlet(returnPitch);  
    },
    /*
    [maxAPI.MESSAGE_TYPES.BANG] : () =>{
        console.log("bang");
    },
    */
};

MAX_API.addHandlers(handlers);

Node for Max を用いて、定形外のUDPデータを受信 #Max8 #n4m

Maxの生命線UDPで問題が・・・

他のアプリを繋いでくれる updreceive

センシングや3D(Unity / UE / Arduino) 等とのコミュニケーション時に重宝するudprecieve ですが、udpを受信する場合に、メッセージが4bytesに揃っていなかったり長すぎた場合にアトリビュートなどの設定やOSC-routeを利用しても上手く受信できない事があります。

OSC Bad message name string: DataAfterAlignedString: Unreasonably long string Dropping entire message. / OSC packet size not a multiple of 4 byte dropping.

Max内にどうにかする方法としてNode for Maxが利用できます。

Node for Max で UDP receive

node object は、とりあえずHelpからコピペでOK

node.script objectjs をHelpからコピペし、ダブルクリックするとテキストエディターが開くので書き換えます。Maxのテキストエディタはクソなので、VS Code使ってます。

udpreceive.js

const dgram = require('dgram');
const IP = '192.168.1.1';
const PORT = 8888;
const socket = dgram.createSocket('udp4');
socket.on('listening', () => {
    const address = socket.address();
    console.log('UDP socket listening on ' + address.address + ":" + address.port);
});
socket.on('message', (message, remote) => {
    console.log(remote.address + ':' + remote.port +' - ' + message);
	/*
		処理
	*/
});
socket.bind(PORT, IP);

とくに外部ライブラリを入れる事なくできました!JS的に正しい書き方なのかは謎。外部ライブラリのOSC-routeなどを使わなくても、テキスト処理はスクリプト言語の十八番でしょうから楽ちんです。

感想

昔、VJソフトのあのタグをつくるためにMaxのjs objectを触っていた頃は、jsの文法を読んで型なしでプロトタイプ継承とか難しいなと思い、深入りしませんでした。時は経ち最近のjsは今どきな文法が色々あって使いやすくなってそうです。

Node.jsやnpmエコシステムなどでは当たり前の事が、Maxおじさんからすると凄いみたいな事は非常に沢山ありそうです。(Blogを適当に放置してる事から分かるように)今までネットワーク / スクリプト言語は触れないように生きてきましたが、そろそろNode.jsから色々触ってみようかなと思いました。

Reference