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つの点からなる図形が生成されればそのやり方はなんでもいいのです.


例えば,ペンで直線と点を描いてもいいですし,ということは,コンピュータで自動生成してもいい訳です.

次に生成された図形から,それぞれの点と線の距離を測り,表にしていきます.この表から,どのような音を,いつ,どれくらいの時間出すべきか,以下のように決定します.点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の値をプロットしていきます.

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のプログラミング環境としての特徴を意識すれば,少し込み入った制御構造もパッチのみで実装することができます.



2017年8月11日金曜日

Signal Bottomシンポジウムで発表しました

およそ半年ごとに開催されている技術者・研究者のプレゼン飲み会"Signal Bottom"のシンポジウムで発表しました.

信号処理・組み込み技術・電子工作およびそれらに関連した数学や物理学・ソフトウェア工学,更には応用事例や研究の紹介までをカバーする飲み(意見交換)会で,酔漢さんによって企画・運営されています.

そんなSignal Bottomの今年7月に行われたシンポジウムで,僭越ながら発表させていただきました.この回は一般に公開できる内容であれば事後にプレゼン資料をwebサイトで公開することになっており,私の発表スライドも公開させていただきました.


内容的には以前このブログで紹介した物理シミュレーション音源合成法Karplus-Strong合成についてです.当日は,Maxで実際にこの合成法を実装しながらデモするという形式をとりました.

また,本ブログでは取り上げていない話題として,Karplus-Strongを用いたオンド・マルトノのパルム・スピーカの再現実験(パルム・スピーカの弦をKarplus-Strong合成器と考えてオンドマルトノの音を合成器に入力する),類似の合成法としてPerry CockのSlideFluteの紹介とデモを行いました.

今回参加して一番戸惑ったのは,参加者の一人だった光エレクトロニクス分野の研究者に「ピッチ」という言葉とその物理的意味が共有できていなかったこと.音響分野ではもはやその意味も物理的に何を言っているかも常識であろうと思われるこの概念が,分野が変われば何を言っているか理解されないというのは,非常に驚きました.結局,こうした議論を重ねた結果,私の発表は時間をかなりオーバーしてしまい,ご迷惑をおかけする形となってしまいました.幅広い分野の専門家が集まるSignal Bottomだからこそ起こる現象で,最も刺激的な瞬間です.こうした刺激を体感できるのは,自分が発表者として参加した時により強く感じることができます.

技術者・研究者の皆さん,Signal Bottomでは参加者の輪が今後も広がっていくことを望んでいるようです(多分).信号処理・組み込み技術・電子工作に興味のある皆さんはSignal Bottomに参加してみませんか?私の知り合いの方でしたら,私から会や酔漢さんを紹介することもできますし,酔漢さんにTwitterで話しかけてみると,大喜びで案内してくれると思います(多分).

2017年8月1日火曜日

ヤニス・クセナキス「音楽と建築」復刊記念(蛇足)〜現代に蘇ったUPICことIanniX〜

前回の記事,いかがでしたでしょうか?今般,彼の著書「音楽と建築」が復刊されたヤニス・クセナキスについて,その手法の一端をMaxのプログラムとして実装しました.

クセナキスのとりわけ初期の作品において特徴的だったのは,昨日の記事でも触れた,沢山のグリッサンド群を重ね合わせた構造を生み出す作品です.



これは,昨日の記事で名前だけ出てきた彼のデビュー作「Metastasis」です.音を聞くと,この線の通りにグリッサンドを多重した音響構造が浮かび上がってきているのが感じられると思います.

こうした作曲法をより直感的に実践するために彼が開発したコンピュータプログラムにUPICがあります.


タブレットとタッチペンを使って線を描くと,横軸を時間,縦軸を周波数とした音響を生成します.建築家でもあった彼らしいアプローチです.


1978年時点でこのような機能をもったプログラムは,非常に先駆的で,UPICは多くの作曲家によって使われることになります.

しかし,UPICは1978年のコンピューティング環境で開発されたプログラムです.このプログラムは,コンピュータの進歩とともに,姿を変えながら受け継がれることになります.

現在では,オープンソースのソフトウェアIanniXとして公開がされており,誰でもダウンロードして利用することができます.


IanniX自体が行うのは,IanniX本体がクライアント・アプリケーションとなって,ユーザが描いた図形からOSCでサーバ・アプリケーションに演奏情報を送信するだけです.音響信号として合成するのは,サーバ・アプリケーションが行います.OSCが受信できれば,演奏情報から音響信号を合成する処理は自分で実装すればよいので,サーバ・アプリケーション自体は何でもいいのですが,IanniX付属のMaxパッチがすぐに使えていいと思います.(他にPdやProcessing 等の環境で実装されたサーバ・アプリケーションが付属しています.)

IanniX本体を立ち上げ,"Patches/Max"フォルダにある"Max Sound Example.maxpat"を起動します.




IanniXの画面はこのようになっています.


例えば,Draw a Smooth Curveを選んで線を引きます.クリックするごとに曲線の制御点が増えていき,ダブルクリックで作図を終了します.


Adds a timelineを選択して,図の横軸の時間軸の開始地点を挿入します.矢印キーで左右にずらすことができます.



再生ボタンを押すと,この図の縦軸を周波数とする音響が,Maxパッチから再生されます.


様々なモードを使い分けて様々な特徴を持つ音を追加できます.





Examplesも非常に充実しています.

こちらはMetastasisの楽譜.


他にも面白い音が作れるサンプルが沢山付属しています.


クセナキスが自分の作曲における技法を解説した「音楽と建築」を読み,IanniXで彼の技法を追体験するのも楽しみ方の一つかもしれません.

2017年7月31日月曜日

ヤニス・クセナキス「音楽と建築」復刊記念〜グリッサンド群を操作するプログラム〜

ヤニス・クセナキスという作曲家をご存知ですか?現代音楽や電子音楽,ヒーリング・ミュージックといったジャンルの音楽に興味のある方はご存知だと思います.


とても神経質そうな,絶妙な表情をしていますが,実は彼は生まれ故郷のギリシャで反政府運動に関わり,その時の闘争で左目を失っています.このことが彼の表情の印象に影響しているのだと思います.ちなみに,彼は酒に酔うと左目の義眼を人前で外して驚かせる癖があったそうです.

彼はフランス亡命後,ル・コルビジェ事務所で建築家として働きました.その後,建築家としての仕事と並行して作曲も行うようになり,オリヴィエ・メシアンの素で作曲を学ぶようになります.その際メシアンに「君は建築家だから数学を知っている.なぜそれを応用しないのか?数学を知っていれば伝統的な作曲技法の修練はあってもなくても同じではないか?」と言われ(メシアンは「トータル・セリエリズム」という非常に厳格な作曲技法を考案し,主にヨーロッパでの現代音楽の創作がシステマティックになっていくきっかけを作った作曲家の一人です.),作曲にも数学を応用するようになります.

彼のそうした作曲理論は,その後の電子音楽やコンピュータ音楽に大きな影響を与えることになります.また,彼が開発した作曲のためのコンピュータ・プログラム「UPIC」は,まだコンピュータで音響を扱うなんて発想がなかった時期に,手書きの図形から音響を生成する,非常に先駆的なプログラムでした.

あまりいい写真がなかったので,最近のUPIC

彼が自分の創作に通底する思想と論理をまとめ,彼の作曲の弟子であった高橋悠治が日本語に訳した書籍「音楽と建築」は,彼の創作のアイデアについて知ることができる格好の資料でしたが,長らく廃刊となっており,中古でしか手に入れることができませんでした.私は,神戸のとあるアートスペースの片隅の,古い芸術関連の本が雑然と並べられた本棚の中に入っているのを見たのが唯一この本を見かけた機会でした.

そんな「音楽と建築」がこの度復刊されました.



私は本文をちゃんと読んだのはこの復刊によって手に入れてからが初めてでした.彼が何を考えて数学を音楽に応用していたか,非常によくわかります.

私は別にクセナキスやクセナキス界隈とは何の関わりもないので,今回の復刊を「記念」する義理はないのですが,折角のタイミングですので,クセナキスっぽい音響構造を作り出すプログラムをMaxで作ってみました.このプログラムは,以前私がツイキャスで配信しながら作ったものを発展させたものです.

彼が数学を応用した作品の中で,初期の有名な作品はデビュー作「Metastasis」と「Pithoprakta」でしょう.これらの作品の「楽譜」が以下です.



こうした作品群で彼が行ったのは,グリッサンド(連続的に音の高さが変化する演奏法.トロンボーンによるそれが有名だろう.)する無数の音群を制御することによって複雑な音構造を浮かび上がらせることでした.それは,Metastasisの構想の中にも見ることができます.



一つ一つのグリッサンドは直線的に支持されています.こうした直線的なグリッサンドする音が様々な長さ・タイミングで重なり合うことで,曲線的な,複雑な構造を形作っています.こうした音響をMaxで作り出します.

多くの音を個別に制御するテクニックは,Maxのpoly~オブジェクトが使えます.poly~オブジェクトの使い方が今回のプログラムの鍵になります.

まずは,この構造をつくるプログラムを作ってみましょう.


まずは,poly~の中身になるパッチを作ります.上の画像を見ると,25個の異なるピッチの音が同じ時刻にスタートして,それぞれ異なる長さで同じピッチに向かってグリッサンドしています.到達地点のピッチを(今回のプログラムでは)4000Hzとすると,line~オブジェクトを使ってこのようになります.親パッチからin 1へスタート時の周波数が,in 2へグリッサンドの時間が入力されます.グリッサンドが終わると音が消えます.


このパッチがpoly~オブジェクトで呼ばれることで,同じプログラムが同時に動作することになります.

親パッチを見てみましょう.


poly~の数を25にして,先ほど作成したパッチを25個生成します.


25個生成したパッチの中で任意のパッチのインレットにデータを入力するには

target [パッチの番号(1〜n)]

 というメッセージに続けてデータを入力します.

例えば,

target 10

200

という順でメッセージを送れば,パッチ(10)に200という整数を入力したことになります.上のパッチでは,グリッサンド開始時の周波数と,グリッサンド時間を入力値としていますので,これらを別々にリストとして決定して,リストの全要素をバラバラに送ると同時に(Maxのリストは一括で入力されます),それぞれの要素が入力される前に "target [パッチの番号(=1から始まるリストのインデックス)]"を挿入すれば,リストで決定した値がpoly~で複数生成したそれぞれのパッチに送れることになります.

そのようなデータの入力体系を作るのがこの部分.



Maxを使ったことがある方は,この部分の上半分,Multisliderでリストが生成されていることはだいたいお分かりだと思います.ちなみに,初期値として,0Hzから4000Hzの少し下あたりまでを線形に増やしていくようなリストをuziとthreshで自動生成しています.肝は下半分.iterとaccumが肝心です.まず,Multisliderからリストが出力されると,accumに"set 0"が送られ,accumの内部変数が0で初期化されます.(MaxのRight to Left Orderはご存知ですよね?)
次にリストがiterに入ります.iterはリストの全要素を一つずつ別のメッセージとして出力するオブジェクトです.今回は25個の浮動小数点数からなるリストを入力していますから,一回iterにリストが入るたびに25回の浮動小数点数の出力がされます.この時,accumの第2インレットに1を入力します.この入力によってaccumの内部変数が1追加されました.先ほど0で初期化したので,内部変数は1になりました.その後,accumの第1インレットにbangを入力します.これによって内部変数の値をアウトレットから出力します.
ところで,iterによって一つの浮動小数点数に分けられたデータは,既にpackに到着しています.(よく見ると,packに向かうラインの方がaccumに向かうラインよりも右側にありますね?)このタイミングで先ほど発生したbangによってaccumから内部変数の値が出力されると

[accumの内部変数] [iterによって分けられたリストの1要素]

というリストがpackから出力されます.これが"target $1,$2"を通り,$1と$2がリストのそれぞれの要素で代入されて出力されることになります.この処理はiterによってリストの要素の個数回繰り返されます.その度にaccumの内部変数には1が加算されるので,iterがリストの要素を出力する毎にtargetの後の数字が一つずつ増えていくことになるのです.

今は,グリッサンド開始時の周波数の決定を行いました.全く同様の方法で,グリッサンドの時間を決定します.

こうして作ったパッチの,"s trigger"に入力しているButtonをクリックすると


スペクトログラムで計測すると,あの画像っぽい構造が現れました.

この構造は,上の画像のようなリストの与え方をしたからです.従って,Multisliderを操作してリストの値を変更すると,現れる構造も変化します.



さて,ここで,操作できる要素を更に増やしてみましょう.以下の4つを独立して決定できるようにします.

・グリッサンド開始時の周波数
・グリッサンド終了時の周波数
・グリッサンドにかかる時間
・グリッサンドの開始時刻

これらを操作するために,poly~のパッチを以下のように変更します.これまでハードコーディングしていた上記に該当する部分をインレットからの入力値に置き換えるます.また,親パッチから送られるトリガーにdelayを挟むことで,グリッサンドの開始に独立した遅延時間が発生するようにします.



それぞれの値を先述の方法で与えるようにします.


これによって更に色々なグリッサンドの構造が作れるようになります.




クセナキスの楽譜で見そうな構造が沢山できます.

このように多くの直線を多重して曲線的な構造を浮かび上がらせることができるということは,音楽や音響に関わらず,クリエイティブ・コーディングに携わる者は改めて再確認したいことであると思います.これ自体は,曲線の接戦の傾きを求める微分そのものであると同時に,コンピュータで曲線を表現する最も基本的なテクニックです.

いかがでしょうたでしょうか?こうしたグリッサンドを多重した音響は先述のソフトウェアUPICで作ることができます.しかし,「音楽と建築」を読むと,UPICによる作曲は直感的な一方,今回取り上げたような方法の方がよりクセナキスの初期における理論を反映できるインタフェースのように思います.クセナキスは統計力学の知見から無数のグリッサンドする音群を操作するというアイデアを導入しました.それぞれの音をグリッサンドのピッチ差とグリッサンドの時間を要素とする一次元ベクトルで表現し,ピアノや一般の管楽器のようなグリッサンドしない音は開始時と終了時のピッチ差がない特殊な場合と考え,全ての音楽がこの方法で実装できるとしました.そして,この音群のベクトルの要素それぞれが確率的に決定できるという方向へ拡張されます.(この考えが彼の中期以降に増えてくる篩法を応用した作曲理論に繋がります.)