このページではあるデータをアルゴリズムに基づいて別のデータに置き換えることで、新たなデータを生み出すアプローチを紹介します。これはテキストを音楽にしたり、株価や太陽の黒点の情報など様々な音楽以外のデータを作曲に利用するようなアプローチです。
Data Mapping (データマッピング)とは
データマッピングとは、2つの異なるデータを関連づけるための過程を意味します。ソースとなるデータを目的のデータに到達するようにルールを策定します。データマッピングにおいては以下のような手順が踏まれます。
- 2つのデータ間での変形や仲介
- 分析によって2つのデータの関連性を調べる
- データの中から隠れた特性を調べる
- 複雑なデータベースをシンプルなデータベースに移行させる
- マッピングにおいて必要の無いデータを削除したり無視したりする
これは企業間の様々な情報のやり取りなどにも利用されており、ある会社で作成されたデータを別の会社の規定に基づいてフォーマットされた状態のデータになるようにデータマッピングを利用します。このデータマッピングのシステム自体が商品となる場合もあります。
音楽におけるデータマッピング
音楽において最初にデータマッピングの概念を使用したのは、おそらくGuido d’Arezzo(991-1031年頃)という10世紀のイタリアの修道士兼音楽理論家兼作曲家です。
彼が行ったデータマッピングによる作曲は、音楽史上最も古いルールベースの作曲技法、すなわち現在で言うアルゴリズミックコンポジションや自動作曲に該当するアプローチです。
彼はラテン語のテキストの母音をピッチに割り当て、単旋律の音楽を生成しました。 (下記の図参照)
存命の現代作曲家Arvo Pärtもこの手の手法で作曲を行った例があります。
詳しくはここに書ききれるボリュームではないため、下記の文献をご参照ください。
Medieval Music (The Norton Introduction to Music History)
The Renaissance Reform of Medieval Music Theory: Guido of Arezzo between Myth and History
Arvo Part (Oxford Studies of Composers)
Mapping of vowels on tone pitches by Guido d’Arezzo
Pitches | G2 | A2 | B2 | C3 | D3 | E3 | F3 | G3 | A3 | B3 | C4 | D4 | E4 | F4 | G4 | A4 |
Vowels | a | e | i | o | u | a | e | i | o | u | a | e | i | o | u | a |
Vowels | o | u | a | e | i | o | u | a | e | i | o | u | a | e | i | o |
Guido d’Arezzo
この時代の音楽家、作曲家、音楽理論家はものを読み書きできた聖職者に限られており、Guidoも例外無く聖職者です。
Micrologusというタイトルの彼の論文は中世の音楽に絶大な影響を及ぼしました。
彼の最大の功績の一つは、死後1000年経過した現在でも尚、支配的なものがあります。それはソルミゼーションです。
「Ut queant laxis(聖ヨハネ賛歌)
」は、6つの句が音階のうちの一つで始まり、しかも1句ごとに上昇するようになっていたため、句の最初の文字「Ut Re Mi Fa Sol La」を利用し「階名唱法」考案しました。これが現在のドレミファソラです。後にSiの音が加わり、UtはDoとなりました。
グイードニアンハンド
更に彼はグイードニアンハンドと呼ばれる方法を使い、聖歌の記憶術を改善した事でも有名です。当時の音楽の世界では、音を正確に表記する方法が確立されておらず、聖歌隊は聖歌を暗譜し、口承で次の代に伝え方法をとっていたため、長い歳月を重ねる間に聖歌自体が変化してしまうことも珍しくなく、暗譜する量や時間にも限りがありました。
それを改善するため、彼は、4本の線の上に四角い音符を書く現在の記譜法の原型を考案しました。
Javaによるテキストデータの解析
public class HelloWorldApp {
public static void main(String[] args) {
byte[] b;
String str = "x";
b = str.getBytes();
System.out.println((int)b[0]);
}
}
上記のJavaのプログラムは文字データを数値化する最も単純なプログラムです。コンパイルし、実行して各文字情報がどのように数値化されていくのかを確かめてください。
テキストデータに含まれる文字のバイトを取得し、数値化しています。上記の写真ではxという文字から120という数値を得ていることがわかります。つまりこのgetBytes()の仕組みが文字データと数値データを繋ぐルール、データマッピングアルゴリズムとなっています。
Max/MSPでの実装
Guidoの技法を参考に、今回のアルゴリズムを組んでおりますが、彼の時代の音楽はモノフォニックです。今の時代に即したホモリズミックなマテリアルを生成するために今回はMax/MSPにおけるJava、mxjオブジェクトでアルファベットのテキストを解析し、対応するピッチをデータマッピングすることで音楽を自動生成するプログラムを構築しています。
mxjで読み込んでいるソース
import com.cycling74.max.*; public class SpeakTestGloria extends MaxObject implements Executable { private MaxClock cl; private static final int MAX_WORD_LENGTH = 16; private static final int CHAR_TIME_BASE = 420; private static int[] map = null; private String[] txt_atoms = null; private int current_word = 0; static { int a,b,c,d,e,f,g; a = 48; b = 50; c = 51; d = 53; e = 55; f = 57; g = 58; map = new int[]{a,b,c,d,e,f,g, (a + 12),(b + 12),(c + 12),(d+12),(e+12),(f+12),(g+12), (a + 24),(b + 24),(c + 24),(d-24),(e-24),(f-24),(g-24), (a - 12),(b - 12),(c + - 12),(d - 12),(e - 12)}; }; public SpeakTestGloria(Atom[] args){ int[] outlet_types = new int[MAX_WORD_LENGTH +1]; for(int i = 0; i < MAX_WORD_LENGTH;i++) outlet_types[i] = DataTypes.INT; outlet_types[MAX_WORD_LENGTH] = DataTypes.MESSAGE; declareInlets(new int[]{ DataTypes.MESSAGE }); declareOutlets(outlet_types); cl = new MaxClock(this); } public void setText(Atom[] args){ txt_atoms = new String[args.length]; for(int i = 0; i < args.length;i++) txt_atoms[i] = args[i].getString(); } public void bang(){ if(txt_atoms == null){ System.err.println("setText before start"); return; } cl.delay(0); } public void execute(){ byte[] b; int len; if(current_word >= txt_atoms.length) current_word = 0; b = txt_atoms[current_word].getBytes(); len = b.length; if(len >= MAX_WORD_LENGTH) len = MAX_WORD_LENGTH; outlet(MAX_WORD_LENGTH, txt_atoms[current_word]); for(int i = 0; i < len; i++){ outlet(i,map[((int)b[i]) - 97]); } cl.delay((double)CHAR_TIME_BASE * len); current_word++; } public void stop(Atom[] args){ cl.unset(); current_word = 0; } protected void notifyDeleted(){ cl.release(); } }
このプログラムはテキスト次第で生成される音楽は全く異なります。ピッチの集合はあらかじめ配列に記述をします。Guidoの時代と同じダイアトニック集合がピッチクラスとして選択されており、音域は最大で3オクターブとなっています。
int a,b,c,d,e,f,g; a = 48; b = 50; c = 51; d = 53; e = 55; f = 57; g = 58; map = new int[]{a,b,c,d,e,f,g, (a + 12),(b + 12),(c + 12),(d+12),(e+12),(f+12),(g+12), (a + 24),(b + 24),(c + 24),(d-24),(e-24),(f-24),(g-24), (a - 12),(b - 12),(c + - 12),(d - 12),(e - 12)}; };
生成されるタイミング、リズムは単語の長さによって変化します。ここでも単語の長さが音化へとデータマッピングされています。
cl.delay((double)CHAR_TIME_BASE * len);
という命令が音の長さに関わっている部分です。
下記の映像はJitterなどは使用しておらず、あくまこのような内部的な仕組みで音楽が生成されていることを示すためのデモンストレーションです。 あくまでホモリズミックにMidiノートナンバーに対応した数列が生成されます。これをMIDIデータとしてシンセサイザーを鳴らす事もMax内部で音響合成することも可能です。
Max/MSPを用いた作品
この作品ではテキストから音楽を生成すると同時に、その時刻で解析しているテキストを表示します。この技術は初歩の初歩であり、Jitterの映像処理やOpenGLなどのグラフィックスと連動させることで更なるインタラクションを考えることも可能でしょう。