なんと、時刻表が音楽になってしまった!エレクトロニカ、ダンス、現代音楽、エクスペリメンタル・メタル、それからチップチューンに動物の鳴き声まで、ヘンな音楽が沢山詰まったCDの登場です。面白い音楽が好きなら、聴いてみるのも良いかもよ。
“自動生成された曲なのに巧みな加工のおかげか誰かのパロディとして聴ける曲もあり(例えばヴィシネグラツキに捧げられた〈目白駅〉の微分音音楽とか、ペンデレツキに捧げられた〈神田駅〉のトーン・クラスタなど)、全体がよく練られた遊びになっているのが面白い” - レコード芸術2012年8月号『クラシック版インターネット配信音源ガイド』
JR東日本のサイトのURLを、ライナーノートに間違って記載してました。ごめんなさい。
| × | http://www.jreasttimetable.jp/ |
| ○ | http://www.jreast-timetable.jp/ |
ある日、ふと思い付きました。「時刻表を音楽にしたら面白いかもしれない」。早速、ものは試しというわけで、発着が多そうなJR新宿駅の時刻表を音楽にしてみました。すると、ラッシュアワーで音もラッシュしていたり、終電間際は音数が減って寂しい雰囲気になったり、意外と面白い曲になりました。そこで山手線一周分、29駅の時刻表を音楽にしたのがこのCDです。
時刻表の音楽への変換は、具体的には以下のような手法を採りました。まず、時刻表の1分を16分音符として扱い、電車の発車に合わせて音を出すようにします。
音高についてはあらかじめ音列を用意した上で、
(路線ID×「時」+「分」) mod 音列の要素数
で算出しました。modは剰余です。この式に出てくる「路線ID」というのは、時刻表のどの路線を使用したかというもので、たとえば品川駅の場合、「埼京線・川越線 大宮・川越方面(北行)」が1、「埼京線・川越線 大崎方面(南行)」が2となります。使用した時刻表は、2008年3月23日時点でJR東日本のWebサイトに掲載されていたものです。
特定の人物に捧げた曲もありますがそれほど深い意味はありません(一部パロディのようなものはあります)。また、秋葉原駅や上野駅などいくつかの駅を除いて、曲と駅との関連もありません。できあがった曲には、リズムを付加したりイントロやエンディングを追加したものもあります。ただし、発音タイミングや音高は時刻表を元にしたものをそのまま使用しています。
左側の木管五重奏はハ長調(Cメジャー)で、右側の木管五重奏は変イ短調(Abマイナー)で、それぞれ演奏しています。3回に1回はスタッカートで強く、残りの2回はテヌートで弱く吹かれます。
6台の太鼓による組太鼓です。音列としては、音高ではなく、太鼓を叩く強さを使用しています。
全体を通して7拍子のミニマルなフレーズを繰り返して演奏しています。発車するタイミングで発音するのではなく、発車するタイミングで、計算式を元にした個数分だけ、弾くはずの音を変移させるようにしました。
外回りと内回り2台分のモーグ風シンセベースに、TR-808風のリズムトラックを付加しました。
恵比寿駅の発車メロディーにもなっている映画「第三の男」のテーマ曲の冒頭の7音を、繰り返し、電車が発車するタイミングで鳴らしています。路線ごとにオクターブを変えてあります。
渋谷駅に通る6本の路線をそれぞれギターの6本の弦に見立て、ペンタトニック・スケールを演奏しています。
「in C」風のパルスをバックに、発車時刻の数列を元に作られた32分音符4つ分のフレーズが演奏されます。
「ヘリコプター弦楽四重奏曲」と同様、通常の弦楽四重奏とは逆の定位になっています。序盤・中盤・終盤で、それぞれフレーズが上昇・停滞・下降します。
13本ある路線のそれぞれで、チェレスタの音が奏でられます。音列としては半音階を使用しました。ムーンライトえちごは1オクターブ上、通勤快速は2オクターブ上、のように、速い電車ほど高い音で演奏しています。オギュスト・ミュステルは、チェレスタの発明者です。
複数のパーカッションを並べ、それを音列としました。時刻表の時間に応じてズレの幅を変えながら、パーカッションの音が「フェイズ」されて演奏されます。
五反田駅と同様、全体を通して同じフレーズが繰り返されます。ただし発車のタイミングで音を変移させるのではなく、発車のタイミングでフレーズの演奏スピードを2倍・3倍・4倍と速くしています。
4分音(半音の半音) ピアノによる演奏です。ペダルは踏みっぱなしです。
中国に源流を持つ雅楽の音階の中から、律旋法を音列として使用しました。新宿駅と同じく、速い電車ほど高い音で演奏したり、水の音に変換したりしています。
ロバート・フリップ風のミニマルフレーズが、時刻表の時間が進むごとに全音づつ高くなって行きます。発車のタイミングで音を変移させています。また、全体にフリッパートロニクス風のエフェクトをかけました。
箏曲「六段」と同じ双調・平調子に調弦したものを音列として使用しました。路線によって音の定位を変えたりはせず一台の箏の曲としています。発音タイミングが重なる場合はグリッサンドや押し手を使用しました。
電車が発車するタイミングで音を鳴らすのではなく、時刻表での30分間の間は音を溜めておいて、30分に1回だけ音を出しています。同じ高さの音が重なった場合はオクターブを変更しました。
ブリテンの「青少年のための管弦楽入門」と同じ順番で各楽器が演奏されます。「むち」の後にトゥッティで演奏されるのも同様です。
開放弦だけを使った弦楽四重奏です。
「春の祭典」の「乙女達の踊り」を曲解してみました。
サンプリングされたウグイスの声のピッチを変更し、音列として使用しました。途中、ウグイス嬢の声のサンプリング音が挿入されます。
48種類の動物の鳴き声が音列として使用されています。オープニングとエンディングのみ、計算式で算出した鳴き声以外の音を使用しています。使用した動物の鳴き声は、以下の通りです。
アシカ/アヒル/アマガエル/イヌ/インコ/ウシ/ウシガエル/ウマ/オウム/オオカミ/オランウータン/カッコウ/カナリヤ/カラス/ガチョウ/クマ/コアラ/ゴリラ/サイ/シジュウカラ/スズムシ/スズメ/ゾウ/チンパンジー/ツクツクボウシ/ツル/トラ/ニホンザル/ニワトリ/ネコ/ハイエナ/ハクチョウ/ハト/パンダ/ヒキガエル/ヒバリ/ヒョウ/ヒヨコ/フクロウ/フラミンゴ/ブタ/ホトトギス/マントヒヒ/メジロ/モズ/ヤギ/ライオン/ラクダ
メシュガー(フレドリック・トーデンダルがギタリストをつとめるデスメタルバンド)風の変拍子(13×4+12) をメインリズムに、ダウンチューニングしたギターで演奏しています。
チップチューンです。ベースのフレーズは、ある「アニソン」から引用しました。また、発車のタイミングで「オタクの女子が言いそうな言葉」を発音しています。YMCKが開発したMagical 8bit PlugというVSTインストゥルメントを使用しました。
音列としてトーン・クラスターを使用しました。路線ごとにオクターブを変えたクラスターが、発車のタイミングで上下に半音づつ移動するようにしています。
電車が発車するタイミングでメトロノームの音を鳴らしています。ただし、全15路線をそれぞれ「路線ID×256分音符」だけ遅らせてあります。
ケチャ風の音楽です。
E(ホ音)の第1倍音(165Hz)から第29倍音(4,785Hz)までの音の中から時刻表の時間に応じて音を選択し、恵比寿駅と同様、順番に鳴らしています。
電車が発車するタイミングで休符を演奏しています。
「世の終わりのための四重奏曲」と同じ編成で、「移調の限られた旋法」を音列として演奏しています。
円環構造に於いて必然的に生じる空と無をウロボロスがごとき矛盾の上で、みたいなことを書くとそれっぽいですが、単に次のボーナストラックまでの無音部分です。
日本最北端の駅である稚内駅では、1日8本しか電車が発車しません。その8本の電車が発車するタイミングで、バッハ主題を2回演奏しています。
時刻表を音楽に変換する際、手で変換を行っていたらものすごく時間がかかってしまいます(実は最初は手動でやろうとしたんですが、すぐに諦めました)。そこで、時刻表から音楽への変換は、Perlというプログラム言語でスクリプトを書いて実行しました。そして、スクリプトが出力したMMLを、MML2MIDというソフトウェアを使ってMIDIファイルに変換し、それをさらにシーケンサーソフトを使って編集しました。
時刻表のデータは、@timesという名前の配列に格納されています。各データは、以下のような感じです。
my @times; $times[1]=<<_; 06 25 通快 川 06 34 06 39 通快 川 06 43 武 ....
「時」と「分」がタブで区切られています。列車の種類に関して追加の情報が存在する行もあります。
以下のプログラムでは、発車時間のセットや休符の圧縮など、本題と関係のないコードは省略しています。また、コードはあくまでも説明のためのものなので、動かないかもしれません。
use strict;
my %all_notes = (
flute_l => [qw(
o5c o5d o5e o5f o5g o5a o5b
o6c o6d o6e o6f o6g o6a o6b
)],
oboe_l => [qw(
o4c o4d o4e o4f o4g o4a o4b
o5c o5d o5e o5f o5g o5a o5b
)],
fagot_l => [qw(
o2c o2d o2e o2f o2g o2a o2b
o3c o3d o3e o3f o3g o3a o3b
)],
horn_l => [qw(
o2c o2d o2e o2f o2g o2a o2b
o3c o3d o3e o3f o3g o3a o3b
o4c o4d o4e o4f o4g o4a o4b
)],
clarinet_l => [qw(
o3c o3d o3e o3f o3g o3a o3b
o4c o4d o4e o4f o4g o4a o4b
o5c o5d o5e o5f o5g o5a o5b
)],
flute_r => [qw(
o4a- o4b- o5c- o5d- o5e- o5f- o5g-
o5a- o5b- o6c- o6d- o6e- o6f- o6g-
)],
oboe_r => [qw(
o4a- o4b- o5c- o5d- o5e- o5f- o5g-
)],
fagot_r => [qw(
o2a- o2b- o3c- o3d- o3e- o3f- o3g-
)],
horn_r => [qw(
o1a- o1b- o2c- o2d- o2e- o2f- o2g-
o2a- o2b- o3c- o3d- o3e- o3f- o3g-
o3a- o3b- o4c- o4d- o4e- o4f- o4g-
)],
clarinet_r => [qw(
o3a- o3b- o4c- o4d- o4e- o4f- o4g-
o4a- o4b- o5c- o5d- o5e- o5f- o5g-
)],
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# 準備
my $current_times = $times[$i];
next unless defined $current_times;
my $prev_minutes = 0;
my $prev_oct = '';
my $velocity = 0;
$mml .= sprintf('%s C%d"%d" ', chr(65 + $i), $i, $i) . " \n";
$mml .= chr(65 + $i) . ' ';
# selecting note series
my @notes;
if ($i == 1 || $i == 2) {
@notes = @{$all_notes{'flute' . ($i % 2 ? '_l' : '_r')}} ;
}elsif($i == 3 || $i == 4){
@notes = @{$all_notes{'oboe' . ($i % 2 ? '_l' : '_r')}} ;
}elsif($i == 5 || $i == 6){
@notes = @{$all_notes{'clarinet' . ($i % 2 ? '_l' : '_r')}} ;
}elsif($i == 7 || $i == 8){
@notes = @{$all_notes{'horn' . ($i % 2 ? '_l' : '_r')}} ;
}elsif($i==9 || $i==10){
@notes = @{$all_notes{'fagot' . ($i % 2 ? '_l' : '_r')}} ;
}
foreach my $time(split(/\n/, $current_times)) {
# 「時」、「分」、それから追加情報をまとめる
my($h, $m, $info) = split(/\s+/, $time);
# 数字以外のゴミを削除
$h =~ tr/0-9//cd;
$m =~ tr/0-9//cd;
# 経過時間を計算
# 基準となるのは午前4時
my $minutes = $h * 60 + $m - 4 * 60;
# 必要な休符をセット
if ($prev_minutes == 0 && $minutes != 0) {
$mml .= 'r16';
}
if ($minutes - $prev_minutes > 1) {
$mml .= 'r16' x ($minutes - $prev_minutes - 1);
}
# 音高の選択
my $this_note = $notes[($i * $h + $m) % @notes];
# 同じオクターブはまとめる
if ($this_note =~ /^o(\d)/) {
if ($prev_oct == $1) {
$this_note =~ s/^o$1//;
} else {
$prev_oct = $1 ;
}
}
# 音の強弱や流さを決定
if ($velocity == 0) {
$this_note = "k64${this_note}";
} elsif ($velocity == 1) {
$this_note = "k96${this_note}";
}
# 算出した音をMMLに追加
$mml .= $this_note . '16';
# その他の処理
$prev_minutes = $minutes;
$velocity = ($velocity + 1) % 3;
}
$mml .= "\n";
}
use strict;
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音の強弱を決定
my $is_loud = ($i * $h + $m ) % 4;
$mml .= $is_loud ? 'k100c16' : 'k44c16';
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my %riffs = (
l => [qw(o4e o4f+ o4g o4f+ o4a o4g o4f+)],
r => [qw(o4a o4b o5c o4b o5d o5c o4b)],
);
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my @time_hashes;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
$time_hashes[$i] = {};
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# この発車時刻の音はズラされる予定
$time_hashes[$i]->{sprintf('%02d%02d', $h, $m)} = 1;
}
}
my $mml = '';
for my $i(0 .. $#times) {
my $j = 0;
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# どちらのリフを使うか決定
my @riff = @{$riffs{$i == 1 ? 'l' : 'r'}};
my $prev_oct = '';
# すべての時刻で音が出る
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $this_note;
if(exists $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)}){
# 発車時刻の場合、音を変移させる
$this_note = $riff[($j + $i * $h + $m) % @riff];
} else {
$this_note = $riff[$j];
}
$j = ($j + 1) % @riff;
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note;
}
}
$mml .= "\n";
}
use strict;
my @notes=qw(c c+ d d+ e f f+ g g+ a a+ b);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音高を決定
$mml .= $notes[($i * $h + $m)% @notes] . '16';
# その他の処理
$prev_minutes=$minutes;
}
$mml .= "\n ";
}
use strict;
my @riff = qw(g g+ a g+ a g+ a);
my @times;
# 略
# 時刻がセットされている
# 音の選択
my @time_hashes;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
$time_hashes[$i] = {};
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音のセット
$time_hashes[$i]->{sprintf('%02d%02d', $h, $m)} = $riff[$j];
# 次の音を使う予約
$j = ($j + 1) % @riff;
}
}
my $mml = '';
for my $i(0 .. $#times) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
foreach my $time (split(/\n/, $current_times)){
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# この時刻の音をセット
$mml .= $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)} . '16';
# その他の処理
$prev_minutes=$minutes;
}
$mml .= "\n";
}
use strict;
my %notes = (
A => [
[qw(o2f+ o2a)],
[qw(o2b o3c)],
[qw(o3e o3f+)],
[qw(o3a o3b)],
[qw(o4c+ o4e)],
[qw(o4f+ o4a)],
],
D => [
[qw(o2b o3d)],
[qw(o3e o3f+)],
[qw(o3a o3b)],
[qw(o4d o4e)],
[qw(o4f+ o4a)],
[qw(o4b o5d)],
],
E => [
[qw(o3c+ o3e)],
[qw(o3f+ o3g+)],
[qw(o3b o4c+)],
[qw(o4e o4f+)],
[qw(o4g+ o4b)],
[qw(o5c+ o5e)],
],
);
my @chords = qw(A A A A D D A A E E D D A A A A);
my @times;
# 略
# 時刻がセットされている
# コードの決定
my %time_to_chords;
my $chord_position = 0;
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $time = sprintf('%02d%02d', $h, $m);
if ($chord_position < 4 * 4) {
$time_to_chords{$time} = 'A';
} elsif ($chord_position < 4 * 6) {
$time_to_chords{$time} = 'D';
} elsif ($chord_position < 4 * 8) {
$time_to_chords{$time} = 'A';
} elsif ($chord_position < 4 * 10) {
$time_to_chords{$time} = 'E';
} elsif ($chord_position < 4 * 12) {
$time_to_chords{$time} = 'D';
} else {
$time_to_chords{$time} = 'A';
}
$chord_position = ($chord_position + 1) % 64
}
}
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音の選択
my $this_chord = $time_to_chords{sprintf('%02d%02d', $h, $m)};
my $note_index = ($i * $h + $m) % @{$notes{$this_chord}};
my $this_note = $notes{$this_chord}->[$i - 1]->[$note_index] . '16';
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# 音の強さを決定
if ($m % 4 == 0) {
$mml .= "k96${this_note}";
} elsif ($m % 4 == 2) {
$mml .= "k88${this_note}";
} else {
$mml .= "k72${this_note}";
}
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @notes = qw(c d r e f r g a r b);
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my @time_hashes;
# 略
# 詳しくは五反田駅のソースを参照のこと
my $mml = '';
for my $i(0 .. $#times) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# そして準備
my $prev_hhmm = '';
my $prev_pattern = 'r16';
# ひとつのパターンに16分音符を4つ使うので、全時刻をチェックしないといけない
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $this_note;
if (exists $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)}) {
# 発車時刻には最初のふたつの音を使用
$mml .= join(
'',
map{
$notes[$_] . '32'
}split(//, sprintf('%02d', $h))
);
$prev_hhmm = sprintf('%02d%02d', $h, $m);
} elsif ($prev_hhmm) {
# 残りを使用
$prev_pattern = join(
'',
map{
$notes[$_] . '32'
}split(//, substr($prev_hhmm, 2, 2))
);
$mml .= $prev_pattern;
$prev_hhmm = '';
} else {
# おやすみ
$mml .= 'r16';
}
}
}
$mml .= "\n"
}
use strict;
my %notes = (
violin_up => [qw(
o3g o3g+ o3a o3a+ o3b o4c o4c+ o4d o4d+ o4e o4f o4f+
o4g o4g+ o4a o4a+ o4b o5c o5c+ o5d o5d+ o5e o5f o5f+
o5g o5g+ o5a o5a+ o5b o6c o6c+ o6d o6d+ o6e
)],
viola_up => [qw(
o3c o3c+ o3d o3d+ o3e o3f o3f+ o3g o3g+ o3a o3a+ o3b
o4c o4c+ o4d o4d+ o4e o4f o4f+ o4g o4g+ o4a o4a+ o4b
o5c o5c+ o5d o5d+ o5e o5f o5f+ o5g o5g+ o5a
)],
cello_up => [qw(
o2c o2c+ o2d o2d+ o2e o2f o2f+ o2g o2g+ o2a o2a+ o2b
o3c o3c+ o3d o3d+ o3e o3f o3f+ o3g o3g+ o3a o3a+ o3b
o4c o4c+ o4d o4d+ o4e o4f o4f+ o4g o4g+ o4a
)],
violin_hovering => [qw(o5g o5g+ o5a o5a+ o5b)],
viola_hovering => [qw(o5c o5c+ o5d o5d+ o5e)],
cello_hovering => [qw(o4c o4c+ o4d o4d+ o4e)],
violin_down => [qw(
o6e o6d+ o6d o6c+ o6c o5b o5a+ o5a o5g+ o5g o5f+ o5f
o5e o5d+ o5d o5c+ o5c o4b o4a+ o4a o4g+ o4g o4f+ o4f
o4e o4d+ o4d o4c+ o4c o3b o3a+ o3a o3g+ o3g
)],
viola_down => [qw(
o5a o5g+ o5g o5f+ o5f o5e o5d+ o5d o5c+ o5c o4b o4a+
o4a o4g+ o4g o4f+ o4f o4e o4d+ o4d o4c+ o4c o3b o3a+
o3a o3g+ o3g o3f+ o3f o3e o3d+ o3d o3c+ o3c
)],
cello_down => [qw(
o4a o4g+ o4g o4f+ o4f o4e o4d+ o4d o4c+ o4c o3b o3a+
o3a o3g+ o3g o3f+ o3f o3e o3d+ o3d o3c+ o3c o2b o2a+
o2a o2g+ o2g o2f+ o2f o2e o2d+ o2d o2c+ o2c
)],
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音列の選択
my @this_notes;
if ($i == 1) {
if ($hhmm le '1200') {
@this_notes = @{$notes{cello_up}};
} elsif ($hhmm le '1700') {
@this_notes = @{$notes{cello_hovering}};
} else {
@this_notes = @{$notes{cello_down}};
}
} elsif ($i == 2) {
if ($hhmm le '1200') {
@this_notes = @{$notes{viola_up}};
} elsif ($hhmm le '1700') {
@this_notes = @{$notes{viola_hovering}};
} else {
@this_notes = @{$notes{viola_down}};
}
} else {
if ($hhmm le '1200') {
@this_notes = @{$notes{violin_up}};
} elsif ($hhmm le '1700') {
@this_notes = @{$notes{violin_hovering}};
} else {
@this_notes = @{$notes{violin_down}};
}
}
my $this_note = $this_notes[($i * $h + $m) % @this_notes];
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note . '16';
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @notes = qw(c c+ d d+ e f f+ g g+ a a+ b);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# オクターブの決定
my $octave = 0;
if ($info =~ /中特/ || $info =~ /青特/ || $info =~ /通特/) {
$octave = 1;
} elsif ($info =~ /快ムえ/) {
$octave = 1;
} elsif ($info =~ /通快/ || $info =~ /特快/) {
$octave = 2;
} elsif ($info =~ /特?あ/ || $info =~ /特か/ || $info =~ /H千/) {
$octave = 3;
} elsif ($info =~ /中ラ/ || $info =~ /青ラ/ || $info =~ /ム信/) {
$octave = 3;
} elsif ($info =~ /特/) {
$octave = 3;
} elsif ($info =~ /H古/ || $info =~ /H小/ || $info =~ /NEX/) {
$octave = 3;
} elsif ($info =~ /快/) {
$octave = 1;
}
if ($octave != 0) {
$mml .= '>' x $octave;
}
$mml .= $notes[($i * $h + $m) % @notes] . '16';
if ($octave != 0) {
$mml .= '<' x $octave;
}
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @notes = qw(d d+ e);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# パターンを生成
my $loops;
if ($h < 8) {
$loops = 0;
} elsif ($h < 12) {
$loops = 1;
} elsif ($h < 18) {
$loops = 2;
} elsif ($h < 22) {
$loops = 1;
} else {
$loops = 0;
}
if ($loops == 0) {
if ($i == 1) {
$mml .= 'p84';
} else {
$mml .= 'p104';
}
$mml .= 'k96' . $notes[($i * $h + $m) % @notes] . '16';
} elsif ($loops == 1) {
if ($i == 1) {
$mml .= 'p84';
} else {
$mml .= 'p104';
}
$mml .= 'k96' . $notes[($i * $h + $m) % @notes] . '32';
if ($i == 1) {
$mml .= 'p24';
} else {
$mml .= 'p44';
}
$mml .= 'k84' . $notes[($i * $h + $m + 1) % @notes] . '32';
} else {
if ($i == 1) {
$mml .= 'p54';
} else {
$mml .= 'p74';
}
$mml .= 'l%4k96' . $notes[($i * $h + $m) % @notes];
if ($i == 1) {
$mml .= 'p104';
} else {
$mml .= 'p124';
}
$mml .= 'l%4k84' . $notes[($i * $h + $m + 1) % @notes];
if ($i == 1) {
$mml .= 'p4';
} else {
$mml .= 'p24';
}
$mml .= 'l%4k62' . $notes[($i * $h + $m + 2) % @notes];
}
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @riff = qw(o3f+ g+ a+ o4c d e f+ g+ a+ o5c d e);
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my @time_hashes;
# 略
# 詳しくは五反田駅のソースを参照のこと
my $mml = '';
for my $i(0 .. $#times) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 準備
my $j = 0;
# すべての時刻で音が出る
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $this_note;
if (exists $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)}) {
# テンポを変更する
my $pattern = ($i * $h + $m) % 3;
if ($pattern == 0) {
# 2倍
$mml .= $riff[$j] . '32';
$j = ($j + 1) % @riff;
$mml .= $riff[$j] . '32';
} elsif ($pattern == 1){
# 3倍
$mml .= 'l%4';
$mml .= $riff[$j];
for (1 .. 2) {
$j = ($j + 1) % @riff;
$mml .= $riff[$j];
}
} else {
# 4倍
$mml .= $riff[$j].'64';
for (1 .. 3) {
$j = ($j + 1) % @riff;
$mml .= $riff[$j] . '64';
}
}
} else {
# 普通のスピード
$mml .= $riff[$j] . '16';
}
# 次の音へ
$j = ($j + 1) % @riff;
}
}
$mml .= "\n";
}
use strict;
# 「^」は4分音だけ高い音を意味する
my @notes = qw(
o2c o3c o4c o5c o6c o4c o5c o6c o4c o5c o6c
o2c^ o3c^ o4c^ o5c^ o6c^ o4c^ o5c^ o6c^ o4c^ o5c^ o6c^
o2e o3e o4e o5e o6e o4e o5e o6e o4e o5e o6e
o2e^ o3e^ o4e^ o5e^ o6e^ o4e^ o5e^ o6e^ o4e^ o5e^ o6e^
o2g+ o3g+ o4g+ o5g+ o6g+ o4g+ o5g+ o6g+ o4g+ o5g+ o6g+
o2g+^ o3g+^ o4g+^ o5g+^ o6g+^ o4g+^ o5g+^ o6g+^ o4g+^ o5g+^ o6g+^
o2c+ o3c+ o4c+ o5c+ o6c+ o4c+ o5c+ o6c+ o4c+ o5c+ o6c+
o2c+^ o3c+^ o4c+^ o5c+^ o6c+^ o4c+^ o5c+^ o6c+^ o4c+^ o5c+^ o6c+^
o2f o3f o4f o5f o6f o4f o5f o6f o4f o5f o6f
o2f^ o3f^ o4f^ o5f^ o6f^ o4f^ o5f^ o6f^ o4f^ o5f^ o6f^
o2a o3a o4a o5a o6a o4a o5a o6a o4a o5a o6a
o2a^ o3a^ o4a^ o5a^ o6a^ o4a^ o5a^ o6a^ o4a^ o5a^ o6a^
o2d o3d o4d o5d o6d o4d o5d o6d o4d o5d o6d
o2d^ o3d^ o4d^ o5d^ o6d^ o4d^ o5d^ o6d^ o4d^ o5d^ o6d^
o2f+ o3f+ o4f+ o5f+ o6f+ o4f+ o5f+ o6f+ o4f+ o5f+ o6f+
o2f+^ o3f+^ o4f+^ o5f+^ o6f+^ o4f+^ o5f+^ o6f+^ o4f+^ o5f+^ o6f+^
o2a+ o3a+ o4a+ o5a+ o6a+ o4a+ o5a+ o6a+ o4a+ o5a+ o6a+
o2a+^ o3a+^ o4a+^ o5a+^ o6a+^ o4a+^ o5a+^ o6a+^ o4a+^ o5a+^ o6a+^
o2d+ o3d+ o4d+ o5d+ o6d+ o4d+ o5d+ o6d+ o4d+ o5d+ o6d+
o2d+^ o3d+^ o4d+^ o5d+^ o6d+^ o4d+^ o5d+^ o6d+^ o4d+^ o5d+^ o6d+^
o2g o3g o4g o5g o6g o4g o5g o6g o4g o5g o6g
o2g^ o3g^ o4g^ o5g^ o6g^ o4g^ o5g^ o6g^ o4g^ o5g^ o6g^
o2b o3b o4b o5b o6b o4b o5b o6b o4b o5b o6b
o2b^ o3b^ o4b^ o5b^ o6b^ o4b^ o5b^ o6b^ o4b^ o5b^ o6b^
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
# 通常の音と4分音は別のMIDIチャンネルである必要がある
my $prev_oct_normal = '';
my $prev_oct_qup = '';
my $mml_normal .= sprintf('%s C%d"%d" ', chr(65 + $i), $i, $i) . " \n";
$mml_normal .= chr(65 + $i) . ' P ';
my $mml_qup .= sprintf('%s C%d"%d" ', chr(65 + $i), $i, $i) . " \n";
$mml_qup .= chr(65 + $i) . ' BS80 P ';
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音の強さの決定
my $velocity_base = 40;
if ($hhmm ge '0700' && $hhmm lt '1000') {
$velocity_base = 80;
} elsif ($hhmm ge '1000' && $hhmm lt '1615') {
$velocity_base = 40;
} elsif ($hhmm ge '1615' && $hhmm lt '2156') {
$velocity_base = 80;
} else {
$velocity_base = 40;
}
# 音の選択
my $this_note = $notes[($h + $i * $m) % @notes] . '16';
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
if ($this_note =~ s/\^//) {
$mml_normal .= 'r16';
$mml_qup .= 'P k' . ($velocity_base + ($i * $h + $m) % 20) . $this_note;
} else {
$mml_normal .= 'P k' . ($velocity_base + ($i * $h + $m) % 20) . $this_note;
$mml_qup .= 'r16';
}
# その他の処理
$prev_minutes=$minutes;
}
$mml .= $mml_normal . "\n" . $mml_qup . "\n"
}
use strict;
my @notes = qw(c d f g a);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# オクターブの決定
my $octave = 0;
if ($info =~ /通快/ || $info =~ /特快/) {
$octave = 2;
} elsif ($info =~ /特/ || $info =~ /ム/ || $info =~ /NEX/) {
$octave = 3;
} elsif ($info =~/快/) {
$octave = 1;
}
if ($octave != 0) {
$mml .= '>' x $octave;
}
$mml .= $notes[($i * $h + $m) % @notes] . '16';
if ($octave != 0) {
$mml .= '<' x $octave;
}
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my %riffs;
$riffs{4} = [qw(o3f o3c+ o2b o3c+)];
$riffs{5} = $riffs{4};
$riffs{6} = [qw(o3g o3d+ o3c+ o3d+)];
$riffs{7} = $riffs{6};
$riffs{8} = [qw(o3a o3f o3d+ o3f)];
$riffs{9} = $riffs{8};
$riffs{10} = [qw(o3b o3g o3f o3g)];
$riffs{11} = $riffs{10};
$riffs{12} = [qw(o4c+ o3a o3g o3a)];
$riffs{13} = $riffs{12};
$riffs{14} = [qw(o4d+ o3b o3a o3b)];
$riffs{15} = $riffs{14};
$riffs{16} = [qw(o4f o4c+ o3b o4c+)];
$riffs{17} = $riffs{16};
$riffs{18} = [qw(o4g o4d+ o4c+ o4d+)];
$riffs{19} = $riffs{18};
$riffs{20} = [qw(o4a o4f o4d+ o4f)];
$riffs{21} = $riffs{20};
$riffs{22} = [qw(o4b o4g o4f o4g)];
$riffs{23} = $riffs{22};
$riffs{24} = [qw(o5c+ o4a o4g o4a)];
$riffs{25} = $riffs{24};
$riffs{26} = [qw(o5d+ o4b o4a o4b)];
$riffs{27} = $riffs{26};
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my @time_hashes;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
foreach my $time (split(/\n/,$current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 発車数の計算
$time_hash{sprintf('%02d%02d', $h, $m)} ||= 0;
$time_hash{sprintf('%02d%02d', $h, $m)}++;
$time_hash{sprintf('%02d%02d', $h, $m)}++;
}
}
my $mml = 'A C1"1"' . " \n" . 'A C1 l16';
my $prev_oct = '';
my $i = 0;
# すべての時刻で音が出る
for my $h(4 .. 25) {
for my $m(0 .. 59) {
last if $h == 25 && $m == 30;
my $this_note;
if ($m == 0) {
# だんだん音が大きくなっていく
$mml .= 'k' . ($h * 4) . 'v' . ($h * 4);
}
my $this_hhmm = sprintf('%02d%02d', $h, $m);
if (exists $time_hash{$this_hhmm}) {
# 発車時刻の場合は、次のリフの音を使う
$this_note = $riffs{$h + $time_hash{$this_hhmm}}->[$i];
} else {
# 本来の音を使う
$this_note = $riffs{$h}->[$i];
}
# リフ中の次の音へ
$i = ($i + 1) % @{$riffs{4}};
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note;
}
}
use strict;
my @notes = qw(
o4g o3c o3d o3d+ o3g o3g+ o4c o4d o4d+ o4g o4g+ o5c o5d
o5c o4g+ o4g o4d+ o4d o4c o3g+ o3g o3d+ o3d o3c
);
# 音とMIDIチャンネルの対応
my %note2ch = (
'o4g' => 1,
'o3c' => 2,
'o3d' => 3,
'o3d+' => 4,
'o3g' => 5,
'o3g+' => 6,
'o4c' => 7,
'o4d' => 8,
'o4d+' => 9,
'o4g' => 10,
'o4g+' => 11,
'o5c' => 12,
'o5d' => 13,
);
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my %time_hash;
my %time_hash_bend;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
foreach my $time(split(/\n/, $current_times)) {
my($h, $m) = split(/\s+/, $time);
$h =~ tr/0-9//cd;
$m =~ tr/0-9//cd;
my $this_note = $notes[($i * $h + $m) % @notes];
my $this_hhmm = sprintf('%02d%02d', $h, $m);
if (exists $time_hash{$this_hhmm}) {
# 発車時刻が重なった場合は押し手する
$time_hash_bend{$this_hhmm} = 1;
}
$time_hash{$this_hhmm} = $this_note;
}
}
# 各MIDIチャンネルのMMLを生成
my @mmls;
for my $i(1 .. (scalar(keys(%note2ch)) + 1 + 1)) {
$mmls[$i] = sprintf('%s C%d"%d" ', chr(65 + $i), $i, $i) . " \n";
$mmls[$i].=chr(65 + $i).' ';
}
for my $h(4 .. 25) {
for my $m(0 .. 59){
my $this_hhmm = sprintf('%02d%02d', $h, $m);
if (exists $time_hash{$this_hhmm}) {
my $this_note = $time_hash{$this_hhmm};
if (exists $note2ch{$this_note}) {
for my $i(1 .. (scalar(keys(%note2ch)) + 1)) {
if ($i == $note2ch{$this_note}) {
$mmls[$i] .= $this_note . '16';
} else {
$mmls[$i] .= 'r16';
}
}
} else {
$mmls[1] .= $this_note . '16';
for my $i(2 .. (scalar(keys(%note2ch)) + 1)) {
$mmls[$i] .= 'r16';
}
}
} else {
for my $i(1 .. (scalar(keys(%note2ch)) + 1)) {
$mmls[$i] .= 'r16';
}
}
# 「押し手」する予定のメモ
if (exists $time_hash_bend{$this_hhmm}) {
$mmls[scalar(keys(%note2ch)) + 1 + 1] .= 'o6b16';
} else {
$mmls[scalar(keys(%note2ch)) + 1 + 1] .= 'r16';
}
}
}
# 出力
for my $i(1 .. (scalar(keys(%note2ch)) + 1 + 1)){
# 略
# 休符をまとめる
print $mmls[$j] . "\n";
}
use strict;
my @notes = qw(o4c o4c+ o4d o4d+ o4e o4f o4f+ o4g o4g+ o4a o4a+ o4b);
my @times;
# 略
# 時刻がセットされている
# 音を溜める
my @rounded_notes;
my $last_rounded_time;
my %rounded_times;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
my %pool;
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 時刻を「四捨五入」する
my $rounded_hhmm = &rounded_hhmm($h, $m);
unless (exists $pool{$rounded_hhmm}) {
$pool{$rounded_hhmm} = {};
$rounded_times{$rounded_hhmm} = $hhmm;
}
$last_rounded_time = $hhmm;
my $this_note = $notes[($i * $h + $m) % @notes];
while (exists $pool{$rounded_hhmm}->{$this_note}) {
if ($this_note =~ /^o(\d)(.+)/) {
if ($1 == 4) {
$this_note = 'o3' . $2;
} elsif ($1 == 3) {
$this_note = 'o5' . $2;
} elsif ($1 == 5) {
$this_note = 'o2' . $2;
} elsif ($1 == 2) {
$this_note = 'o6' . $2;
} else {
die;
}
}
}
$pool{$rounded_hhmm}->{$this_note} = 1;
}
@rounded_notes[$i] = \%pool;
}
for my $i(0 .. $#times) {
next unless defined $rounded_notes[$i];
foreach my $time(sort(keys(%{$rounded_notes[$i]}))) {
if ($time ne $rounded_times{$time}) {
$rounded_notes[$i]->{$rounded_times{$time}} = $rounded_notes[$i]->{$time};
delete $rounded_notes[$i]->{$time};
}
}
}
# MMLの生成
my $mml = '';
for my $i(0 .. $#times) {
next unless defined $rounded_notes[$i];
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
my $count=0;
foreach my $time(sort(keys(%{$rounded_notes[$i]}))) {
my($h, $m);
if($time =~ /^(\d{2})(\d{2})$/) {
$h = $1;
$m = $2;
}
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 溜めていた音を出力する
$mml .= join('0', keys(%{$rounded_notes[$i]->{$time}})) . '16';
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
sub rounded_hhmm {
my $hh = shift;
my $mm = shift;
if ($mm < 30) {
return "${hh}00";
} else {
return "${hh}30";
}
}
use strict;
my %notes = (
flute => [qw(o5c o5d o5e o5f o5g o5a o5b)],
piccolo => [qw(o6c o6d o6e o6f o6g o6a o6b)],
oboe => [qw(o4c o4d o4e o4f o4g o4a o4b)],
clarinet => [qw(o3c o3d o3e o3f o3g o3a o3b)],
fagot => [qw(o2c o2d o2e o2f o2g o2a o2b)],
violin => [qw(o5c o5d o5e o5f o5g o5a o5b)],
viola => [qw(o4c o4d o4e o4f o4g o4a o4b)],
cello => [qw(o3c o3d o3e o3f o3g o3a o3b)],
contrabass => [qw(o2c o2d o2e o2f o2g o2a o2b)],
harp => [qw(o3c o3d o3e o3f o3g o3a o3b o4c o4d o4e o4f o4g o4a o4b)],
horn => [qw(o3c o3d o3e o3f o3g o3a o3b)],
trumpet => [qw(o5c o5d o5e o5f o5g o5a o5b)],
trombone => [qw(o3c o3d o3e o3f o3g o3a o3b)],
tuba => [qw(o2c o2d o2e o2f o2g o2a o2b)],
timpani => [qw(o2c o2d o2e o2f o2g o2a o2b)],
bdrum_and_cymbal => [qw(o2c o3b)],
tmb_and_triangle => [qw(o3f+ o5g+ o5a)],
snare_and_wblock => [qw(o2e o5e- o5e)],
xylophon => [qw(o5c o5d o5e o5f o5g o5a o5b)],
cnet_and_tomtom => [qw(o2e- o3g)],
whip => [qw(o4c o4d o4e)],
percs => [qw(o2c o3b o3f+ o5g+ o5a)]
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
my $this_time = sprintf('%02d%02d', $h, $m);
my @this_notes;
if ($h <= 4) {
if ($i == 1 || $i == 2) {
@this_notes = @{$notes{flute}};
} else {
@this_notes = @{$notes{piccolo}};
}
} elsif ($h <= 5) {
@this_notes = @{$notes{oboe}};
} elsif ($h <= 6) {
@this_notes = @{$notes{clarinet}};
} elsif ($h <= 7) {
@this_notes = @{$notes{fagot}};
} elsif ($h <= 8) {
@this_notes = @{$notes{violin}};
} elsif ($h <= 9) {
@this_notes = @{$notes{viola}};
} elsif ($h <= 10) {
@this_notes = @{$notes{cello}};
} elsif ($h <= 11) {
@this_notes = @{$notes{contrabass}};
} elsif ($h <= 12) {
@this_notes = @{$notes{harp}};
} elsif ($h <= 13) {
@this_notes = @{$notes{horn}};
} elsif ($h <= 14) {
@this_notes = @{$notes{trumpet}};
} elsif ($h <= 15) {
if ($i == 1 || $i == 2) {
@this_notes = @{$notes{trombone}};
} else {
@this_notes = @{$notes{tuba}};
}
} elsif ($this_time lt '1620') {
@this_notes = @{$notes{timpani}};
} elsif ($this_time lt '1640') {
@this_notes = @{$notes{bdrum_and_cymbal}};
} elsif ($this_time lt '1700') {
@this_notes = @{$notes{tmb_and_triangle}};
} elsif ($this_time lt '1720') {
@this_notes = @{$notes{snare_and_wblock}};
} elsif ($this_time lt '1740') {
@this_notes = @{$notes{xylophon}};
} elsif ($this_time lt '1800') {
@this_notes = @{$notes{cnet_and_tomtom}};
} elsif ($this_time lt '1830') {
@this_notes = @{$notes{whip}};
} else {
@this_notes = @{$notes{flute}};
# トゥッティのときは以下のコードを使う
# ハープ用
# @notes = @{$notes{harp}};
# 打楽器用
# @notes = @{$notes{percs}};
}
my $this_note = $notes[($i * $h + $m) % @notes] . '16';
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note;
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my %notes = (
violin => [qw(o3g o4d o4a o5e)],
viola => [qw(o3c o3g o4d o4a)],
cello => [qw(o2c o2g o3d o3a)],
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0..$#times){
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音の決定
my @this_notes;
if ($i == 3 || $i == 4) {
@this_notes = @{$notes{violin}};
} elsif ($i == 2 ){
@this_notes = @{$notes{viola}};
} else {
@this_notes = @{$notes{cello}};
}
my $this_note = $notes[($i * $h + $m) % @notes];
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note . '16';
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my %notes = (
on => 'g+0b0>e16<',
off => 'g0b-0>d-0e-16<',
);
my @times;
# 略
# 時刻がセットされている
# 発車時刻の情報を覚えておく
my @time_hashes;
# 略
# 詳しくは五反田駅のソースを参照のこと
my $mml = '';
for my $i(0 .. $#times) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# オクターブの決定
if ($i == 1 || $i == 2) {
$mml .= 'o5';
} elsif ($i == 3 || $i == 4) {
$mml .= 'o4';
} else {
$mml .= 'o3';
}
# すべての時刻で音が出る
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $this_note;
if (exists $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)}) {
$this_note = 'k100' . $notes{on};
} else {
if ($m % 2 == 0) {
$this_note = 'k48' . $notes{off};
} else {
$this_note = 'r16';
}
}
$mml .= $this_note;
}
}
$mml .= "\n";
}
use strict;
my @notes = qw(c c+ d d+ e f f+ g g+ a a+);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
$mml .= $notes[($i * $h + $m) % @notes] . '16';
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @notes = qw(
o2c o2c+ o2d o2d+ o2e o2f o2f+ o2g o2g+ o2a o2a+ o2b
o3c o3c+ o3d o3d+ o3e o3f o3f+ o3g o3g+ o3a o3a+ o3b
o4c o4c+ o4d o4d+ o4e o4f o4f+ o4g o4g+ o4a o4a+ o4b
o5c o5c+ o5d o5d+ o5e o5f o5f+ o5g o5g+ o5a o5a+ o5b
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
$mml .= $notes[($i * $h + $m) % @notes] . '16';
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @notes = qw(
o2d+16 o2e16 o2f16 o2f+16 o2g16 o2g+16
o2a16 o2a+16 o2b16 o3c16 o3c+16 o3d16
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
my %drum_notes;
my %bass_notes;
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
my $this_note = $notes[($i * $h + $m) % @notes];
$mml .= $this_note;
# ドラム用に時刻を覚えておく
$drum_notes{$hhmm} = 'a32r32';
# ベースの音を決定
my $note_for_bass;
if ($this_note =~ /^o(\d)([a-g+]+)/) {
$note_for_bass = 'o' . ($1 - 1) . $2 . '16';
}
if (exists $bass_notes{$hhmm}) {
# 低い方が良い
if (&cmp_note($bass_notes{$hhmm}, $note_for_bass) == 1) {
$bass_notes{$hhmm} = $note_for_bass;
}
} else {
$bass_notes{$hhmm} = $note_for_bass;
}
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
# ドラムとベースのMMLを生成
for my $i(5 .. 6) {
$mml .= sprintf('%s C%d"%d" ', chr(65 + $i), $i, $i) . " \n";
$mml .= chr(65 + $i) . ' ';
# ドラム用にオクターブのセット
$mml .= 'o1' if $i == 6;
# 覚えておいた音を出力
for my $h(4 .. 25) {
for my $m(0 .. 59) {
my $hhmm = sprintf('%02d%02d', $h, $m);
if ($i == 5) {
# ベース
if (exists $bass_notes{$hhmm}) {
$mml .= $bass_notes{$hhmm};
} else {
$mml .= 'r16';
}
} else {
# ドラム
if (exists $drum_notes{$hhmm}) {
$mml .= $drum_notes{$hhmm};
} else {
$mml .= 'r16';
}
}
}
}
$mml .= "\n";
}
sub cmp_note {
my $note_a = shift;
my $note_b = shift;
my $oct_a;
if ($note_a =~ /o(\d)/) {
$oct_a = $1;
}
my $oct_b;
if ($note_b =~ /o(\d)/) {
$oct_b = $1;
}
if ($oct_a == $oct_b) {
return $note_a cmp $note_b;
} else {
return $oct_a <=> $oct_b;
}
}
use strict;
my @notes = qw(
o4e o4f o4f+ o4g o4g+ o4a o4a+ o4b o5c o5c+ o5d o5d+
o5e o5f o5f+ o5g o5g+ o5a o5a+ o5b o6c o6c+ o6d o6d+ o6e
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
my $this_note = $notes[($i * $h + $m) % @notes];
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# 16分音符ではなく32分音符を出力
$mml .= $this_note . '32r32';
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @clusters = qw(
e0d+0d0c+0c16
f0e0d+0d0c+16
f+0f0e0d+0d16
g0f+0f0e0d+16
g+0g0f+0f0e16
a0g+0g0f+0f16
a+0a0g+0g0f+16
b0a+0a0g+0g016
);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
# オクターブの決定
$mml .= 'o' . (8 - $i);
# クラスター用のカウンタのセット
my $index = 0;
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# トーン・クラスターを選択
if (($i * $h + $m) % 2) {
$index++;
} else {
$index--;
}
# 端まで行ったら止まるように
if ($index > $#clusters) {
$index = $#clusters;
}
if ($index < 0){
$index = 0;
}
# MMLの生成
$mml .= $clusters[$index];
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 「路線ID×256分音符」だけ遅らせるのは手動で・・・
$mml .= 'c';
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
$mml .= 'c';
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
# 倍音を以下の音に割り当て
my @all_notes = qw(
o1c o1c+ o1d o1d+ o1e o1f o1f+ o1g o1g+ o1a o1a+ o1b
o2c o2c+ o2d o2d+ o2e o2f o2f+ o2g o2g+ o2a o2a+ o2b
o3c o3c+ o3d o3d+ o3e
);
my @riffs;
for my $i(4 .. 25) {
$riffs[$i] = [@all_notes[($i - 4) .. ($i - 4 + 7)]];
}
my @times;
# 略
# 時刻がセットされている
# 発車時刻ごとに音を計算
my @time_hashes;
for my $i(0 .. $#times) {
my $current_times = $times[$i];
next unless defined $current_times;
$time_hashes[$i] = {};
my $j = 0;
my $prev_h;
foreach my $time(split(/\n/, $current_times)) {
my($h, $m) = split(/\s+/, $time);
$h =~ tr/0-9//cd;
$m =~ tr/0-9//cd;
if ($h ne $prev_h) {
# 「時」が変わったらリフ用のカウンタをリセット
$prev_h = $h;
$j = 0;
}
$time_hashes[$i]->{sprintf('%02d%02d', $h, $m)} = $riffs[int($h)]->[$j];
$j = ($j + 1) % @{$riffs[int($h)]};
}
}
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音を決定
my $this_note = $time_hashes[$i]->{sprintf('%02d%02d', $h, $m)} . '16';
# 同じオクターブはまとめる
# 詳しくは品川駅のソースを参照のこと
# その他の処理
$mml .= $this_note;
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 休符を演奏
$mml .= 'r16';
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
use strict;
my %notes;
$notes{4} = {
1 => [qw(
o4c16 o4d16 o4e16 o4f+16 o4g+16 o4a+16 o5c16
o4a+16 o4g+16 o4f+16 o4e16 o4d16 o4c16
)],
2 => [qw(
o3c16 o3d16 o3e16 o3f+16 o3g+16 o3a+16 o4c16
o3a+16 o3g+16 o3f+16 o3e16 o3d16 o3c16
)],
3 => [qw(
o2c16 o2d16 o2e16 o2f+16 o2g+16 o2a+16 o3c16
o2a+16 o2g+16 o2f+16 o2e16 o2d16 o2c16
)],
4 => [qw(
o3c0e0g+16 o3d0f+0a+16 o3e0g+0o4c16
o3d0f+0a+16 o3c0e0g+16
)],
};
$notes{5} = $notes{4};
$notes{6} = $notes{4};
$notes{7} = {
1 => [qw(
o4c16 o4d-16 o4e-16 o4e16 o4f+16 o4g16 o4a16 o4b-16 o5c16
o4b-16 o4a16 o4g16 o4f+16 o4e16 o4e-16 o4d-16 o4c16
)],
2 => [qw(
o3c16 o3d-16 o3e-16 o3e16 o3f+16 o3g16 o3a16 o3b-16 o4c16
o3b-16 o3a16 o3g16 o3f+16 o3e16 o3e-16 o3d-16 o3c16
)],
3 => [qw(
o2c16 o2d-16 o2e-16 o2e16 o2f+16 o2g16 o2a16 o2b-16 o3c16
o2b-16 o2a16 o2g16 o2f+16 o2e16 o2e-16 o2d-16 o2c16
)],
4 => [qw(
o3c0e-0f+16 o3d-0e0g16 o3e-0f+0a16 o3e0g0b-16 o3f+0a0o4c16
o3e0g0b-16 o3e-0f+0a16 o3d-0e0g16 o3c0e-0f+16
)],
};
$notes{8} = $notes{7};
$notes{9} = $notes{7};
$notes{10} = {
1 => [qw(
o4c16 o4d16 o4e-16 o4e16 o4f+16 o4g16 o4a-16 o4b-16 o4b16 o5c16
o4b16 o4b-16 o4a-16 o4g16 o4f+16 o4e16 o4e-16 o4d16 o4c16
)],
2 => [qw(
o3c16 o3d16 o3e-16 o3e16 o3f+16 o3g16 o3a-16 o3b-16 o3b16 o4c16
o3b16 o3b-16 o3a-16 o3g16 o3f+16 o3e16 o3e-16 o3d16 o3c16
)],
3 => [qw(
o2c16 o2d16 o2e-16 o2e16 o2f+16 o2g16 o2a-16 o2b-16 o2b16 o3c16
o2b16 o2b-16 o2a-16 o2g16 o2f+16 o2e16 o2e-16 o2d16 o2c16
)],
4 => [qw(
o3c0e-0f+16 o3d0e0g16 o3e-0f+0a-16 o3e0g0b-16 o3f+0a-0b16 o3g0b-0o4c16
o3f+0a-0b16 o3e0g0b-16 o3e-0f+0a-16 o3d0e0g16 o3c0e-0f+16
)],
};
$notes{11} = $notes{10};
$notes{12} = $notes{10};
$notes{13} = {
1 => [qw(
o4c16 o4d-16 o4d16 o4f16 o4f+16 o4g16 o4a-16 o4b16 o5c16
o4b16 o4a-16 o4g16 o4f+16 o4f16 o4d16 o4d-16 o4c16
)],
2 => [qw(
o3c16 o3d-16 o3d16 o3f16 o3f+16 o3g16 o3a-16 o3b16 o4c16
o3b16 o3a-16 o3g16 o3f+16 o3f16 o3d16 o3d-16 o3c16
)],
3 => [qw(
o2c16 o2d-16 o2d16 o2f16 o2f+16 o2g16 o2a-16 o2b16 o3c16
o2b16 o2a-16 o2g16 o2f+16 o2f16 o2d16 o2d-16 o2c16
)],
4 => [qw(
o3c0d0f+16 o3d-0f0g16 o3d0f+0a-16 o3f0g0b16 o3f+0a-0o4c16
o3f0g0b16 o3d0f+0a-16 o3d-0f0g16 o3c0d0f+16
)],
};
$notes{14} = $notes{13};
$notes{15} = $notes{13};
$notes{16} = {
1 => [qw(
o4c16 o4d-16 o4f16 o4f+16 o4g16 o4b16 o5c16
o4b16 o4g16 o4f+16 o4f16 o4d-16 o4c16
)],
2 => [qw(
o3c16 o3d-16 o3f16 o3f+16 o3g16 o3b16 o4c16
o3b16 o3g16 o3f+16 o3f16 o3d-16 o3c16
)],
3 => [qw(
o2c16 o2d-16 o2f16 o2f+16 o2g16 o2b16 o3c16
o2b16 o2g16 o2f+16 o2f16 o2d-16 o2c16
)],
4 => [qw(
o3c0f0g16 o3d-0f+0b16 o3f0g0o4c16
o3d-0f+0b16 o3c0f0g16
)],
};
$notes{17} = $notes{16};
$notes{18} = $notes{16};
$notes{19} = {
1 => [qw(
o4c16 o4d16 o4e16 o4f16 o4f+16 o4g+16 o4a+16 o4b16 o5c16
o4b16 o4a+16 o4g+16 o4f+16 o4f16 o4e16 o4d16 o4c16
)],
2 => [qw(
o3c16 o3d16 o3e16 o3f16 o3f+16 o3g+16 o3a+16 o3b16 o4c16
o3b16 o3a+16 o3g+16 o3f+16 o3f16 o3e16 o3d16 o3c16
)],
3 => [qw(
o2c16 o2d16 o2e16 o2f16 o2f+16 o2g+16 o2a+16 o2b16 o3c16
o2b16 o2a+16 o2g+16 o2f+16 o2f16 o2e16 o2d16 o2c16
)],
4 => [qw(
o3c0e0f+16 o3d0f0g+16 o3e0f+0a+16 o3f0g+0b16 o3f+0a+0o4c16
o3f0g+0b16 o3e0f+0a+16 o3d0f0g+16 o3c0e0f+16
)],
};
$notes{20} = $notes{19};
$notes{21} = $notes{19};
$notes{22} = {
1 => [qw(
o4c16 o4c+16 o4d16 o4e-16 o4f16 o4f+16 o4g16 o4g+16 o4a16 o4b16 o5c16
o4b16 o4a16 o4g+16 o4g16 o4f+16 o4f16 o4e-16 o4d16 o4c+16 o4c16
)],
2 => [qw(
o3c16 o3c+16 o3d16 o3e-16 o3f16 o3f+16 o3g16 o3g+16 o3a16 o3b16 o4c16
o3b16 o3a16 o3g+16 o3g16 o3f+16 o3f16 o3e-16 o3d16 o3c+16 o3c16
)],
3 => [qw(
o2c16 o2c+16 o2d16 o2e-16 o2f16 o2f+16 o2g16 o2g+16 o2a16 o2b16 o3c16
o2b16 o2a16 o2g+16 o2g16 o2f+16 o2f16 o2e-16 o2d16 o2c+16 o2c16
)],
4 => [qw(
o3c0d0f16 o3c+0e-0f+16 o3d0f0g16 o3e-0f+0g+16 o3f0g0a16 o3f+0g+0b16 o3g0a0o4c16
o3f+0g+0b16 o3f0g0a16 o3e-0f+0g+16 o3d0f0g16 o3c+0e-0f+16 o3c0d0f16
)],
};
$notes{23} = $notes{22};
$notes{24} = $notes{22};
$notes{25} = $notes{22};
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
# 音列の選択
my @this_notes = @{$notes{int($h)}->{$i}};
$mml .= 'k' . ($h * 4 + 40) . $this_notes[($i * $h + $m) % @this_notes];
# その他の処理
$prev_minutes = $minutes;
}
$mml .= "\n";
}
# 特にすることなし・・・
use strict;
my @notes = qw(b- a >c< b);
my @times;
# 略
# 時刻がセットされている
my $mml = '';
for my $i(0 .. $#times) {
# もろもろの準備は省略
# 詳しくは品川駅のソースを参照のこと
my $index = 0;
foreach my $time(split(/\n/, $current_times)) {
# 時間をセットしたりゴミを取ったり
# 詳しくは品川駅のソースを参照のこと
$mml .= $notes[$index] . '16';
$index = ($index + 1) % @notes;
$prev_minutes = $minutes;
}
$mml .= "\n";
}
Music by HAGIHARA Yoshiaki with Perl scripts.
Sleeve design and artwork by AKIYAMA Mimico.
Last update: Dec 31, 2013.