ピアノの運指を自動生成するには?
一般的に言ってピアノの初見能力は訓練次第でかなりのスピードにまで向上する。一つの音符を1つの文字だと考えてみると想像しやすい。文字を読む速度は子供のころは遅いが、大人になるころには1分間に1000文字ぐらい読めるようになっているはずで、ピアノを10年か20年ぐらいやっていれば、1分間に1000音符ぐらい読めるようになっていても不思議ではない。
しかし、どれほど初見能力があってもミスタッチなしに正確に演奏できるか、そして、リアルタイムに運指を導き出せるかと言うと話は別である。
例えば、フランツ・リストは「どんな難曲でも初見で弾ける」と豪語していたが、ショパンのエチュードに至っては初見では弾けなかったと言われている。私が思うに、ショパンのエチュードは運指がすこぶる嫌らしいのだ。
知らない人のために説明すると「運指」というのはどの音符をどの指で押すのかということなのだが、運指は無数に考えられ、数学的に言うと組み合わせ爆発をしている。
組み合わせ爆発しているものを人間は瞬時に解答できないので(例:ナップサック問題)、どれだけ初見能力があり、超高速で正確に指を動かす能力があったとしても、運指を瞬時に決められない以上、そこに人間の限界があるのだろう。
―――とまあ、そんなありきたりな説明には飽き飽きしている人のために、もう少し突っ込んだ話をしようというのが今回の趣旨である。上の説明ですでにお腹いっぱいになった人はブラウザを閉じてすみやかにお戻りください。
ピアノの場合、好ましい運指の条件として次のようなものが考えられる。
・あまり特定の2指か3指での動きが続くとそれらの指が疲れてくるのでなるべく指は満遍なく使いたい。
・同じ指で次の違う鍵を押すのはあまり良くない(前の音が切れてしまうため)
・2の指(人差し指)から3の指(中指)のような隣合う指を使っていく場合、前の音からなるべく跳躍がないほうがいい(そんなに指が開かないし、またミスタッチもしやすくなるため)
・1の指(親指)と2の指(人差し指)はそこそこ開くが、2の指(人差し指)と3の指(中指)はさほど開かないというような指ごとの特性がある。1と2の間は多少開いてもいいが、2と3の指の間が開くと無理な動きになるので音が途切れてはならないときは、前者のほうが好ましい。
・トリル、モルデント、プラルトリラー等の交互連打は2,3(or 3,4)の指でやるのが好ましく、4,5の指はそこまで速く交互に動かないので出来れば避けたい。
そこで、最適な運指を探すアルゴリズムは、良くないとされるような運指に高い点数をつければ、その点数を最小化するような経路を探すという有向グラフの最短路問題に帰着する。動的計画法を用いればこれはO(N)で解ける。
フルートで同じような議論をしてある論文があるので参考のため紹介しておく。
フルートの運指のモデル化とその最適化に関する研究
http://ci.nii.ac.jp/naid/110006164752
このような最短経路問題を人間は瞬時に解くことは不可能であり(人間の計算能力的なものを超えていると思われる)、いくら初見能力が高かろうと、複雑な譜面に対して最適な運指を実時間で求めることは出来ないと考えるべきだと思う。
つまり、ショパンのエチュードレベルの曲を初見で弾ける人間は多分この世にいないのだと思う。
(演奏前に楽譜を見て運指を考えていいなら可能なのかも知れない。私には未知の領域すぎてわからない。)
さて、話を少し戻ろう。
動的計画法でO(N)で解けるのだから本当に人間に不可能なのかどうかは議論の余地がある。
つまり、これがどれくらいの計算コストなのか、もう少し突っ込んで考えてみる。
旋律がすべて単音であるとして、かつ、右手だけをいまは問題として扱う。
また、現在鍵を押さえている指だけに着目し、それより過去の時間においてどの鍵をどの指で押さえていたかは問わないものとする。(たとえば3の指で鍵盤中央のドの音を押さえているとき、自ずと手首がどのへんにあるか、他の指がどのへんにあるのかは確定するだろうという仮定をする。)
そうすると、現在、鍵を押さえている指は5通り(片手には指が5本あるから)で、そこまでの最小の経路のスコアが既知である。これをそれぞれ、S(1)〜S(5)とする。つまり、例えばS(1)ならば現在の鍵を1の指(親指)で押している場合の最小のスコア。(そこまでの経路のうち、最小のスコアをつける経路のスコア)
次に押さえるべき鍵をたとえばaの指で押さえるときのことを考える。ひとつ前の鍵を押さえていた指がbだとしたら
今回のS(a) = 前回のS(b) + 今回のコスト(=前の鍵をbで押さえて今回の鍵をaで押さえるときのコスト関数)
である。
S(a)は最小化しないといけないから、結局、
・前回のS(1) + 今回のコスト(前の鍵を1で押さえて今回の鍵をaで押さえるときのコスト)
・前回のS(2) + 今回のコスト(前の鍵を2で押さえて今回の鍵をaで押さえるときのコスト)
・前回のS(3) + 今回のコスト(前の鍵を3で押さえて今回の鍵をaで押さえるときのコスト)
・前回のS(4) + 今回のコスト(前の鍵を4で押さえて今回の鍵をaで押さえるときのコスト)
・前回のS(5) + 今回のコスト(前の鍵を5で押さえて今回の鍵をaで押さえるときのコスト)
のうち最小のものを選択することになる。
今回のS(1)〜S(5)に対して上記のように最小のコストのものを選んでやる必要があるので、コスト関数を25個それぞれ計算して、上記のようにS(1)〜S(5)を更新してやる必要があるので、S(1)〜S(5)を記憶するための5つの記憶域と、1音符に対して25回のコスト関数の計算、およびその加算と最小値を探すための比較が必要になる。
「暗算日本一の人とかなら可能なんじゃないか」と言う人がいるかと思うが、しかし暗算日本一の人も数字を文字を読むように認識しているだけだろうから、人間の文字を読む速度(1分に1000文字程度)を超えた計算は不可能ではないかと私は思う。
ピアノ曲でテンポの速い曲はBPM200程度であり、つまり1分間に4分音符が200個、16分音符なら800個、両手ならその倍の1600個。その1600個の音符それぞれに対して上記のように25回のコスト関数の計算、25回の加算、5回の最小値の選出が必要になる。これは間違いなく人間の処理能力を越えていると思う。
ゆえに、そのような譜面に対してピアノの運指をリアルタイムに人間が求めることは出来ないという結論になる。
一方、コンピューターで計算させて良いのであれば、上記アルゴリズムはこれは極めて簡単なプログラムで実現できる。実際は単音ではなく和音であったり、あと右手と左手が交差するようなこともあるし、鍵を押したまま他の指を動かす場合もあるのでもう少しややこしいが考え方自体はここに書いた方法で良い。
また、直前に押した指だけではなく、その一つ前とか二つ前の指も考慮して、S(x,y,z)のようなスコアが最小化するように更新していく(このとき1音符につき5の4乗=625回のコスト関数の計算が必要になる)とさらにリアルな運指が得られる。
さて、そのようにして運指を導き出し、MIDIファイルからMMDのモーションファイルを生成するものをいっちょ作ったろかい!と思って私は考えていたのだが、調べていたらすでにやってる人が居て、しかも結構動画の完成度が高くて激しく萎えたのでその動画を紹介してこの記事を終わりたい。
【MMD】ミクさんがビッグブリッヂの死闘を弾いてくれました。.mp4
追記。iPhoneの超有名アプリのFingerPianoの作者、和田さんに振ってみました。