※この記事は「はじめての<脱>音楽 やさしい現代音楽の作曲法」における私執筆の「OpenMusic」の基礎及び,前回のOpenMusicの基礎 番外編をお読みください.
「はじめての<脱>音楽 やさしい現代音楽の作曲法」,すでに重版になったようで,ご好評いただいているようです.私が担当したのはほんの一部だけですが,非常に嬉しく思います.
OpenMusicの特徴は,ソースコードを書かなくても良いグラフィカル・プログラミングですが,グラフィカル・プログラミングは見た目の難しさが少なく,直感的にプログラムを作成しても何らかの結果を得やすいという利点がありますが,一方で,プログラムの制御構造が,グラフィカル・プログラミングという名前とは裏腹に,見ただけでは分からないという欠点もあります.(その制御構造の分かりづらさは前回の記事でお分かりいただけたと思います.)なので,込み入ったプログラムを書こうとすると途端に難しくなってきます.今日ご紹介する繰り返し処理もその一つ.パッチの見た目からこの制御構造を理解するのはほぼ不可能だと思います.
プログラミングでよく使うテクニックに,繰り返し処理があります.その名の通り,同じ処理を指定した回数繰り返す処理です.例えば,10000個の整数全部に100を足す等の処理です.正攻法でいけば,10000回同じ処理を書かないといけないように思えますが,繰り返し処理を使えば,一回だけ処理を書いておいて,それを10000回繰り返させる,といった書き方が可能です.この処理はプログラミングの常識的なテクニックなので,何らかのプログラミング言語を学んだことがある人ならご存知のはずです.
OpenMusicでも繰り返し処理を記述することができます.繰り返し処理を行うオブジェクトが"omloop"オブジェクトです.
パッチ内でomloopオブジェクトを出して,ダブルクリックすると,画像の右側のようなウィンドウが出てきます.このウィンドウが,omloopの中身のパッチを作成するウィンドウで,このウィンドウで作った処理が,繰り返し処理されることになります.
"eachTime"と"finally"というオブジェクトが既にあります.この2つのオブジェクトは繰り返し処理に必須のオブジェクトなので,最初から出ています.
omloopの処理がどのように行われるか知るために,このようなパッチを作りました.Eval Boxすると,OM Listenerウィンドウにこのように表示されます."forloop"オブジェクトは,所謂for文を実装するオブジェクトで,第1インレットの値から第2インレットの値まで内部変数の値を1ずつ増やしながら繰り返しを行うオブジェクトです.
前回の記事で,OpenMusicは,パッチの下から上のオブジェクトにデータの要求を行うという制御構造を説明しました.その考え方でこのパッチを見ると,以下のようなことが起きています.重要なのは,eachTimeの使い方です.eachTimeは,ループの各回の開始時点でデータの要求を行い,データが到着すると,ループが終了するまで,次のデータ要求を繰り返します.
① forloopオブジェクトの内部変数は0(第1インレットで設定したので)
② eachTimeオブジェクトがprintオブジェクトに値を要求
③ printオブジェクトはデータを持っていないのでさらに上のテキストボックスにデータを要求
④ テキストボックスは"hello"を出力
⑤ printオブジェクトはOM Listenerウィンドウに"hello"を表示し,アウトレットからも出力
⑥ eachTimeオブジェクトに"hello"が入力されたので,この回は終了.forloopオブジェクトの内部変数が1増える
⑦ ②〜⑥をforloopオブジェクトの内部変数が9になるまで繰り返す
⑧ forloopオブジェクトの内部変数が9になったのでループは終了.finallyオブジェクトがデータ要求を行い,データを受け取るとomloopオブジェクトの処理は終結.(この時,finallyオブジェクトに入力された値が,omloopオブジェクトのアウトレットから出力される)
このようになります.この処理の結果が,上の画像のOM Listenerウィンドウの表示です.尚,最後,"finish"が2回表示されているのは,1個目は,omloop内のprintオブジェクトに入力された時点の"finish",2個目は,omloopをEval Boxした結果としての"finish"です.
また,forloopオブジェクトの内部変数は,forloopオブジェクトのアウトレットから整数で出力されます.
値の範囲を変えると,この通り.
また,omloopウィンドウ左上にある,緑色の矢印ボタンをクリックすると,インレットオブジェクトが出てきます.そして,パッチウィンドウのomloopオブジェクトには,インレットが増えています.この操作を繰り返すと,インレットをいくつでも増やすことができます.このようにして,omloopオブジェクトの外からomloopオブジェクトに入力した値を,omloopオブジェクトの処理で使うことができるのです.
この他によく使うループの方法として,listloopがあります.listloopオブジェクトは,インレットに入力されたリストの要素をループ毎に順番に1つずつ出力していくオブジェクトです.
長くなりそうなので今回はここまで.
2018年5月24日木曜日
2018年5月17日木曜日
コンテンポラリーミュージックユニットAffine始めました.
Twitterではちょこちょこ言っていますが,今年の初めから,これまでずっと活動してきたmacaroomに加え,「Affine(アファイン)」というユニットを始めました.macaroomでは主にポップな歌モノをやっていますが,こちらはコンテンポラリーミュージック.完全なる実験音楽です.
macaroomが去年行った"Cage Out"という一連の企画で出会ったSaKi 汐音さん(名前暫定)という作曲家(?)にお誘いいただきまして始めることになりました.始めはこんなにがっつりやるつもりではなかったのですが,以前から興味のあった実験音楽や,本格的なライブ・エレクトロニクスの実践ができると思い,また,相方の常人離れした感性に惹かれ,何か面白いことができるのではないかと思い,今は,このユニットで私のできるだけのことをやってみようという気持ちになっています.
そんなAffineの頭のおかしい相方が,Affineのことを記録するブログを始めました.
http://affinedrawing.blogspot.jp/
ブログを始める際,「私が手間をとってブログをやるのだからお前も同じだけの手間を取れ」という非常に日本人的な発想丸出しの要望が来たので(頭おかしいくせにこういう時だけ日本人根性丸出し),このブログにたまにAffineのことも書いていきます.(複数ブログをやるのはかったるい)
ユニット名「Affine」は,私が提案しました.ユニット名について,この一案だけ出て,他に対案が全く出なかった(主宰者からも出ないという有様)ので,無投票当選となりました.
Affine.数学や工学に詳しい人であれば馴染み深い言葉です.画像処理の基本・アフィン変換のアフィンです.しかし,古い教科書は参考書では,このAffineをアファインと読む例もあり,我々はその読み方を採用することにしました.それについて,深い理由はなく,2音節より3音節の方が良いかなと思っただけです.
Affineとは,非常に基礎的なベクトルの演算だけで幾何学を構築した空間のことです.
多くの場合,幾何学というと,あの直線の長さがどうこう,ここの角度が云々と,その空間にあるものの「形」をベースにして議論がされます.一方Affine幾何学の場合,空間にあるものの形を考えることなく,ベクトルとその操作だけで幾何学の基本的な性質を構築します.逆に言うと,そのような抽象的な幾何学で明らかになった諸性質を実際的な空間で議論し直すのが,いわゆる通常の幾何学と言えるかもしれません.(この理解は数弱の私の理解であり,非常に信憑性が薄いです)
最初は,"Orthogonal" というユニット名を考えました.Orthogonalとは直交という意味です.直交とは,ある直線と別の直線が90度に交わっていること.
2つのベクトルが直交している時,その内積が0になることは数学の常識です.ある量とある量が独立して変化する時,それらの量は直交していると言えます.例えば,バスに乗っている時の心拍数と,その人の移動する速さは直交しています.バスが早く走ろうがゆっくり走ろうが,その人は座っているだけであり,運動による心拍数の上下がないからです.しかし,歩きまたは走って移動している時の心拍数と,その人の移動する速さは,直交していない場合が多いでしょう.ゆっくり歩いている時よりも早く走っている時の方が心拍数が上がると考えられ,移動する速さの上昇に応じて心拍数が上がっていきます.このような関係の場合,それらの量は直交ではありません.
直交について,図で描くと,このようになるでしょうか?
上の図は,x軸とy軸が直交している場合です.(0,2)にあった点Pがx軸に平行に移動する場合,どこまで移動してもyの値は変わりません.yの値に関係なく,xの値を変化させ雨事ができるわけです.
しかし,x軸とy軸が直交していない場合,点Pをx軸に平行に移動すると,yの値も変わっていることがわかります.(すごく微妙な図になってしまいましたね・・・)
このように,互いに作用せずに変化する量を扱えるという性質が直交した座標系にはあるのです.
ちなみに,ステレオのアナログレコードは,左右チャネルの振動がそれぞれ直角になるようなVの字に刻まれており,これによって,お互いの影響を受けず,2チャネルの振動を1本の針が読み取ることができるのです.
macaroomが去年行った"Cage Out"という一連の企画で出会ったSaKi 汐音さん(名前暫定)という作曲家(?)にお誘いいただきまして始めることになりました.始めはこんなにがっつりやるつもりではなかったのですが,以前から興味のあった実験音楽や,本格的なライブ・エレクトロニクスの実践ができると思い,また,相方の常人離れした感性に惹かれ,何か面白いことができるのではないかと思い,今は,このユニットで私のできるだけのことをやってみようという気持ちになっています.
そんなAffineの頭のおかしい相方が,Affineのことを記録するブログを始めました.
http://affinedrawing.blogspot.jp/
ブログを始める際,「私が手間をとってブログをやるのだからお前も同じだけの手間を取れ」という非常に日本人的な発想丸出しの要望が来たので(
ユニット名「Affine」は,私が提案しました.ユニット名について,この一案だけ出て,他に対案が全く出なかった(主宰者からも出ないという有様)ので,無投票当選となりました.
Affine.数学や工学に詳しい人であれば馴染み深い言葉です.画像処理の基本・アフィン変換のアフィンです.しかし,古い教科書は参考書では,このAffineをアファインと読む例もあり,我々はその読み方を採用することにしました.それについて,深い理由はなく,2音節より3音節の方が良いかなと思っただけです.
Affineとは,非常に基礎的なベクトルの演算だけで幾何学を構築した空間のことです.
多くの場合,幾何学というと,あの直線の長さがどうこう,ここの角度が云々と,その空間にあるものの「形」をベースにして議論がされます.一方Affine幾何学の場合,空間にあるものの形を考えることなく,ベクトルとその操作だけで幾何学の基本的な性質を構築します.逆に言うと,そのような抽象的な幾何学で明らかになった諸性質を実際的な空間で議論し直すのが,いわゆる通常の幾何学と言えるかもしれません.(この理解は数弱の私の理解であり,非常に信憑性が薄いです)
最初は,"Orthogonal" というユニット名を考えました.Orthogonalとは直交という意味です.直交とは,ある直線と別の直線が90度に交わっていること.
2つのベクトルが直交している時,その内積が0になることは数学の常識です.ある量とある量が独立して変化する時,それらの量は直交していると言えます.例えば,バスに乗っている時の心拍数と,その人の移動する速さは直交しています.バスが早く走ろうがゆっくり走ろうが,その人は座っているだけであり,運動による心拍数の上下がないからです.しかし,歩きまたは走って移動している時の心拍数と,その人の移動する速さは,直交していない場合が多いでしょう.ゆっくり歩いている時よりも早く走っている時の方が心拍数が上がると考えられ,移動する速さの上昇に応じて心拍数が上がっていきます.このような関係の場合,それらの量は直交ではありません.
直交について,図で描くと,このようになるでしょうか?
上の図は,x軸とy軸が直交している場合です.(0,2)にあった点Pがx軸に平行に移動する場合,どこまで移動してもyの値は変わりません.yの値に関係なく,xの値を変化させ雨事ができるわけです.
このように,互いに作用せずに変化する量を扱えるという性質が直交した座標系にはあるのです.
ちなみに,ステレオのアナログレコードは,左右チャネルの振動がそれぞれ直角になるようなVの字に刻まれており,これによって,お互いの影響を受けず,2チャネルの振動を1本の針が読み取ることができるのです.
さて,何故ユニット名を直交を意味するOrthogonalにしようと思ったかというと,ユニット開始時点のスタイルとして想像していた,互いに互いのやっていることは気にせず,即興的にパフォーマンスしていくというスタイルが,まさに直交系のイメージに重なったからです.(※最近は互いに無干渉だと表現が発展しないということが分かってきたので,徐々に互いに干渉するようにしています.)
しかし,直交はともかく,Orthogonalは言い慣れないし,変な場所にアクセントがあるので,あんまり語感が気に入らないということで,類似の良い単語は無いかと考え,Affineにしました.
ですから,私個人としては,ユニット名はOrthogonalにしたかったのであり,Affineというユニット名自体には,殆ど意味は込められていません.
今後とも当ブログ・macaroom共々Affineもよろしくお願いいたします.
どんなユニットなのか書くのを忘れていました.長くなるので書きませんが,気になる方は,Affineが企画する最初のイベントにぜひお越しください.
2018年5月2日水曜日
「はじめての<脱>音楽 やさしい現代音楽の作曲法」にて付録記事を掲載しました 〜OpenMusicの基礎 番外編〜
随分久しぶりの投稿になってしまいました.仕事がバタバタし(これは毎年のこと),音楽活動もこれまでのmacaroomに加え,新しい活動も始めました.また,他にもいくつか個人的に引き受けたこともあり,そろそろ何足ものわらじを履くのがキツくなってきました.
そんな中の1つ,この度自由現代社から発売された「はじめての<脱>音楽 やさしい現代音楽の作曲法」において,巻末の付録部分に「OpenMusicの基礎」と題してIRCAMによる作曲支援ソフトウエアOpenMusicの初歩的な使い方を掲載する部分を執筆させていただきました.
OpenMusicは,現代音楽の作曲において多く用いられていながら,日本国内においては紹介される機会も少なく,あまり武器として使っている作曲家は見かけません.しかし,現代音楽史上でも存在感のある作曲家が多く使っていることも事実で,彼らの足跡を辿る良い手がかりにもなり得るソフトウエアです.
しかし,付録として掲載したので,簡単な操作方法の説明と,私が例題として作ったプログラム例を載せるのみにとどまってしまっています.正直な話,あの記事を読んだ結果,OpenMusicの使い方がわかったとして,それを使いこなして創作を行えるかというと,かなり難しいかもしれません.そこで,本ブログで,少しずつではありますが,本付録の補填記事を掲載していきたいと思います.(本記事を読む前に,「はじめての<脱>音楽 やさしい現代音楽の作曲法」を買って読んでくださいね〜)
今回は,プログラマであれば一番気になるところ「OpenMusicプログラミングにおける制御構造」です.本来,プログラミング言語や環境を紹介するときは,これを真っ先に説明しなければならないのですが,本書は作曲法を説明する本であり,プログラミングの本ではないので,省略しました.
まず,比較のために,Maxの制御構造も確認してみましょう.今回作ったのは,非常に簡単なプログラム「100に1を足して100+1=101をコンソールに表示するプログラム」です.こんな感じ.
そんな中の1つ,この度自由現代社から発売された「はじめての<脱>音楽 やさしい現代音楽の作曲法」において,巻末の付録部分に「OpenMusicの基礎」と題してIRCAMによる作曲支援ソフトウエアOpenMusicの初歩的な使い方を掲載する部分を執筆させていただきました.
OpenMusicは,現代音楽の作曲において多く用いられていながら,日本国内においては紹介される機会も少なく,あまり武器として使っている作曲家は見かけません.しかし,現代音楽史上でも存在感のある作曲家が多く使っていることも事実で,彼らの足跡を辿る良い手がかりにもなり得るソフトウエアです.
しかし,付録として掲載したので,簡単な操作方法の説明と,私が例題として作ったプログラム例を載せるのみにとどまってしまっています.正直な話,あの記事を読んだ結果,OpenMusicの使い方がわかったとして,それを使いこなして創作を行えるかというと,かなり難しいかもしれません.そこで,本ブログで,少しずつではありますが,本付録の補填記事を掲載していきたいと思います.(本記事を読む前に,「はじめての<脱>音楽 やさしい現代音楽の作曲法」を買って読んでくださいね〜)
今回は,プログラマであれば一番気になるところ「OpenMusicプログラミングにおける制御構造」です.本来,プログラミング言語や環境を紹介するときは,これを真っ先に説明しなければならないのですが,本書は作曲法を説明する本であり,プログラミングの本ではないので,省略しました.
まず,比較のために,Maxの制御構造も確認してみましょう.今回作ったのは,非常に簡単なプログラム「100に1を足して100+1=101をコンソールに表示するプログラム」です.こんな感じ.
実践的なMaxプログラミングに慣れている方は状況に応じてもっと違った作り方をするかもしれませんが,今回は,制御構造を説明しやすいように画像のように作っています.
Maxのプログラム制御で押さえておきたいのが,
・データが第1インレットに入力されたらアウトレットからデータを出力し,次のオブジェクトに入力される(これがオブジェクトの繋がっている分だけ繰り返される)
・あるオブジェクトからの出力は,右→左の順番でデータが出力される
の2点です.これらを踏まえてこのパッチを見てみると,このような順で処理が行われているということになります.
上記2点の法則に従った順番になっていることを確認してみてください.
Maxはインタラクティブ操作を前提としたイベントドリブンプログラミングになっており,そのため,入力→出力というデータの流れが視覚的にうまく表現されている,非常に優れたプログラミング環境だと思います.
さて,同様の処理をOpenMusicでやると以下のようになります.
このパッチのprintオブジェクトを右クリックして,"Eval Box"をクリックすると,OM Listenerウィンドウに計算結果が表示されるわけです.
この,Eval Boxをクリックした時に,プログラムが実行されるのですが(Maxのインタラクティブなイベントドリブンプログラミングに慣れているとここが分かりづらい),この時,次のようなことが起こります.
・あるオブジェクトがEval Boxされると,そのオブジェクトのインレットに接続されているオブジェクトにデータを要求する
・データを要求されたオブジェクトがデータを持っていればそれを出力する
・データを要求されたオブジェクトがデータを持っていなければ,さらにそのオブジェクトのインレットに接続されているオブジェクトにデータを要求する
・要求の結果,データがインレットに入力されれば,処理してアウトレットから出力
・これをEval Boxしたオブジェクトから上のオブジェクトのつながりの数だけ繰り返す
この箇条書きで分かりましたでしょうか?とても難しいですね.これも,図に処理手順を書くと下のようになります.
Maxとは違い,下から上に要求が伝わり,データが処理されていることに注意してください.
尚,上の図において③と④の順番は,左から右の順でデータが到着しており,Maxとは逆です.この点については,私も現状そこまで詳しくないので,もしかしたら逆かもしれません.しかし,他の処理での挙動を見ていると,どうやら左から右の順でデータが処理されているように思います.
ごく簡単なパッチでのご紹介になりましたが,これがOpenMusicにおけるプログラミングの制御構造になります.このような面倒なことを知らなくても,冒頭紹介した本の付録で紹介した程度のプログラムを作成することは可能です.しかし,omloopや条件分岐等,プログラミングの醍醐味と言える処理を取り入れたパッチを作成しようと思うと,こうした制御構造の理解なしでは自分の意図通りの処理を実装することはかなり困難です.
それではよいアルゴリズム作曲ライフを!!
2017年12月31日日曜日
12/16 CAGE INにおけるVariationsⅡの演奏について
私が技術全般をサポートしているエレクトロニカユニットmacaroomが今年の8月にリリースしたミニアルバム"cage out"は,アメリカの現代音楽作曲家ジョン・ケージの楽曲を楽譜通りに,尚且つポップな「歌モノ」として演奏するという試みを行った画期的な内容となったアルバムでした.このアルバムの発売記念イベントとして,このプロジェクトのアドバイザをしていただいた現代音楽作曲家の川島素晴先生と,先生に紹介していただいたインプロビゼーション系の演奏ユニット木漏れ日エレキに,本格的なジョン・ケージ楽曲の演奏を行っていただくという事も行いました.
このイベントのアンサーイベントとして川島先生が企画したのが,先日行われたCAGE IN.このイベントは,最初から最後まで全てジョン・ケージの楽曲,しかも初期から晩年まで時系列順に聴けるという日本では非常に珍しい内容でした.私はこのイベントで音響を担当し,様々な楽曲の音源の準備や機材のプランニング等を行い,当日はそのオペレーションを行なったのですが,何曲かは出演者として演奏を行いました.その曲の1つが,VariationsⅡという曲です.この曲はイベントの第2部「ミュージサーカス」の中で演奏した曲です.ミュージサーカスとは,同時多発的に色々な楽曲や演目を行うというケージが提唱したコンサート形式で,本イベントではケージの様々な楽曲を全出演者で同時に演奏しました.その中でVariationsⅡは出演者それぞれが独自に準備し,ミュージサーカスの中で演奏することになっており,出演者それぞれのVariationsⅡが同時に演奏されていたのです.
私は,VariationsⅡで指示されている作業を全てコンピュータ・プログラムによって行い,演奏もプログラムによって自動演奏するという形で演奏しました.この試みは,川島先生から「VariationsⅡの新しいアプローチかもしれない」というご評価をいただきました.個人的には,過去にも似たことを考え実践した人は沢山いただろうと思うのですが,とにかく,当日はミュージサーカスということで音場がぐちゃぐちゃでどの音がそれだったのか分からなかったと思いますし,せっかく作ったのでその内容をご紹介します.尚,本プログラムはイベントの準備に追われ,自分のことに構う優先順位がどんどん下がる中,とにかく「16日に上演する」ことだけを目的としたため,ほとんど全てハードコーディングになっており,また,実際には特定の条件でしかありえないようなことを動作の前提としているため,あまり他の場面で再利用できるような段階ではありませんので,その点はご了承ください.
VariationsⅡの譜面には,点と直線が書かれた5枚の透明シート,直線のみが書かれた1枚の透明シートがついてきます.これをテーブルの上にばらまくと,6本の直線,5つの点からなる図形が生成されます.これは,楽譜に指示されたやり方のひとつで,実際には,6本の直線,5つの点からなる図形が生成されればそのやり方はなんでもいいのです.
----------------------------------------------------------------------------------------------------------------------
2018/01/06追記
webから今見つけている範囲で,本件と類似の取り組みもご紹介しておきます.
Variations 10b: A digital realization of John Cage's Variations II
Pythonで演奏上々の生成を行って,OSC経由で何らかの音響合成プログラムに演奏させるものです.
ジョン・ケージ《VARIATINOS II》への 演奏ソフトウェアアートによるアプローチ
VariationsⅡに着想を得て,手法は同じでも,独自のパラメータ設定により演奏を行うプログラム.openFrameworksのaddonとして開発したそうです.
このイベントのアンサーイベントとして川島先生が企画したのが,先日行われたCAGE IN.このイベントは,最初から最後まで全てジョン・ケージの楽曲,しかも初期から晩年まで時系列順に聴けるという日本では非常に珍しい内容でした.私はこのイベントで音響を担当し,様々な楽曲の音源の準備や機材のプランニング等を行い,当日はそのオペレーションを行なったのですが,何曲かは出演者として演奏を行いました.その曲の1つが,VariationsⅡという曲です.この曲はイベントの第2部「ミュージサーカス」の中で演奏した曲です.ミュージサーカスとは,同時多発的に色々な楽曲や演目を行うというケージが提唱したコンサート形式で,本イベントではケージの様々な楽曲を全出演者で同時に演奏しました.その中でVariationsⅡは出演者それぞれが独自に準備し,ミュージサーカスの中で演奏することになっており,出演者それぞれのVariationsⅡが同時に演奏されていたのです.
私は,VariationsⅡで指示されている作業を全てコンピュータ・プログラムによって行い,演奏もプログラムによって自動演奏するという形で演奏しました.この試みは,川島先生から「VariationsⅡの新しいアプローチかもしれない」というご評価をいただきました.個人的には,過去にも似たことを考え実践した人は沢山いただろうと思うのですが,とにかく,当日はミュージサーカスということで音場がぐちゃぐちゃでどの音がそれだったのか分からなかったと思いますし,せっかく作ったのでその内容をご紹介します.尚,本プログラムはイベントの準備に追われ,自分のことに構う優先順位がどんどん下がる中,とにかく「16日に上演する」ことだけを目的としたため,ほとんど全てハードコーディングになっており,また,実際には特定の条件でしかありえないようなことを動作の前提としているため,あまり他の場面で再利用できるような段階ではありませんので,その点はご了承ください.
VariationsⅡの譜面には,点と直線が書かれた5枚の透明シート,直線のみが書かれた1枚の透明シートがついてきます.これをテーブルの上にばらまくと,6本の直線,5つの点からなる図形が生成されます.これは,楽譜に指示されたやり方のひとつで,実際には,6本の直線,5つの点からなる図形が生成されればそのやり方はなんでもいいのです.
例えば,ペンで直線と点を描いてもいいですし,ということは,コンピュータで自動生成してもいい訳です.
次に生成された図形から,それぞれの点と線の距離を測り,表にしていきます.この表から,どのような音を,いつ,どれくらいの時間出すべきか,以下のように決定します.点1つにつき,1つの音として,パラメータを当てはめていきます.つまり,6個のパラメータを持つ音を5つ,考えるわけです.
ここで少し難しいのは6番目の直線と点の距離.これは,音をいくつ増やすかということを決定します.例えば,点1と直線6の距離が3.1cmであったら,音1は3個の音を出さなければならない訳です.この時,3回同音連打をするのではなく,新しく上記の図形を生成し,表を作ってその表の数字を順に当てはめていきます.
ここまでの作業をMATLABで行い,それぞれのパラメータをテキストファイルとして保持するプログラムを作成しました.高校までの数学の知識のみで実現できます.尚,実際には,2回目以降の図形の生成は,実際に生成された点と直線6の距離によって何回行うかが異なるはずです.ですから,本当は2回目以降の図形の生成は無限ループにして,必要な値の数が揃ったらループを抜けるという具合にするのが正解と思われます.しかし,今回のプログラムの範囲では,3回以上生成を行う必要がほぼない(各点と直線6との距離の和が(5x6)-5=25を超えない)と判断したので,1回行うのみになっています.
----------------------------------------------------------------------------------------------------------------------
clear;
close all;
rng('shuffle');
pointx=zeros(1,5);%5点のx座標
pointy=zeros(1,5);%5点のy座標
%直線ax+by+c=0
a=zeros(1,6);
b=zeros(1,6);
c=zeros(1,6);
d=zeros(5,6);%直線と点の距離
%点を乱数で決定
for k=1:5
pointx(k)=rand(1,1)*20-10;
pointy(k)=rand(1,1)*20-10;
end
figure(1);
hold on;
plot(pointx,pointy,'x');
plot(pointx,pointy,'o');
%直線を乱数で決定
for k=1:6
a(k)=rand(1,1)*4-2;
b(k)=rand(1,1)*4-2;
c(k)=rand(1,1)*4-2;
%ax+by+c=0
%y=(-ax-c)/b
plot([min(pointx) max(pointx)],[(-a(k)*min(pointx)-c(k))/b(k),(-a(k)*max(pointx)-c(k))/b(k)]);
end
xlim([min(pointx)-2 max(pointx)+2]);
ylim([min(pointy)-2 max(pointy)+2]);
%距離を求める
for k=1:5
for n=1:6
d(k,n)=abs(a(n)*pointx(k)+b(n)*pointy(k)+c(n))/sqrt(a(n)*a(n)+b(n)*b(n));
end
end
d
%6列目の数に応じてピッチの数を決定
times=floor(d(:,6))+1
%決定された数だけピッチの変数を確保
pitch1=zeros(times(1),1);
pitch1(1)=d(1,1);
pitch2=zeros(times(2),1);
pitch2(1)=d(2,1);
pitch3=zeros(times(3),1);
pitch3(1)=d(3,1);
pitch4=zeros(times(4),1);
pitch4(1)=d(4,1);
pitch5=zeros(times(5),1);
pitch5(1)=d(5,1);
%もう一度点と線のオペレーションを実行
rng('shuffle');
fig=2;
for k=1:5
pointx(k)=rand(1,1)*20-10;
pointy(k)=rand(1,1)*20-10;
end
figure(fig);
hold on;
plot(pointx,pointy,'x');
plot(pointx,pointy,'o');
for k=1:6
a(k)=rand(1,1)*4-2;
b(k)=rand(1,1)*4-2;
c(k)=rand(1,1)*4-2;
%ax+by+c=0
%y=(-ax-c)/b
plot([min(pointx) max(pointx)],[(-a(k)*min(pointx)-c(k))/b(k),(-a(k)*max(pointx)-c(k))/b(k)]);
end
d2=zeros(5,6);
for k=1:5
for n=1:6
d2(k,n)=abs(a(n)*pointx(k)+b(n)*pointy(k)+c(n))/sqrt(a(n)*a(n)+b(n)*b(n));
end
end
d2=reshape(d2,30,1);%d2を1次元に変形
%d2の値を順にそれぞれのピッチに追加していく
index=1;
for k=2:length(pitch1)
if index<=30
pitch1(k)=d2(index);
index=index+1;
end
end
for k=2:length(pitch2)
if index<=30
pitch2(k)=d2(index);
index=index+1;
end
end
for k=2:length(pitch3)
if index<=30
pitch3(k)=d2(index);
index=index+1;
end
end
for k=2:length(pitch4)
if index<=30
pitch4(k)=d2(index);
index=index+1;
end
end
for k=2:length(pitch5)
if index<=30
pitch5(k)=d2(index);
index=index+1;
end
end
%値をピッチ(Hz)として正規化(範囲は適当に決めている)
pitch1=400+600*pitch1/max(d(:,1))
pitch2=400+600*pitch2/max(d(:,1))
pitch3=400+600*pitch3/max(d(:,1))
pitch4=400+600*pitch4/max(d(:,1))
pitch5=400+600*pitch5/max(d(:,1))
%ピッチを保存
fp=fopen('pitch1.txt','w');
fprintf(fp,'%f\r\n',pitch1);
fclose(fp);
fp=fopen('pitch2.txt','w');
fprintf(fp,'%f\r\n',pitch2);
fclose(fp);
fp=fopen('pitch3.txt','w');
fprintf(fp,'%f\r\n',pitch3);
fclose(fp);
fp=fopen('pitch4.txt','w');
fprintf(fp,'%f\r\n',pitch4);
fclose(fp);
fp=fopen('pitch5.txt','w');
fprintf(fp,'%f\r\n',pitch5);
fclose(fp);
%音量を0-1に正規化して保存%
fp=fopen('dynamics.txt','w');
fprintf(fp,'%f ',d(:,2)/max(d(:,2)));
fclose(fp);
%音色パラメータを1-100にスケーリングして保存
fp=fopen('sound.txt','w');
fprintf(fp,'%f ',(99*d(:,3)/max(d(:,3)))+1);
fclose(fp);
%持続時間を0-1に正規化して保存
fp=fopen('tlength.txt','w');
fprintf(fp,'%f ',d(:,4)/max(d(:,4)));
fclose(fp);
%タイミングを最大45分になるようにスケーリングして保存
fp=fopen('timing.txt','w');
fprintf(fp,'%f ',1000*45*60*(d(:,5)/max(d(:,5))));
fclose(fp);
----------------------------------------------------------------------------------------------------------------------
これによって,各パラメータが決まりました.
このテキストファイルをMaxで読み込んで,演奏します.まず,テキストファイルを読み込んで,それぞれのタイミングで音を生成します.今回,タイミングの最大値を45分(2700000ms)にしたので,delayオブジェクトがそんな大きな値の遅延を行えるのか,少し心配でしたが,どうやら大丈夫なようです.
音の生成は"p pulse"で行なっています.その中身がこちら.
根本的には,パルスにBPFをかけたものを音源として使っています.パルスは,全周波数のパワーが均等な信号であるため,これをフィルタに通すと,そのフィルタの特性そのままの音色となって出力されます.今回はBPFをフィルタとして使っています.ですので,フィルタのQがせまくなると,その中心周波数を周波数とする正弦波に近い音色が得られます.コンピュータ音楽で音程感のある音を得る時によく使う方法の1つです.
今回の演奏では,音色パラメータをフィルタのQとして適用しています.つまり,音色パラメータの値が小さければ,周波数帯域の広いノイズに近い音,音色パラメータの値が大き切れば,周波数帯域の狭い音程感の強い音となって演奏されます.
更に,この音にリバーブをかけています.本当は自作のリバーブを使いたかったのですが,これまで作った自作リバーブの中に,この音に合うものがなかったので,とはいえ,新しいリバーブを作っている時間がなかったので,コンピュータ音楽家の松本昭彦さんのForeverbを使わせていただきました.このリバーブの最大の残響時間を最大の持続時間として,適用します.測定したところ,このリバーブの最大の残響時間は約20秒でしたので,持続時間が1の時(MATLABでは0-1に正規化して書き出しました),Maxで20000倍して適用しています.この適用方は,Foreverbの残響時間が線形に増えていく(Foreverbで設定したReverb Timeが0.5であれば残響時間は10秒になる)という仮定を前提とした適用方ですが,実際にはそのような増え方はしていません.ですので,厳密に行うならば,残響時間を様々な値で測定し,その増え方を反映した曲線で値を適用しなければなりません.今回のプログラムでは線形に残響時間が増えると仮定したため,下の動画でお聞きいただければ分かりますが,音から次の音がなるまでの間に音が持続しておらず,音に隙間ができてしまっています.
同様に他のパラメータも適用し,あとはスタートボタンとなるトグルをクリックすれば演奏が開始されます.
以上が今回のCAGE INで行なったVariationsⅡの全容です.ここから,更に発展する方向としては,今回MATLABで行なった図形の生成をjavascriptで実装し,Maxのjsオブジェクトを使って生成から演奏までの1連の流れを1つのプログラムで行うようにする等が考えられます.
これは,タイミングの最大値を3分にして楽譜を生成した様子です.音の雰囲気だけでも感じていただけると幸いです.(3分過ぎから音量注意です)
2018/01/06追記
webから今見つけている範囲で,本件と類似の取り組みもご紹介しておきます.
Variations 10b: A digital realization of John Cage's Variations II
Pythonで演奏上々の生成を行って,OSC経由で何らかの音響合成プログラムに演奏させるものです.
ジョン・ケージ《VARIATINOS II》への 演奏ソフトウェアアートによるアプローチ
VariationsⅡに着想を得て,手法は同じでも,独自のパラメータ設定により演奏を行うプログラム.openFrameworksのaddonとして開発したそうです.
2017年10月15日日曜日
Maxによるロジスティック写像 〜漸化式をMaxで実装〜
ロジスティック写像という方程式をご存知でしょうか?離散的な変数nを持つ量xを以下の差分方程式で与えた時の現象のことです.
\[x_n=ax_{n-1}(1-x_{n-1})\]
aは定数です.例えば,
\[a=2\]
として
\[x_0=0.001\]
から計算を始めると,
\[x_1=2\times0.001\times(1-0.001)=0.001998\]
\[x_2=2\times0.001998\times(1-0.00998)=0.31975992\]
\[x_3=2\times0.31975992\times(1-0.31975992)=0.5329816\]
\[x_4=2\times0.5329816\times(1-0.5329816)=0.49691391\]
\[x_5=2\times0.49691391\times(1-0.49691391)=0.49998095\]
\[x_6=2\times0.49998095\times(1-0.49998095)=0.5\]
\[x_7=2\times0.5\times(1-0.5)=0.5\]
というようにxは0.5に収束します.(この式では,一度0.5になってしまえば,もうそれ以上変化のしようがないことがわかります.)
このことを図にするとこのようになります.
(やってみればわかりますが)初期値が0.001以外でも,xは0.5に収束します.しかし,これはa=2の場合の話です.aを他の値にしたときの様子も見てみましょう.
a=3のとき,xは2つの値を繰り返す変化に収束するようです.
ちょっと見づらいですが,a=3.5のとき,4つの値を繰り返します.
aの値が増えると,徐々にxの変化の乱雑さが増えていきます.
a=4になると,ほとんど法則性なく変化しているといってもいいような変化をするようになります.しかし,この変化も冒頭で紹介したロジスティック写像の式の計算結果です.aの値が違うだけで実に多種多様な変化をもたらす方程式だということが分かります.このことを表したのが,有名な図
です.横軸がaの値.aの値によってxがどんな値に収束するかを表しています.ロジスティック写像の驚くべき点は,決定論的な法則による変化であるはずなのに,そうとは思えない変化をもたらすことです.このように,決定論的な法則があるにもかかわらず,見た目にはその法則が見出せないような変化をする系のことを「カオス力学系」と呼びます.ロジスティック写像はカオス力学系の非常に初歩的な例の一つです.
MATLABでロジスティック写像を実装してみます.aの値を変化させながらxの値をプロットしていきます.
実装のポイントは,「前回のxの値」を保持しておいて,それを「現在のxの値」の算出に利用するところです.
実行結果はこのようになります.
先ほどの図に比べて分岐のところで非連続な感じになっているのは,aを変化させる刻み幅が広いからです.
こうした,現在の値が過去の値によって決定されるような関係式のことを「漸化式」と呼びます.こうした漸化式は,コンピュータプログラミングで実装するのが簡単なので,コンピュータサイエンスが発展すると盛んに研究されるようになりました.一般にコンピュータによる数値計算は,いかに問題を漸化式に落とし込むかということが重要になるといっても過言ではありません.(オイラー法なんかがまさに良い例です.)
MATLABのようなソースコードを書いていくプログラミグ環境で漸化式を実装するのは非常に簡単です.一方,Maxのようなビジュアルプログラミング環境で行うにはどうしたらいいでしょうか?結論から言うと,Maxでロジスティック写像を実装するにはこのようになります.
このパッチで重要なのはf(floatの略)オブジェクトです.fは第二インレットに入った浮動小数点数を保持して,第一インレットにbangが入った時に保持した値をアウトレットから出力します.その値を使って,その下にある部分でロジスティック写像の計算を行います.この時,t(triggerの略)オブジェクトとRight to Left Orderを利用して,計算の順番を冒頭の式の通りに制御している点にも注目したいところです.そして,計算結果をまたfloatに入れてまで保持します.保持した値が次のbangの入力によって出力され,再びロジスティック写像の計算を行います.これをbangの入力の度に繰り返します.
ここで意識したいのは,一度fオブジェクトにbangが入力されると,ロジスティック写像の計算をして,もう一度fオブジェクトに計算結果を格納するまでが,ひとかたまりの処理として行われるということです.このひとかたまりの処理は原則同期的に行われるので,処理をし終わるまでパッチは他の処理を行いません.(非同期に動作するオブジェクトは別です.)
このように,Maxのプログラミング環境としての特徴を意識すれば,少し込み入った制御構造もパッチのみで実装することができます.
\[x_n=ax_{n-1}(1-x_{n-1})\]
aは定数です.例えば,
\[a=2\]
として
\[x_0=0.001\]
から計算を始めると,
\[x_1=2\times0.001\times(1-0.001)=0.001998\]
\[x_2=2\times0.001998\times(1-0.00998)=0.31975992\]
\[x_3=2\times0.31975992\times(1-0.31975992)=0.5329816\]
\[x_4=2\times0.5329816\times(1-0.5329816)=0.49691391\]
\[x_5=2\times0.49691391\times(1-0.49691391)=0.49998095\]
\[x_6=2\times0.49998095\times(1-0.49998095)=0.5\]
\[x_7=2\times0.5\times(1-0.5)=0.5\]
・・・
というようにxは0.5に収束します.(この式では,一度0.5になってしまえば,もうそれ以上変化のしようがないことがわかります.)
このことを図にするとこのようになります.
(やってみればわかりますが)初期値が0.001以外でも,xは0.5に収束します.しかし,これはa=2の場合の話です.aを他の値にしたときの様子も見てみましょう.
a=3のとき,xは2つの値を繰り返す変化に収束するようです.
ちょっと見づらいですが,a=3.5のとき,4つの値を繰り返します.
aの値が増えると,徐々にxの変化の乱雑さが増えていきます.
a=4になると,ほとんど法則性なく変化しているといってもいいような変化をするようになります.しかし,この変化も冒頭で紹介したロジスティック写像の式の計算結果です.aの値が違うだけで実に多種多様な変化をもたらす方程式だということが分かります.このことを表したのが,有名な図
です.横軸がaの値.aの値によってxがどんな値に収束するかを表しています.ロジスティック写像の驚くべき点は,決定論的な法則による変化であるはずなのに,そうとは思えない変化をもたらすことです.このように,決定論的な法則があるにもかかわらず,見た目にはその法則が見出せないような変化をする系のことを「カオス力学系」と呼びます.ロジスティック写像はカオス力学系の非常に初歩的な例の一つです.
MATLABでロジスティック写像を実装してみます.aの値を変化させながらxの値をプロットしていきます.
clear; close all; len=100000; starta=2.9; x=zeros(1,len); a=zeros(1,len); xmem=0.0000001; for k=1:len, a(k)=(4-starta)*k/len; a(k)=a(k)+starta; x(k)=a(k)*xmem*(1-xmem); xmem=x(k); end figure(2); plot(a,x,'.','MarkerSize',1); xlim([starta,4]); ylim([0,1]);
実装のポイントは,「前回のxの値」を保持しておいて,それを「現在のxの値」の算出に利用するところです.
実行結果はこのようになります.
先ほどの図に比べて分岐のところで非連続な感じになっているのは,aを変化させる刻み幅が広いからです.
こうした,現在の値が過去の値によって決定されるような関係式のことを「漸化式」と呼びます.こうした漸化式は,コンピュータプログラミングで実装するのが簡単なので,コンピュータサイエンスが発展すると盛んに研究されるようになりました.一般にコンピュータによる数値計算は,いかに問題を漸化式に落とし込むかということが重要になるといっても過言ではありません.(オイラー法なんかがまさに良い例です.)
MATLABのようなソースコードを書いていくプログラミグ環境で漸化式を実装するのは非常に簡単です.一方,Maxのようなビジュアルプログラミング環境で行うにはどうしたらいいでしょうか?結論から言うと,Maxでロジスティック写像を実装するにはこのようになります.
このパッチで重要なのはf(floatの略)オブジェクトです.fは第二インレットに入った浮動小数点数を保持して,第一インレットにbangが入った時に保持した値をアウトレットから出力します.その値を使って,その下にある部分でロジスティック写像の計算を行います.この時,t(triggerの略)オブジェクトとRight to Left Orderを利用して,計算の順番を冒頭の式の通りに制御している点にも注目したいところです.そして,計算結果をまたfloatに入れてまで保持します.保持した値が次のbangの入力によって出力され,再びロジスティック写像の計算を行います.これをbangの入力の度に繰り返します.
ここで意識したいのは,一度fオブジェクトにbangが入力されると,ロジスティック写像の計算をして,もう一度fオブジェクトに計算結果を格納するまでが,ひとかたまりの処理として行われるということです.このひとかたまりの処理は原則同期的に行われるので,処理をし終わるまでパッチは他の処理を行いません.(非同期に動作するオブジェクトは別です.)
このように,Maxのプログラミング環境としての特徴を意識すれば,少し込み入った制御構造もパッチのみで実装することができます.
登録:
投稿 (Atom)


































