kiyasuの日記

ハッピーうれピーよろしく哀愁

Daito Manabe + Satoshi Horii phenomena

mutek.org

これのアーカイブをシアター上映していたので見てきました。いやーよかったです。ただパルスやアクセントに合わせて映像を動かすのではなく、素材となっているCGの形状、動き、カメラワークに必然性があり、音楽の印象を増幅させているようでした。

max summer school 2019でとても印象に残っている講義がありました。Jean-Marc Pelletier先生によるjitterの講義で、「黒い平面状を光点がランダムに移動するが、移動に連動して音も自動生成させたい。どのようにすれば良いか」という課題を扱ったものでした。

文化的背景が共通でなくても上に行くと高い音、下に行くと低い音という挙動に人は安心感・納得感を覚えるとか、ただ上下を正確に音に反映すると蚊の羽音のような不快なものになるから細かい挙動はフィルタリングするとか、そういった「音と映像の必然性のある関係を考える」というのがひとつのトピックで、これが僕はすごく印象に残ってました。

このアーカイブでみたVJはまさにそんな必然性のある映像だったなーと。説明するのは難しいんですが、不定期なパキンパキンとしたパルスに合わせて尖った宝石のようなオブジェクトが勢いよく突き刺さる。流れるようなシンセの音と、しなやかな女性の肩を思わせるワイヤーフレームがマリアージュする。などなど。低音と連動する箱は画面下部に、高音の箱は上部に配置される。

映像に必然性があると音楽への没入感が段違いですね。これは面白かったなあ。


mutekアーカイブが面白かったので週末のこれも見ました。

これも面白かった。配信内で紹介されたm4lデバイス、試してみよう。

cclab.sfc.keio.ac.jp

ROLI SEABOARD BLOCKをMax(for Live)で扱う

MaxとMax for Live

Max for Liveはmidiバイスの選択に制限がかかっています。

cycling74.com

そのためmax for liveではableton live経由で入ってきたmidiトラックを利用することになります。具体的にはAbleton LivemidiトラックにMax for Live/Max Instrumentを作成し、その中のmidiinオブジェクトからデータを取ってくる、ということですね。

ableton liveが新しい11でのMPE対応と対応デバイスを挙げてましたがそのなかにMax for Liveが入っておらず、この方法で大丈夫かな?と心配でした。

f:id:mojo_nobu:20210220182416p:plain

が、データ見ると入っているようです。midiキーボードから入力されたデータをフィルタリングなどせずMax for Liveに投げている、みたいな感じでしょうか。うーん、でもそれってこれまでも純正デバイス以外は普通に対応できてたってことにならんかね?11ではmidiクリップがmpe形式で保存できるようになるのかしらん。

MPEとして扱う

ともかくMaxをSEABOARDを使ってみましょう。

maxはmidiバイス選択で、Max for Liveは上記の方法で[midiin]オブジェクトからmidiデータを引っ張ってきます。以下、スクショは全てMax for Liveです。

[mpeparse]オブジェクトを作り、そのリファレンスからごっそりコピペで持ってきましょう。MPEに関してはこれで事足りるかと思います。

f:id:mojo_nobu:20210220183517p:plain

使う時は以下を参考にMPEの用語とSEABOARDの操作のすり合わせをしましょう。

Max tutorial: Receiving and displaying the Seaboard's MPE data : ROLI Support

Strike is transmitted as Velocity Press is transmitted as Aftertouch Glide is transmitted as Pitch Bend Slide is transmitted as CC 74 Lift as Release Velocity Data from the Preset Shift buttons or SoundDial is transmitted as Program Change data

マルチタッチデバイスとして扱う

単にMPEの入力装置として扱うだけではなく、MaxはSEABOARDを押し込み機能を持ったマルチタッチデバイスとしてそのデータを取得することができます。

BLOCKS用のパッケージを取得

Maxのパッケージマネージャーで配布されているこちらを取得します。

cycling74.com

maxのメニューからFile/Show Package Managerを選択して「BLOCKS」などと検索して取得します。

f:id:mojo_nobu:20210220165128p:plain

パッチ内でこれで[blocks.*]オブジェクトが使えるようになりました。では使ってみましょう。パッチ内に新規オブジェクトとして[blocks.seaboard]を作ってみましょう。

f:id:mojo_nobu:20210220170018j:plain

続いてエディットモードに入ってalt押したままseaboardの画像をクリックしてリファレンスを見てみましょう。

f:id:mojo_nobu:20210220170140p:plain

タッチのインデックスも取れてるし、多分これで大体のことはできる。

展望

あとはMPE対応音源をあさったり、対応してない音源でもマルチタッチ情報を使ってウネウネ操作してみたりしようと思います。

MRAL(仮)のはなし

先日こういう動画をアップしました。

www.youtube.com

HoloLens2からMax経由でAbletonLiveのセッションビューを再生、録音できるようになりました。これでMixedReality作曲できる!

#HoloLens2​
#AbletonLive​
#maxforlive​
#maxmsp

仮ですがアプリ名はMRAL(Mixed Reality Ableton Live)です。このアプリについての説明と展望を書いておこうかと思います。

どういうアプリか

作曲ソフト、Ableton LiveのセッションビューをHoloLens2のMR空間から操作できるようになるアプリです。

Ableton LiveとMax

Ableton LiveはMax(名前がいろんなものと被るので一般的にはMax8やMax/Mspと呼ばれたりする)というプログラミング環境を使って作曲に使うエフェクトやプラグインを作ることができるのですが、MaxはLOM(Live Object Model)というAPIを使ってAbleton Live自体の情報を取得することもできます。Live上で現在どのクリップが再生されているのか取得したり、Liveに対して「特定のトラックで新規録音を開始させる」などの命令を送ることもできます。

MaxとHoloLens(Unity)

Maxはプログラミング環境としてUDPやOSCの送受信の機能を備えているので、これを使ってHoloLensアプリと通信を行います。HoloLensアプリはUnityで作ってます。

図にするとこんな感じです。

f:id:mojo_nobu:20210214204100p:plain
システム図

難しかった(現在進行形で難しい)ところ

Maxがとにかく曲者でした。ノードの中に流れるシーケンシャルなデータを逐次処理していく、というのが普通のプログラミングと違っていて慣れるまで大変でした。C#だと工場のオートメーションのところがMaxだと流しそうめんみたいな。データをプールするような作りになっていないというか。

Maxはちょくちょく触っていたんですが、久しぶりに触ると感覚も忘れてしまうので、定期的に触らなければ・・・という思いを強くしました。慣れると自分に必要なオブジェクトがわかってきて、それを探して使っていくのが面白いです。

あとは一連の処理の末端に複数のsendがあった場合その後のreceiveの実行順は未定義らしいとかあって、全体的に何かしらロジックを組むような用途には向いてないのかなという感触でした。Maxが悪いんじゃなく僕の使い方、アプローチが何か間違ってるのかも、という話です。シューゲイザーのエフェクト構成でクラシックを弾くんじゃない、みたいな。

それこそgenとか使えば良かったのかもしれない。今後の課題。

このアプリで何が嬉しいか

今のところ特にないんですよね。

実はこのプロジェクト自体は結構長くて、1年半くらい前にこういうのを作りました。

youtu.be

Ableton Liveにはclipのon/offを切り替えて曲の構造を変えながら作曲していくセッションビュー という機能があるんですが、それをHoloLensで叩く。スマホARでは手がふさがる、VRでは楽器が見えない、ということで考えたアプリです。 これで楽器を弾く手を止めることなく、曲の展開をどんどん変えていけるようになりました。

このときは「MRにより実空間での場所を取らないから嬉しい」「演奏の手を止めずにLiveを操作できるから嬉しい」そのあたりを考えていたんだと思います。しかし、

果たしてそうだろうか・・・?

あまりにも特定のシーンに限定しすぎではないか・・・?

演奏中に視線(正確にはhead gaze)でclip選択は難しすぎないか・・・?

機能にアクセスできるからって同じ見た目にする必要ないし、もっとMR特化のインタフェースがいいんじゃないか・・・?

などと頭を回る疑念。ここで手が止まるのが自分の悪いところである。先のことはわからないがとりあえず「Ableton Liveの機能をHoloLens上に再現する」にフォーカスし、手を動かしていくことにしました。なので現状これによって嬉しくなることはないです。書いていて思いましたがこれって技術デモみたいなものですね。

あと、あんまり頭の中でだけで作ったものを見せても、見た人は付いてきてくれないんじゃないかなという気持ちもあった。いきなり空中のCGを手でぐねぐねやるよりも、とりあえず技術デモから始めるのって悪くない気がしますね。

今後の展望・やりたいこと

自分は音楽が好きなので「新しい音楽を作りたい」というのが一番やりたいことですね。「新しい音楽」というのが新しい楽曲構造なのか、音色なのかリズムなのか、演奏表現なのか、というのは定かじゃないですが。

ソフトウェアの進化によって理屈の上ではどんな音も出せるはずなんですが、ウンウン頭を捻ってPCの画面と睨めっこして新しい音を出すだけでは面白くない。新しい道具、インタフェースから人間の反応を引き出すやり方っていうのは悪くないと思うんですよね。HoloLens単体だとフィジカルなフィードバックがないので、この場合は演奏表現よりも楽曲構造や音色、リズムの生成に影響が出るんじゃないかとか。

新しくなるのは音楽ではなく、体験なのかもしれないし。視点かもしれない。作曲風景って五線譜からPCの画面まで2Dなんだけど、3D空間で作られているというイメージが浸透すればリズムの捉え方も変わるかもしれない。その辺りは固執せずにやっていけたらいいな。

まあ、単に見た目にでも新しいパフォーマンスが生まれればそれも良しかな。

続live.object: Live API is not initialized, use live.thisdevice to determine when initialization is complete(未解決)

kiyasu.hatenadiary.com

こちらの問題はまだ解決せず。

cycling74.com

ただ、このスレッドを読んでみると、どうやらシステム全体の負荷が原因のひとつではあるようだ。maxを起動させずlive上だけで操作するとエラーが出ない、エラーが出やすい処理と出にくい処理がある、などの報告がある。

このスレッドには[deferlow]の使いどころも書いてあるので読むのがいいと思います。[live.path]の直後に入れればいいらしい。つまりエラー文中の"notification"とは[live.path]のアウトレットの出力のことのようだ。

ではMaxの設定を変えてみてはどうか。

Max6の環境設定をいじってパフォーマンスをあげる:Max/MSP | mirrorboy

この記事を見つけた。

簡単なパッチでいろいろ設定かえて試してみたが解決せず…同時処理イベント数とか、最初の設定値で十分足りてそうなんだよなあ。

そうこうしていると動いていたパッチも変な挙動になってしまった。そこかしこにdeferlow突っ込んでいたが、deferlowってちょっと遅らせるだけではなくて「右のinletから順番に処理する」というルールも変えてしまうらしいのだった。ちょっと一回落ち着いてdeferlowの置き場所考え直して、処理全体も整理したほうがいいな…

進捗

最近ずっとやってるプロジェクト、そろそろ終わらせたいんだけど次から次へと問題が起こる。今日はm4lのデバイスが起動後に動作しないという状態になった。なんだこれは…
パッチを一度閉じて再度開いたり、編集モードに切り替えてセーブしたりしたら動くようになった。

たまに出るこのwarningと関係あるだろうか?

live.object: Live API is not initialized, use live.thisdevice to determine when initialization is complete

live.thisdeviceの使い方もよくわからない。getstateメッセージを突っ込んでみたが…


とりあえず細かいことには目を瞑ってゴンゴンやろう、と思って進めてきたが、[live.object]を呼び出すときに以下のエラーが出る件、だんだんと頻発するようになった。どうやら腰を据えて向き合わないといけないようだ。

live.object: Changes cannot be triggered by notifications. You will need to defer your response.

live.object: Setting the Id cannot be triggered by notifications. You will need to defer your response.

フィードバックループしないための仕組みで、notificationきっかけで[live.object]のid設定したりプロパティ設定をしようとするとこのエラーが出るようだ。ただ毎回出るわけではなく、体感では作業の最初の頃は出ないが続けているうちにだんだん出る可能性が高くなってくる。

ちなみに

You will need to defer your response.

は[deferlow]オブジェクトのことらしく、これを適当なところに挟めば解決する「かも」みたいな記事を見つけた。改善はしているのかもしれないがそれでもエラーが出る時は出る。

cycling74.com

ほかにもいろいろ知見が集まっていたので訳してみた

  • 編集中のデバイスが含まれている時、この問題が起こる傾向がある。maxとlive間の通信がうまくいっていないようだ

  • 編集状態じゃなければ問題なく動くようだ

  • deferやdeferlowは信用できない。live.objectのid指定時にdeferlowを挟み込んだり、live.objectの前段に挟み込んだりしたが毎回異なる結果とエラーがでた。

  • edit modeじゃないときどういう挙動になるか調べるため、右クリックでliveからmaxを開いた。editorかそうじゃないかで、確かにスケジューリングなどの挙動がだいぶ異なるようだ…

「編集状態じゃなければ問題なく動く」というのは本当だろうか。試したが自分の環境ではうまくいかなかった。というか一回閉じると冒頭の「そもそも動作しない」みたいな挙動になったのだった。どうすれば…


次にこちらの長大なスレッド読んでみよう。

cycling74.com

Note: changes to a Live Set and its contents are not possible from a notification. The error message in the Max Window is 'Changes cannot be triggered by notifications'. In many cases putting a deferlow between the notification outlet and the actual change helps to resolve the issue.

古いですが Live API Overview Reference

からの引用ですね。自分プロジェクトではnotificationから呼びまくりだし、おそらくそうせざるを得ない。どうするべ…とりあえずこのスレッドをじっくり読んで、以下の記事も目を通しておこう

cycling74.com

cycling74.com

【Max8】[iter]の終わりを検知する

[iter]オブジェクトは結構便利ですが、終わりを検知したいときがあります。maxで明確に処理順を定義したいときです。基本的には処理は上から下まで順番に流れるんですが、send, receiveを挟むとその後の順番が不安だったりする…

そういうときはリストの最後に終端シンボルを自分で定義してそれを検出すればよいです。

f:id:mojo_nobu:20210109233614p:plain

[iter]に行く前にリストの後ろにendなどをappendして、出口で[route]で受ければよいです。

【LOM】オブジェクトにアクセスする方法いくつか

オブジェクトのidを直接指定する

f:id:mojo_nobu:20210101101547p:plain

パスをたどってオブジェクトを指定する

f:id:mojo_nobu:20210101103600p:plain

真ん中の[live.path]がミソです。これで「左から3番目のトラックの上から5番目のClipSlotをfireする」となります。パスの番号は0始まりなので2の場合は端から0,1,2で3番目です。

f:id:mojo_nobu:20210101103859p:plain

↑は実行後のableton liveの画面。「左から3番目のトラックの上から5番目のClipSlot」がfireされてますね。OK。

パスの指定方法はこちらの冒頭の図をご覧ください。

docs.cycling74.com

Tracks以下のClipSlots配列を取得してオブジェクトにアクセスする

応用編です。Tracks以下にいくつClipSlotsがあるかわからないので全部取ってきていい感じに利用したい場合のやりかたです。

f:id:mojo_nobu:20210101115942p:plain

右のコンソールにidが順番に出力されています。[zl.filter]と[iter]を使ってidだけ順番に出力させます。

ちなみにClipSlotsはScenes経由ではなくTracks経由で取得したほうがいいようです。どちらでも取れるんですけど、Tracks経由が正規のパスで、Scenesのほうがリンクみたいになってるぽい。かつてScenes経由で取ってそのあとの処理で面倒なことになったりしたので、特に理由なければTracks経由でいきましょう。

live.objectからパスを取得する

逆に、上記方法で指定したオブジェクトからパスを取ってくることもできます。 f:id:mojo_nobu:20210101164525p:plain getpathメッセージを使います。