見出し画像

ピッチによるソート、または音楽の無意味化

どうすれば音楽を「無意味化」できるだろうか? 音楽とは何か、意味とは何か、と問うのも一興であるが、とりあえず波形データをピッチ(音高)の高低順にソート(並び替え)してしまえば、紛れもなく無意味になるであろう。

例えば、以下はJohn von Neumannの名言を、ASCIIコード順にソートしたものである(スペースを除く)。

,,.Aaaaaaabbccddeeeeeeeeeeeffgghiiiiiiiilmmmmmnnnnnnnnnnoooooooprrrrrsssssssstttttttttuuvwyy

以下、ピッチ情報による波形データのソートについて検討する。まず課題となる音声ファイルを作る。Score.recordNRTを用いて、ランダムなピッチを15秒間演奏したものを、音声ファイルとして直接出力する。

// Example 1
(
SynthDef(\x, {|pch, dur|
	var env, frq, sig;
	env = Env([0, 1, 0.5, 0.5, 0], [0.01, 0.01, dur-0.05, 0.02]).ar(2);
	frq = pch.midicps;
	sig = PMOsc.ar(frq, frq, 1, 0, env);
	Out.ar(0, sig);
}).store;

p = Pbind(
	\instrument, \x,
	\pch, Pwhite(36, 84, inf),
	\dur, Pwhite(0.1, 0.5, inf),
);

z = p.asScore(15);
z.score.postcs;
o = ServerOptions.new.numOutputBusChannels = 1;
Score.recordNRT(z.score, outputFilePath: "any.wav".resolveRelative, options: o);
)

出力した音声ファイル(any.wav)を聴いてみる。この段階で既に無意味ではないのか……については(音と意味に関する詳しい検討を要するので、本稿では)措くとする。

// Example 2
(
f = Buffer.read(s, "any.wav".resolveRelative);

SynthDef(\playbuf, {
	a = PlayBuf.ar(1, f.bufnum, doneAction: 2);
	Out.ar(0, a!2);
}).play;
)

次にany.wavをピッチ順にソートするが、かなり込み入ったプログラミングになってしまった。このような場合、最初からクラスファイルとして書くと書きやすく、保守性も担保される。PitchSortクラスの中身については後述する。

クラスファイル(*.sc)は下記を問い合わせて示される、いずれかのディレクトリに置き、SCを起動(再起動またはリコンパイル)することで使用できる。

Platform.userExtensionDir
Platform.systemExtensionDir

Example 3はany.wavのピッチによる降順ソートを行う。

// Example 3
p = PitchSort("any.wav".resolveRelative).do;

ソート処理した音声はsorted.wavとして出力される。聴いて確認してみると、時々外しているようだが、概ねピッチの高い音から低い音に並び替えられている。

// Example 4
(
f = Buffer.read(s, "sorted.wav".resolveRelative);

SynthDef(\playbuf, {
	a = PlayBuf.ar(1, f.bufnum, doneAction: 2);
	Out.ar(0, a!2);
}).play;
)

さて、any.wavのような音源であれば、比較的良い結果が出るが、既存曲の音源などの場合はどうか。Berio「Sequenza I」やWebern「Kinderstück」など試したが、ほとんど上手く行かなかった。Pitchのパラメータの調整や入力前の音声へのフィルタ処理、あるいは元音源のノイズ除去、コンプレッションなどの下拵えも必要かも知れない。

ところで、Kermit-Canfield (2014)によれば、Pitchの他、すぐに使えるピッチトラッカーとしてSuperColliderにはTartiniとQitchが存在する。どちらもExtensionで、筆者は未使用だが、Tartiniは比較的導入がしやすいようである。いずれ試してみよう。

PitchSortの中身について簡単に述べる。まず音声ファイルを読み込み、Score.recordNRTを用いて(実時間よりも速く)ピッチ情報を取得、別途、波形処理ソフトでも確認できるように一旦pch.wavに書き出す(PitchSort.score)。

その後、再度pch.wavを読み込み、各周波数の開始位置と持続時間を集計する。但し、pch.wavのデータはコントロールレート(kr)であるため、64サンプル毎でしか記録されていない。Pitchの出力はコントロールレートしか用意されていないが、K2A.arを用いてオーディオレートに変換すると何故か補完が行われるため、後の処理に支障を来す。

そのため、些か遠回りだが読み込んだpch.wavを64サンプルごとにサンプル&ホールドするという方法でオーディオレートに変換する(PitchSort.sort)。その後はソート済みのデータ(開始サンプル、持続サンプル数、周波数)に従って、入力音源を再構成し、出力する(PitchSort.audio)。

さて、音楽を無意味化すること、それ自体の意味について問うのも一興ではある――筆者は何度となくPitchSortのアルゴリズムを用いてライブパフォーマンスを行っている――が、本稿の真の目的は、波形データの非実時間処理(Score.recordNRT)と、クラスファイルの実例を示すことであった。音楽の無意味化という意味不明の課題でも、プログラミングにおいては良い練習になるかも知れない。

話は変わるが、何らかのデータを音に変換する可聴化(sonification)に基づく音楽作品は何故「必ずや」失敗するのか。筆者は過去に一度だけ、2011年3月11日前後の詳細な地震データに基づく制作をしたことがあった(元データについては本稿で初めて述べる)。あえて元データを「音楽化」することなく、単に「可聴化」するに留めたことには、恐らく何らかの意図があったと思うが、当然今となっては覚えていない。

補足:ソートアルゴリズムによる興味深い作品として、Erik CarlsonAlphabetized Winterreise」を挙げよう。シューベルト「冬の旅」全曲を歌詞に基づいてソートしたものだが、実演には最低二人の歌手が必要であり、現在も未初演と思われる。近年、既存の録音の編集によるリアライズが確認できるようになったが、楽譜よりも面白いとは思えない。何故だろうか。


この記事が気に入ったらサポートをしてみませんか?