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

UniOSCとMaxを使ったOSCの送受信 #Max7 #Unity #OSC

UniOSC購入&起動

UniOSCをUnity Asset Storeで購入し、UniOSC.Mobile Sceneを起動します。

iOSアプリをインストール

Build SettingをiOSにし、Xcodeでビルドインストールします。iPhone6sで実行すると画面レイアウトが崩れますが、とりあえず気にしなければテストはできます。また私の環境だとなぜかIPアドレスがおかしい値になっています。が気にしなくても動きました。OSC OUT側のIPアドレスはMaxが動作しているMacやPCのIPを入力しておきます。

MaxでOSCのRecieve Sendパッチ作成

Max側は、OSCを送受信ですがUDPのオブジェクト使って準備しました。udpsendのIPアドレスにはiPhoneの設定画面で確認したIPアドレスを入力しておきます。また送信側のメッセージにはOSCのフォーマットに合うようにスラッシュをprependしておきます。(そうじゃないと確認できない。)

通信確認

MaxのSender側のスライダーを動かすと、UniOSC appのTraceに受け取れた事が表示されます。逆にUniOSC app側のSendボタンを押せば、Max側で受信を確認できました。

正確なメトロノーム #max7

揺れの少ない正確なメトロノームをつくりたい〜

スクリーンショット 2016-08-22 1.24.24

Maxの標準のmetroは精度が悪いと言われております。計測したわけでは無いですが16部音符で再生すると結構気になるくらいグルーヴ感があるようです。より正確なメトロノームを生成するにはMSPを使うのが良いとの事で以前某楽器メーカーの方に教わった方法を実装してみました。

サンプル


----------begin_max5_patcher----------
746.3ocyWkjaaCCEcs7oPfqcBDE0XAZuHEEAzRzNL0hxkjx0NAw.EdSW0yPG
1UfbAJxsQ.sWiJRY033JWKKGolMhfeyg26y2ev2Lv.LJcAQ.Leg4qMMLtYfg
g1jxfwl4FfD7hnoXgdY.F48oitBLr7mjjERsYbrPhkYBSI9sjz4Dd0JXYIoY
xoDod61arNCKitjxlbAmDIKudD7bqglNt5AnkqZv19bKy2rYOkGib4LR4F.f
gl.JqX6UqfFqwRA9Nyaq6mx185ExkS0mB.nLb6fApOCOMWvzTbbBQHLg0yc3
g3NJHTM3a2.pWGmgN0RZ3SBokoSlTr81wLGXflSNUe+C7mg43DhjvufvviJw
m09X89drgnNj3GRvqD6wb5bxQq3gtVORxGdZRd+NTxGkljPJt2c8B+7tu8qu
9i7O7870eIe8GyWeW95Oku9970etd2g09cG1taoQJCEPnsbFiSYxw3Hx1OsJ
aB50Za5c9WdE2NTZPtNFGs5nIJzBo4XXP4ye02Zk1+Oyi4wN53cHzWQm.cNr
.2VlIyo+imO4r2kTt0Iu8r6eN+pWtxz57VxWaWzCx2+MgEzIL7zZoMJr+E3m
oXsaaossNosG5zncP+SaR7DxpV1V1l7wNNGl0ivrIpxT5wZ4t+y01Tf1gcYa
JHu9ODe1kXQJeUqxkuwo3qE79gmlf2oCE7ixjxz1xOjMZOO50KsqsJcXG9xh
kRdFs5BTyzlGyIuKivhVdz7N.ssX2psUrZSS25yALkx18Ocpgox9icDhzLdT
EJpZ027AjFSDRJCKoEO+OrHuGslKowwD11QrwTgJHVSEqZeQdRgie+AGmF.m
cvbWhGTSvipVXegml.Gm9CNdOyvieSjOg8GdBZh+oGwSXSvS+Et2nnqdCMp+
AyggSayMWV4.Oa1bBWr4L0PonX4Uo5Rh9C0Sorxo5dK.bxbZ05czVv7hBhxh
pgY7xBTK7JaNAjjFS3rhZsp5XCT27sC9MfZHW6C
-----------end_max5_patcher-----------

入力したテキストを先頭から1文字・2文字・・・と増やしながら出力するJSオブジェクト #max7

[code]
"use_strict";
var tsk = new Task(repeater_function, this);
var s = "";

function text(val){

s = val;
var length = s.length;

tsk.cancel();
tsk.interval = 200;
tsk.repeat(length);
}

function repeater_function()
{
var index = tsk.iterations;
outlet(0,s.slice(0,index));
}

[/code]

HSL to RGB 変換 JS オブジェクト #max7

JSオブジェクト用コード

[code]
function rgbToHsl(r, g, b){

r /= 255, g /= 255, b /= 255;

var max = Math.max(r, g, b), min = Math.min(r, g, b);

var h, s, l = (max + min) / 2;

if(max == min){
h = s = 0; // achromatic
}else{
var d = max – min;
s = l > 0.5 ? d / (2 – max – min) : d / (max + min);
switch(max){
case r: h = (g – b) / d + (g < b ? 6 : 0); break;
case g: h = (b – r) / d + 2; break;
case b: h = (r – g) / d + 4; break;
}
h /= 6;
}
outlet(0, h, s, l);
}

function hslToRgb(h, s, l){
var r, g, b;

if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1; if(t > 1) t -= 1;
if(t < 1/6) return p + (q – p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q – p) * (2/3 – t) * 6;
return p;
}

var q = l < 0.5 ? l * (1 + s) : l + s – l * s;
var p = 2 * l – q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h – 1/3);
}
r = Math.round(r*255);
g = Math.round(g*255);
b = Math.round(b*255);
outlet(0,r, g, b);
}
[/code]

引用元

RGB to HSL conversion