前回、音楽の一部をJavaで作りましたが改善が必要な点があります。それは「いつ演奏するか」という時間の問題です。ここで使ったプレリュードは16分音符が切れ目なく続くものでした。このため16分音符一つ分の時間が決まっている場合、それを足しあげていくと次に演奏する音の開始時間は簡単に求められます。しかし通常はメロディはもっと複雑で開始時間を求めるのは簡単でない場合が多いです。
Javaでの実装:平均律クラヴィーアBWV846プレリュードの一部
音楽と時間
前回の実装では16分音符を0.25秒としていました。
double duration = 0.25;
テンポは通常4分音符が1分間に何回演奏されるかを基準にします。使われる単位は英語でBeats Per Minuteと言われて略語でBPM、bpmとも表記されます。
今回の場合4分音符の時間は16分音の4個分の時間に等しいので1秒となります。これが1分間に演奏されるのはちょうど60回です。よってこの曲のbpmは60となります。
例えば「テンポを早くしよう」ということになるとbpmの値を増やします。80にした場合さっきと逆の計算をすると16分音符の長さは0.1875秒となります。プログラムの中でもこのようにbpmによるテンポ設定ができるようにしたいと思います。
拍子
他に時間に関係する音楽の概念として拍子というものがあります。一小節の中にどのくらいの音符が入るかを定義するものです。楽譜の最初に分数のように記されています。
一番多く見かけるのは4/4という表記です。これは分母にあたる4が単位となる音符、分子はその単位の音符がいくつ入るかを表しています。「4分音符が4拍」という言い方をします。
3/4であれば4分音符が3個、9/8であれば8分音符が9個となります。
この分母は一般に2の乗数以外になることはありません。大抵は2、4、8あたりでまれに16、32、64というものもあります。
大抵の曲は最初に設定された拍子で最後までつづくのですが曲によっては部分的にあるいは常時拍子が変わるものがあります。
人が設定したい項目
テンポと拍子を考えた時、人が設定したい値は以下のものになります。
- テンポはx小節目のy拍目にbpmで設定する
- 拍子はx小節目に「y分音符がz拍」で設定する
「拍」は整数でなく小数になりえます。
一方プログラムの方はこの設定から以下のような情報が必要となります。
- 開始からx秒目にy秒間の音を演奏する
実装内容の検討
この変換を行うプログラムを作ります。前提としては拍子もテンポも演奏処理の前に確定している必要があります。あるパートを演奏した後でテンポを変えて他のパートを演奏するとパート間で音がずれてしまいます。
曲の位置を小節と拍の二つの値で管理するのは面倒なので確定後は拍だけにしたいと思います。通常は小節は1ベースで数えますがプログラムでは不要なバグを防ぐため0ベースとします。
以下ユースケースを出して考えます。
小節 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
拍子設定 | 4/4 | 3/4 | 3/8 | ||||||||
位置(拍) | 0 | 4 | 8 | 12 | 16 | 19 | 22 | 25 | 28 | 29.5 | 31 |
最初の0小節目は4分音4拍なので小節が増えるごとに4ずつ増えていきます。4小節目で拍子が4分音符3拍にかわるのでこの後は3ずつ増えます。8小節目からは8分音符3拍に変わります。8分音符は4分音符の半分なので単位は0.5になりこれが3拍なので一小節の長さは1.5になります。このあとは1.5ずつ増えることになります。
次回は小節と拍から位置を求める実装を考えます。