日本語を Max6 から Processing に OSC 経由で送る際の文字化けについて

oscP5-1

Max6 は文字コードのエンコーディングに UTF-8 を、Processing は内部的には Java なので UTF-16 を用いているのではと推測されます。そのため Processing 向けのoscP5は、Max6から受け取った UTF-8 の日本語バイト列を toString() すると、UTF-16 として解釈して文字化けしてしまいます(たぶん)。OscMessage や OscArgument のクラスなどひと通りみたのですが、エンコーディングに関するメソッドが見当たりませんでした。

そこで対策ですが、Max6 から受け取った OscMessage の Byte 列を一旦 UTF-8 として String に変換すれば問題が無くなりました。そんなに検証してないので問題あったら教えて欲しいっす!

[java]
void oscEvent(OscMessage theOscMessage) {

//このprintでは日本語の文字化けが確認される。
theOscMessage.print();

//OSCをByte列として取得
byte[] bytes = theOscMessage.getBytes();

try {

//Byte列をUTF-8として解釈
String str = new String(bytes, "UTF-8");

//Addrpatternとtypetagを削除する
String typeTagStr = theOscMessage.typetag();
str = str.substring(str.indexOf(typeTagStr) + typeTagStr.length());

//コンソールにMax6から送った日本語のメッセージが表示される
println("String:"+str);

}
catch(UnsupportedEncodingException e) {

e.printStackTrace();

};

}
}
[/java]

Max SDK のサンプルプロジェクトから External Object を作成:Max/MSP, Max SDK, C

Max/MSPを使ったアプリケーションを実装する際に、音に関して非リアルタイム && 1sample毎に信号処理したい(例えば、読み込んだ音声波形を再生する前にグリッチしたり、音のアタック部分だけを分析したりといった事。)欲求が高まってきました。期待をいだいて GEN や Max in JavaScript に手をだしたんですが、それらでは不可能だったので遂にMax SDKに手を出し始めましたよ!

これからMax SDKを使ったエクスターナルオブジェクト作成について書いてみたいと思います。ちなみにMac OS 10.8 / Xcode 4 の環境でやります。またJavaじゃなくてC言語なのは、少し前にArduinoをやってC言語を勉強したからです。

準備

SDKのダウンロード先 →  Max SDK

ダウンロードしたフォルダ MaxSDK-6.0.4を適当な場所に置きます。自分は /Document/Max 以下に置きました。Maxのサーチパス下に置くとコンパイルしたオブジェクトをMaxが認識してくれるので都合がいいです。

Xcodeプロジェクトを開く

/MaxSDK-6.0.4/examples/basics/ 以下にサンプルプロジェクト(*.xcodeproj)がいくつか入っているので、例えばsimplemax.xcodeproj 開いてみると、Xcodeが立ち上がります。

.xcconfig の修正

スクリーンショット 2013-01-25 4.18.32

このままだとコンパイルが通らないので、/MaxSDK-6.0.4/maxmspsdk.xcconfig の33,34行目を

[javascript]
SDKROOT = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk
MACOSX_DEPLOYMENT_TARGET = 10.8
[/javascript]

へと変更します。Mountain Lionには10.6のSDKが入ってないためです。

コンパイル

左上の三角ボタンを押して、コンパイルが完了です。/MaxSDK-6.0.4/sdk-build 以下に simplemax.mxo が作成されている事が確認できます。

Max6を起動

スクリーンショット 2013-01-25 4.23.19

/MaxSDK-6.0.4/sdk-buildフォルダがMaxのサーチパス内に入っていれば、Max6を起動し、simplemaxオブジェクトをインスタンス化する事が出来ます。すでにMaxが起動していた場合は、一旦Max.appを落としてから起動しなおしてください。せっかく作ったこのsimplemaxオブジェクト、実は何も入力を受け付けないオブジェクトなので、何もできないです。

/example 以下には、沢山のサンプルプロジェクトがあるので色々試して見てください。ちなみに全てのサンプルプロジェクトにヘルプパッチ(*.maxhelp)が付いているので、パッチの説明・使用例が見られます。

まとめ

今回は、Max SDK をダウンロードして、Xcodeにてサンプルプロジェクトのコンパイルを行ない、External Objectの作成を行ないました。

補足

プロジェクトフォルダ内になる *.def と *.vcproj は、Win用の開発環境であるVisual Studio 用のファイルのようですので、Macの方は気にしなくて良いようです。

“use strict” が有効であるかを確認:Max/MSP, JavaScript

スクリーンショット 2012-12-27 4.38.18

ECMAScript 5 で導入されている “use strict” / strict モードは、JavaScript の機能を制限する代わりにエラーチェック機能やらセキュリティが提供されるモードとの事です。機能の1例としては、var を付けないで変数を宣言するとエラーがでます。というわけで早速 Max6 で “use strict” が使えるか調べてみました。

コード

[javascript]

"use strict"
autowatch = 1;

//strictモードが有効である場合
//関数内ではthisがundefinedになる。

//以下の関数は即時関数であり、宣言時に一度実行され
//結果がhasStrictModeに代入される

var hasStrictMode = (function () {
"use strict";
return this === undefined
}());

function bang() {

//trueが出力され"use strict"が有効である事が確認できる
post("hasStrictMode:" + hasStrictMode);
value = hasStrictMode; //JavaScript Referenceエラーが発生
outlet(0, value); //出力はされない
};

[/javascript]

結果 – Max6で”use strict” は利用可能

実行結果の画像を見ると hasStrictMode : true が出力されており、”use strict” が利用可能である事が確認できます。 var を付けてない value を利用しようとした所で、ちゃんとエラーがでてプログラムが止まっています。加えて、strict モードでない場合も試したのですが、1が出力される事を確認しました。

参考資料

  • JavaScript 第6版 – hasStrictMode のコードは p.117 5.7.3 “use strict” 文より利用させて頂きました。

ファイル冒頭で宣言したプロパティのスコープ:Max/MSP, JavaScript

スクリーンショット 2012-12-26 11.45.35

JavaScriptに関する本を読んでいると、”プロパティや関数の宣言は関数で閉じ込めないとグローバルのスコープになっちゃうよ”という注意がいたるところに書いてあります。Max6のJavaScriptを書く時に、ファイルの冒頭で変数宣言してたので、それってパッチを複数使う場合に変数が共有されて問題になりそうだなと思ったので、同じ簡単に調べてみました。

コード

GlobalTest.js

[javascript]

var value; //var 付きでプロパティを宣言しているので、スコープはファイル内

function set(num){

value = num;
outlet(0,value);
}

[/javascript]

GlobalTest2.js

[javascript]

value;
//var 無しでプロパティ宣言をしているので、スコープはグローバル

function bang(){

outlet(0,value);
}

function set(num){

value = num;
outlet(0,value);

}

[/javascript]

テスト

まず左側のNumber Box に909 → Bang としても 右下のメッセージには 909 は入りませんでした。これで var 宣言した GlobalTest.js の value プロパティはファイル間で共有されて無い事がわかります。

加えて GlobalTest.js パッチを復数使っても、それぞれ別の値が出力されたので、var 宣言したプロパティのスコープはファイル内である事が確認できました。

続いて左側のNumber Boxに909 右側のNumber Boxに303と入れた後に、右側のBangを押しました。上記画像が結果です。GlobalTest2.js の出力は、二つとも 303 と同じ出力を行なっており、プロパティ value が共有されている事がわかります。これは var 無しで宣言した value プロパティが二つのファイル間で共有されている、つまりグローバルオブジェクトのプロパティになっている事が理解できます。

※JavaScriptに慣れて無いこともあり、確認漏れなどあったら、教えて頂けると幸いです。

結論

ファイルの冒頭で

  • var を付けて宣言すれば、スコープはファイル内になる。
  • var を付けないで宣言すれば、スコープはグローバルオブジェクトになる。

参考図書

JavaScriptパターン――優れたアプリケーションのための作法

message を送る時の注意点:Max/MSP,JavaScript

スクリーンショット 2012-12-24 22.17.40

メリークリスマス!JavaScriptからmessageを送る時に、微妙にハマった事をメモしておきます。

あるパッチオブジェクトにメッセージを送っていたんですが、どうも反応しない。調べてみると、Listで送らなきゃいけない所、Stringで送っていました。Stringでmessageを送った場合は、messageの始点と終点に引用符が付きます。注意したいポイントです。

加えて、JavaScriptでListを作る場合は、Arrayを利用すればOKでした。

[javascript]

inlets = 1;
outlets = 2;
autowatch = 1;

function sendMessage(){

var messageList = [1,2,3];
outlet(0,messageList);

var messageString = "1 " + "2 " + "3";
outlet(1,messageString);
}

[/javascript]