以下、本発明を実施するための形態について図面を参照しながら詳細に説明する。
図1は、本発明による演奏操作ガイド装置100の実施形態を示すブロック図である。この演奏操作ガイド装置100は、演奏情報読み出し手段101、操作状態推定手段102、パート同士の状態比較手段103,演奏操作ガイド手段104を備える。また、内部または外部に、記憶部105が具備される。
演奏情報読み出し手段101は、曲を構成する各楽音の、発音を行う発音タイミングに関する情報と、音高に関する情報と、演奏者の演奏操作に関する情報と、を含む演奏情報108を記憶部105から読み出す。
操作状態推定手段102は、演奏情報読み出し手段101によって読み出された演奏情報108夫々に基づいて、その演奏情報108における演奏者の演奏操作状態を推定する。
パート同士の状態比較手段103は、操作状態推定手段102が推定した演奏操作情報をパート間で比較することにより、演奏操作に不都合が生じないように、パート毎の演奏操作状態を補正する。
演奏操作ガイド手段104は、操作状態推定手段102により推定されパート同士の状態比較手段103により補正された第1の演奏操作状態106と、第1の演奏操作状態106より後に推定された第2の演奏操作状態107とに基づいて、演奏者の演奏操作に関するガイドを行う。
上述の構成において、パート同士の状態比較部103は、操作状態推定手段102が推定した演奏操作状態が示す各指の演奏位置がパート間で衝突する状態にある場合に、演奏操作状態中の各指の演奏位置に関する情報を補正してよい。
より具体的には、操作状態推定手段102は、各指の奥行き方向の位置に関する情報をさらに含む演奏操作状態を推定する。そして、パート同士の状態比較手段103は、操作状態推定手段102が推定した演奏操作状態が示す親指に最も近い演奏位置の音高をパート毎に取得する。そして、パート同士の状態比較手段103は、その音高のうち左手のパートの音高が右手のパートの音高よりも高い場合に、左手のパートおよび右手のパートともに第1の演奏操作状態を含むならば、演奏操作状態中の各指の奥行き方向の位置に関する情報を補正する。また、パート同士の状態比較手段103は、左手のパートおよび前記右手のパートのうちの一方のパートのみが第1の演奏操作状態を含むならば、他方のパートの演奏操作状態中の前記各指の音高に関する情報を補正する。
ここまでの構成において、演奏操作ガイド装置100は、鍵盤楽器の演奏操作に関するガイドを行うものとしてよい。このとき、操作状態推定手段102は、演奏者の第1及び第2の演奏操作状態106,107として、親指で鍵盤を押鍵中の状態及びこの状態から親指以外の指で親指の上を越えて移動させて次以降のタイミングにて押鍵する状態を推定してよい。この場合に、演奏操作ガイド手段104は、親指が演奏を行うべき指としてガイドするとともに、親指以外の指を演奏の準備を行うべき指としてガイドしてよい。また、操作状態推定手段102が、演奏者の第1及び第2の演奏操作状態106,107として、親指で鍵盤を押鍵中の状態及びこの状態から親指以外の指で押鍵中に親指で親指以外の指の下をくぐらせて移動させて次以降のタイミングにて押鍵する状態を推定してよい。この場合に、演奏操作ガイド手段104は、親指以外の指を演奏を行うべき指としてガイドするとともに、親指を演奏の準備を行うべき指としてガイドしてよい。さらに、操作状態推定手段102は、演奏者の第1及び第2の演奏操作状態106,107として、鍵盤の所定の鍵が押鍵されている状態及びその押鍵されている鍵から所定の基準値よりも離れた位置の鍵が次に押鍵される状態を推定してよい。この場合に、演奏操作ガイド手段104は、現在の押鍵状態から次の押鍵状態への移動の準備をガイドしてよい。
以上の実施形態の構成により、操作状態推定手段102が、演奏情報読み出し手段101によって読み出された演奏情報108夫々に基づいて、演奏情報108における演奏者の演奏操作状態を、第1および第2の演奏操作状態106,107として推定することができる。これらの第1および第2の演奏操作状態106,107を用いて、演奏操作ガイド手段104が演奏ガイドを行うことにより、各動作タイミングにおいて、演奏を行うべき指の運指ガイドだけでなく、それ以降の演奏の準備を行うべき指のガイドも行うことができる。演奏の準備の動作としては、他の指による親指越えや、親指による指くぐり、広範囲での指の移動などの動作を含むことができ、これにより演奏動作のテクニックに関するガイドを行うことが可能となる。
さらに、本実施形態では、左手と右手のパートで練習を行うための演奏ガイドを実行するときに、楽譜上、左手パートと右手パートの間で、演奏される指同士が衝突しそうになったり、あるいは次に演奏する準備を行うべき指を置く場所と演奏中の指が衝突しそうになった場合に、パート同士の状態比較手段103が、それらの状態を検知して補正することが可能となる。
具体的には、演奏中の指同士が衝突しそうになった場合は、各パートの演奏中の指および演奏の準備を行うべき指全体を奥行き方向の前後にずらして演奏ガイドをすることにより、衝突を回避できる。例えば鍵盤楽器の場合、一方のパートが奥の黒鍵側にある場合は、そのパートの指全体がさらに黒鍵側に移動するように、また他方のパートが手前の白鍵側にある場合、そのパートの指全体がさらに白鍵側に移動するように、演奏位置がずらされる。また、次に演奏の準備を行うべき指を置く場所と演奏中の指が衝突しそうになった場合には、左手と右手の各パートで指がオーバーラップしている分だけ、演奏の準備を行うべき指のほうを音高指定方向(例えば鍵盤楽器の鍵盤の横方向)にずらして演奏ガイドを行うことにより、衝突を回避できる。このようにして、本実施形態では、両手パートが衝突しない運指ガイドが可能となる。
図2は、図1の機能構成を有する演奏動作ガイド装置100の実施形態のハードウェア構成の一例を示す図である。この装置100は、CPU(中央演算処理装置)201、ROM(リードオンリーメモリ)202、RAM(ランダムアクセスメモリ)203、入力部204、表示部205、およびMIDIインタフェース部(以下「MIDI I/F」と表記する)206が、バス207によって相互に接続された構成を備える。MIDI I/F206は、外部(内蔵でもよい)の電子楽器208に接続される。
CPU201は、ROM202に記憶された制御プログラムに従って、当該演奏操作ガイド装置100の全体の制御を行う。
ROM202は、後述する各フローチャートで示される制御動作を実行する制御プログラムを記憶する。また、ROM202は、複数の楽曲の図1に示される演奏情報108などを記憶する。
RAM203は、制御プログラムの実行に必要な、後述する図3、図4に示される、演奏情報、動作データなどの各種情報を、一時的に記憶する。
入力部204は、ユーザによるキーボード、マウス、各種スイッチ等による入力操作を検出し、その検出結果をCPU201に通知する。
表示部205は、CPU201の制御によって送られてくるデータを液晶ディスプレイなどに出力する。例えば、表示部205は、後述する図25のような表示形式で、演奏動作ガイドを表示する。
MIDI I/F206は、CPU201が、ROM202またはRAM203上の演奏情報を、MIDI(Musical Instrument Digital Interface)のデータフォーマットで、電子楽器208に順次転送することにより、演奏動作ガイドを行う楽曲を自動演奏させることができる。
本実施形態による演奏操作ガイド装置100の動作は、後述する各フローチャート等で実現される図1の各部の機能処理を搭載した制御プログラムを、CPU201がROM202から読み出して順次実行することで実現される。そのプログラムは、特には図示しない可搬型記録媒体を介して提供されてもよく、或いは特には図示しないネットワーク接続装置によりネットワークから取得できるようにしてもよい。
以下、図1の機能構成と図2のハードウェア構成を有する本実施形態による演奏操作ガイド装置100の動作について、以下に詳細に説明する。
図3は、演奏動作ガイドを行う曲の演奏情報Note[0]、Note[1]、・・・、Note[N−1]のデータ構成例を示す図であり、図1の演奏情報108に対応する。演奏情報は、図2において、CPU201が電子楽器208に対して演奏ガイドをさせるにあたって必要な、インデックス番号(0、1、・・・、N−1)(Nは1曲分の演奏情報の数)、発音を開始する発音開始時刻Timeと発音継続時間Gate(図1の「発音タイミングに関する情報」に対応)、音高Pitch(図1の「音高に関する情報」に対応)、右手(値「0」)または左手(値「1」)を示すトラック番号Hand(図1の「パートに関する情報」に対応)、および指番号Finger(図1の「演奏する指に関する情報」に対応)の各情報を記憶する。演奏情報Note[0]、Note[1]、・・・、Note[N−1]は、図2において、CPU201によってROM202からRAM203に転送された後に、順次読み出されて処理されるが、発音開始時刻Timeの順に並ぶように、インデックス番号(0、1、・・・、N−1)が付与されている。
図4は、図2のCPU201による後述する制御処理によってRAM203上に生成される動作データframe[0]、frame[1]、・・・、frame[FrameCount−1]のデータ構成例を示す図であり、図1の動作情報107、108に対応する。frame[0]、frame[1]、・・・、frame[FrameCount−1]はそれぞれ、フレーム番号0、1、・・・、FrameCount−1に対応する動作データである。すなわち、動作データの出力単位はフレームである。FrameCountは、RAM203上に生成される動作データのフレームの総数を示す。動作データは、図2において、CPU201が表示部205に演奏動作ガイドを表示させるにあたって必要な、右手(値「0」)または左手(値「1」)を示すトラック番号「Hand」、5本の各指の演奏位置「position[0]〜position[4]」(指を置くべき鍵盤番号)(図1の「各指の演奏位置に関する情報」に対応)、そこへ動くにあたっての動作を開始・終了する時刻である動作開始時間「start」と動作終了時間「term」(図1の「動作タイミングに関する情報」に対応)、各指の状態「status[0]〜status[4]」(それぞれ、値「−1」が準備動作、値「1」が押鍵)(図1の「各指の演奏のガイド/演奏準備のガイドを指示する情報」に対応)、奥行き方向の位置「Zpos」(図1の「奥行き方向の位置に関する情報」に対応)などの情報を記憶する。
以下、本実施形態の動作について、フローチャートを用いて説明する。以下の説明において、図1の各機能部分と図2の各ハードウェア部分を随時参照するものとする。また、図3で説明した演奏情報Note[0]〜Note[N−1]、および図4で説明した動作データframe[0]〜frame[FrameCount−1]は、RAM203に記憶されるものとする。さらに、以下の説明で用いる各変数も、RAM203に記憶されるものとする。また、以下の説明では、ある変数の名称が、その変数が記憶している値を指す場合がある。
図5は、本実施形態全体動作処理を示すメインフローチャートである。この処理は、図2において、CPU201が、ROM202に記憶された制御プログラムを実行する動作として実現される。
本実施形態では、ユーザが入力部204から楽曲を選択することにより、CPU201が、その楽曲1曲分の演奏情報Note[i](0≦i≦N−1)(図3参照)をROM202からRAM203に読み出し、その読み出した各演奏情報Note[i]に対して順次、動作情報を一括して生成する。
処理が起動すると、CPU201は、RAM203上の演奏情報や各種変数を初期化し(ステップS501)、RAM203から図3に例示される構成の演奏情報を読み込み(ステップS502)、RAM203上に図4に例示されるデータフォーマットで動作データを生成し(ステップS503)、プログラムを終了する。
図6は、図5のステップS503の動作情報生成処理の例を示すフローチャートである。
まず、CPU201は、各変数を初期化する(ステップS601)。CPU201は、演奏情報検索ポインタ変数meTail[0]に、RAM203に図3に例示されるフォーマットで記憶されている演奏情報Note[0]、Note[1]、・・・、Note[N]のうちから、トラック番号(図3参照)を参照することにより、右手パートの最初の演奏情報へのポインタを設定する。同様に、CPU201は、演奏情報検索ポインタ変数meTail[1]に、上記演奏情報Note[0]、Note[1]、・・・、Note[N]のうちから、左手パートの最初の演奏情報へのポインタを設定する。動作開始時刻変数start[0]とstart[1]には、時刻0が設定される。start[0]は右手パート用、start[1]は左手パート用である。この変数は、ステップS607の動作データ出力の処理で使用される。現在のタイミングにおいて各指を押鍵中とすべき演奏情報へのポインタ変数Hand[0][0]〜Hand[0][4](これら4つの変数は右手の親指から小指に対応)およびHand[1][0]〜Hand[1][4](これら4つの変数は左手の親指から小指に対応)には、未定義値NULLが設定される。以降、この変数を、「押鍵対象演奏情報ポインタ変数」と呼ぶ。また、図4の動作データの総数を示す変数FrameCountの値が「0」に初期設定される。この変数は、ステップS607の動作データ出力の処理で操作される。
次に、CPU201は、次鍵の検索の処理を実行する(ステップS602)。この処理は、各パートの各指の次に押鍵する演奏情報へのポインタ変数Next[0][0]〜Next[0][4](これら4つの変数は右手パートの親指から小指に対応)およびNext[1][0]〜Next[1][4](これら4つの変数は左手パートの親指から小指に対応)の各値を算出する処理である。以降、この変数を、「次タイミング演奏情報ポインタ変数」と呼ぶ。ステップS602は、最初の実行であって、ステップS601により、右手パートの演奏情報検索ポインタ変数meTail[0]と左手パートの演奏情報検索ポインタ変数meTail[1]には、それぞれ各パートの最初の演奏情報へのポインタが設定されているこのため、ステップS602での次鍵の検索の処理により、曲の先頭の発音タイミングに対して、各パート毎に、各指においてその次のタイミングで押鍵されるべき各演奏情報へのポインタ変数Next[0][0]〜Next[0][4]およびNext[1][0]〜Next[1][4]が予め取得されることになる。この次タイミング演奏情報ポインタ変数は、ステップS605のパート毎の状態確認処理の中の準備確認の処理(後述する図9のステップS908および図12〜図15参照)で参照される。なお、このステップS602の次鍵の検索の処理は、図9のステップS904またはS905の処理の後、ステップS906の処理に先立って行うようにしてもよい。
その後、CPU201は、ステップS603で、右手パート演奏情報検索ポインタ変数meTail[0]および左手パート演奏情報検索ポインタ変数meTail[1]がそれぞれ参照する演奏情報Note[0]、Note[1]、・・・、Note[N]のうちの発音開始時刻Time(図3参照)が早い方、すなわち、右手パートと左手パートのうちの先に演奏すべき演奏情報を、検索ポインタ変数mePtrに設定しながら、ステップS604で検索ポインタ変数mePtrの内容が未定義値NULLとなってRAM203上の演奏情報の検索が全て終了したと判定するまで、以下のステップS605、S606、およびS607の一連の処理を繰り返し実行する。
なお、右手パート演奏情報検索ポインタ変数meTail[0]および左手パート演奏情報検索ポインタ変数meTail[1]の各内容は、ステップS605の中の押鍵検索の処理(後述する図9のステップS907および図11のS1110参照)で、現在の押鍵タイミングに対応して各パート毎に同時に押鍵すべき演奏情報が検索される毎に、それらの同時に押鍵すべき演奏情報の次に押鍵すべき演奏情報へのポインタとして、順次更新される。
まず、CPU201は、パート毎の状態確認の処理を実行する(ステップS605)。ここでは、CPU201は、図1の操作状態推定手段102の機能に対応する処理を実行する。この結果、右手パート出力バッファ用演奏情報ポインタ変数prep[0][0]〜prep[0][4](これら4つの変数は右手パートの親指から小指に対応)に、右手パートのそれぞれの指で押鍵を行う演奏情報と押鍵の準備動作を行う演奏情報へのポインタが得られる。同様に、左手パート出力バッファ用演奏情報ポインタ変数prep[1][0]〜prep[1][4](これら4つの変数は左手パートの親指から小指に対応)に、左手パートのそれぞれの指で押鍵を行う演奏情報と押鍵の準備動作を行う演奏情報へのポインタが得られる。
次に、CPU201は、パート同士の状態比較の処理を実行する(ステップS606)。ここでは、CPU201は、図1のパート同士の状態比較手段103の機能に対応する処理を実行する。ここでは、CPU201は、前述したように、左右パート間で、押鍵を行う指同士が衝突しそうになったり、あるいは次の押鍵のために押鍵の準備動作を行う指と押鍵を行う指が衝突しそうになったりする状態を検知する。そして、CPU201は、右手パート鍵盤奥行き方向状態補正値zOffset[0]と左手パート鍵盤奥行き方向状態補正値zOffset[1]、および右手パート鍵盤横方向状態補正値xOffset[0]と左手パート鍵盤横方向状態補正値xOffset[1]を、それぞれ生成する。右手パート鍵盤奥行き方向状態補正値zOffset[0]は、現在のタイミングで右手パートについて押鍵を行う指または押鍵の準備動作を行う指の鍵盤上での演奏位置を、衝突の検知状態に応じて鍵盤の奥行き方向で補正するための値である。同様に、左手パート鍵盤奥行き方向状態補正値zOffset[1]は、現在のタイミングで左手パートについて押鍵を行う指または押鍵の準備動作を行う指の鍵盤上での演奏位置を、衝突の検知状態に応じて鍵盤の奥行き方向で補正するための値である。一方、右手パート鍵盤横方向状態補正値xOffset[0]は、現在のタイミングで右手パートについて押鍵を行う指または押鍵の準備動作を行う指の鍵盤上での配置位置を、衝突の検知状態に応じて鍵盤の横方向で補正するための値である。同様、左手パート鍵盤横方向状態補正値xOffset[1]は、現在のタイミングで左手パートについて押鍵を行う指または押鍵の準備動作を行う指の鍵盤上での配置位置を、衝突の検知状態に応じて鍵盤の横方向で補正するための値である。
最後に、CPU201は、動作データ出力の処理を実行する(ステップS607)。動作データ出力の処理では、CPU201は、図1の操作状態推定手段102の機能に対応する処理を実行する。この結果、CPU201は、図4で説明したデータフォーマットで、演奏ガイドを実行するための動作データ(図1の「動作情報108」に対応)を出力する。
CPU201は、以上のステップS605、S606、およびS607の一連の処理を、演奏情報の発音タイミング毎に実行することにより、各動作タイミングにおける演奏ガイドのための動作データを一括して出力することが可能となる。
図7は、図6のステップS602の次鍵の検索の処理の例を示すフローチャートである。
CPU201はまず、パート検索用変数iHに値0を設定する(ステップS701)。パート検索用変数iHは、右手または左手のうちどちらを処理するかを示す情報であり、その値が0なら右手、1なら左手を示す。その後、CPU201は、ステップS707でパート検索用変数iHの値を+1しながら、ステップS902で変数iHの値が2に達したと判定するまで、変数iHが示す右手および左手の各パート毎に、以下のステップS703からS706の一連の処理を実行する。これにより、CPU201は、演奏ガイド開始時の押鍵タイミングに対する、右手パート次タイミング演奏情報ポインタ変数Next[0][0]〜Next[0][4]および左手パート次タイミング演奏情報ポインタ変数Next[1][0]〜Next[1][4]を設定する。
次に、CPU201は、指番号指定変数ifigに値「0」を格納する(ステップS703)。
次に、CPU201は、ステップS706で指番号指定変数ifigの値を+1ずつしながら、ステップS704で変数ifigの値が片手の指の最大数「5」に達したと判定するまで、ステッ705で、変数ifigが示す指に対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]を更新する処理を実行する。ここで、ifig=0ならば親指、ifig=1ならば人差し指、ifig=2ならば中指、ifig=3ならば薬指、ifig=4ならば小指が、それぞれ指定されたことになる。
図8は、図7のステップS705のNext[iH][ifig]の更新処理の例を示すフローチャートである。
まず、CPU201は、現在のパートiHおよび現在の指番号ifigが示す指に対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]に未定義値NULLを格納する(ステップS801)。
次に、CPU201は、演奏情報検索用変数iに、現在のパートiHに対応する演奏情報検索ポインタ変数meTail[iH]に+1した値を格納する(ステップS802)。これは、現在のパートの演奏情報の次の演奏情報から検索が行われるという意味である。
次に、CPU201は、ステップS806で演奏情報検索用変数iの値を+1ずつしながら、ステップS803で変数iの値が演奏情報の最大数(図3の例では、演奏情報の最大数=N)に達したと判定するまで、各演奏情報Note[i](現在の演奏情報のインデックス番号+1≦i≦N−1)毎に、以下のステップS804とS805の判定処理を実行する。
すなわち、CPU201はまず、演奏情報検索用変数iが示す演奏情報Note[i]中の右手または左手を示すトラック番号Hand(図3参照)(図8中では「Note[i].Hand」と記載)が、パート検索用変数iHの値が示す現在処理中のパート番号に等しいか否かを判定する(ステップS804)。なお、図8中の「==」は、その両辺の値同士が「等しい」ことを検査する演算子である。
ステップS804の判定がNOならば、演奏情報検索用変数iが示す演奏情報Note[i]は、現在処理対象としている手(右手または左手)以外で演奏する音符であるので、CPU201は、ステップS806の処理に移行して、次の演奏情報の検索に進む。
ステップS804の判定がYESならば、CPU201はさらに、演奏情報検索用変数iが示す演奏情報Note[i]中の指番号Finger(図3参照)(図8中では「Note[i].Finger」と記載)が、現在処理中の指番号ifig(図7のステップS703、S704、S706参照)に等しいか否かを判定する(ステップS805)。
ステップS805の判定がNOならば、演奏情報検索用変数iが示す演奏情報Note[i]は、現在処理対象としている指以外で演奏する音符であるので、CPU201は、ステップS806の処理に移行して、次の演奏情報の検索に進む。
ステップS805の判定がYESになると、CPU201は、現在のパート番号iHおよび現在の指番号ifigが示す指に対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]に、トラック番号(パート番号)と指番号が一致して検索された演奏情報Note[i]へのポインタ値(記憶アドレス等)を格納して、次タイミング演奏情報ポインタ変数Next[iH][ifig]の更新処理を終了する。
ステップS804またはS805の判定がNOの状態が続き、やがて全ての演奏情報についての検索が終了してステップS803の判定がNOになると、CPU201は、図8のフローチャートで示される、ifigで表される指に関しての次タイミング演奏情報ポインタ変数Next[iH][ifig]の内容がステップS801でNULLに設定されたまま、その更新処理を終了する。そしてこの図8処理は、図7で、ifigによる指の指示を順次変えながら繰り返して実行されて、現在処理中のパート(右手・左手)の全ての指について順次処理が行われる。
以上のようにして、図7と図8のフローチャートで示される処理の例によって、図6のステップS602の次鍵の検索の処理が実現される。
図9は、図6のステップS605のパート毎の状態確認の処理の例を示すフローチャートである。
CPU201はまず、パート検索用変数iHに値0を設定する(ステップS901)。前述したように、パート検索用変数iHの値は、0なら右手、1なら左手を示す。その後、CPU201は、ステップS909でパート検索用変数iHの値を+1しながら、ステップS902で変数iHの値が2に達したと判定するまで、変数iHが示す右手および左手の各パート毎に、以下のステップS903からS908の一連の処理を実行して、動作データ(図4参照)を一括して生成する。
まず、CPU201は、検索ポインタ変数mePtrの値が現在のパートiHに対応する演奏情報検索ポインタ変数meTail[iH]の値と等しいか否かを判定する(ステップS903)。
本実施形態では、パート検索用変数iHの値の制御(ステップS901、S902、S909)によって、右手パート(iH=0)における押鍵の状態または押鍵の準備動作の状態を検出する処理と左手パート(iH=1)における押鍵の状態または押鍵の準備動作の状態を検出する処理が常にペアで処理される。これは、後述するように、本実施形態では、図6のステップS606のパート同士の状態比較の処理において、右手パートの演奏状態と左手パートの演奏状態を比較して衝突が発生するかどうかを判定する必要があるためである。
そして、前述したように、図6のステップS603において、検索ポインタ変数mePtrには、右手パート演奏情報検索ポインタ変数meTail[0]と左手パート演奏情報検索ポインタ変数meTail[1]のうち、各ポインタが示す演奏情報の発音開始時刻Time(図3参照)が早い方の演奏情報へのポインタが格納される。なお、左右パート同時に発音される場合には、mePtr=meTail[0]=meTail[1]となっている。
mePtr==meTail[iH]となってステップS903の判定がYESなら、CPU201は、現在のパートiHに対応する押鍵動作フラグ変数pushKey[iH]に値「1」を設定する。一方、mePtr≠meTail[iH]となってステップS903の判定がNOなら、pushKey[iH]に値「0」を設定する。押鍵動作フラグ変数pushKey[iH]は、右手パートと左手パートのうち早く押鍵または押鍵の準備動作のガイド(以下「押鍵動作」と記載する)が開始されたほうのタイミングで、現在のパートiHがその早いほうの押鍵動作のタイミングであるか(値「1」)、否か(値「0」)を示すフラグである。図17のフローチャートの説明で後述するように、CPU201は、図6のステップS606のパート同士の状態比較の処理において、右手パートと左手パートの比較を行うときに、右手パートおよび左手パートのうちどちらが早く押鍵動作に入ったかを判別することにより、適切な衝突回避の制御を行う。この判別のために、CPU201は、ステップS903で設定された押鍵動作フラグ変数pushKey[iH]の値を参照する。
ステップS904またはS905の処理の後、CPU201は、離鍵確認の処理を実行する(ステップS906)。なお、ここで、図6のステップS602の「次鍵の検索」の処理をステップS906の処理に先立って行うこととしてもよい。離鍵確認の処理では、押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]が示す現在のパートiHの5本の各指の押鍵状態を示す演奏情報のうち、発音期間(発音開始時刻Time+発音継続時間Gate)(図3参照)が、演奏情報検索ポインタ変数meTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報の発音開始時刻Timeよりも前に終了する指があれば、その指の押鍵状態が終了させられる。
次に、CPU201は、押鍵検索の処理を実行する(ステップS907)。押鍵検索の処理では、演奏情報検索ポインタ変数meTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報と同時に押鍵を行うべき現在のパートiHに属する演奏情報が検索される。そして、その検索された演奏情報がmeTail[iH]が示す演奏情報とともに、各演奏情報に登録されている指に対応する押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]にセットされる。また、次タイミング演奏情報ポインタ変数Next[iH][0]〜Next[iH][4]のうち、上記セットが行われた指に対応するポインタの内容が、そのセットが行われた指においてその次のタイミングで押鍵されるべき現在のパートiHに属する演奏情報へのポインタ値に更新される。なお、同じパートに属し同時に発音開始される演奏情報はRAM203上では連続して記憶されている。このため、上記押鍵検索の処理により同時に発音開始される演奏情報が検索された後は、演奏情報検索ポインタ変数meTail[iH]の内容は、それらの同時に押鍵すべき演奏情報を飛び越して、その次に押鍵すべき演奏情報へのポインタとして設定される。
続いて、CPU201は、準備確認の処理を実行する(ステップS908)。この結果、演奏情報検索ポインタ変数meTail[iH]が示す演奏情報中の発音開始時刻Time(図3参照)に対応する押鍵タイミングにおいて、パートiHの5本の各指で押鍵または押鍵の準備動作を行う演奏情報へのポインタが、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4](これら4つの変数はパートiHの親指から小指に対応)に得られる。この処理が、ステップS901、S902、およびS909で制御されるパート検索用変数iHの値「0」および「1」毎に実行されることにより、右手パートに対応する出力バッファ用演奏情報ポインタ変数prep[0][0]〜prep[0][4]と、左手パートに対応する出力バッファ用演奏情報ポインタ変数prep[1][0]〜prep[1][4]が算出される。
上述の準備確認の処理では、演奏情報が順次読み込まれながら、曲の各再生時点において、再生時点における演奏情報に対応する演奏状態とその再生時点以降における演奏情報に対応する演奏状態とが比較される。この結果、例えば、親指で押鍵中に親指以外の指で親指の上を越えて移動させて次以降のタイミングにて押鍵する第1の状態(指越え)が検出される。または、親指以外の指で押鍵中に親指で親指以外の指の下をくぐらせて移動させて次以降のタイミングにて押鍵する第2の状態(指くぐり)が検出される。また、第1および第2のいずれの状態でもなく、任意の指で押鍵中の鍵から所定の基準値に比較して近い位置の異なる鍵を次以降のタイミングにてその任意の指以外の指で押鍵する第3の状態が検出される。あるいは、任意の指で押鍵中の鍵と同じ鍵を次のタイミングにてその任意の指以外の指で押鍵する第4の状態が検出される。さらには、現在押鍵されている鍵から所定の基準値よりも離れた位置の鍵が次に押鍵される状態が検出される。
以上のステップS906の離鍵確認の処理、ステップS907の押鍵検索の処理、ステップS908の準備確認の処理は、図1の操作状態推定手段102の機能を実現する。
図10は、図9のステップS906の離鍵確認の処理の例を示すフローチャートである。
まず、CPU201は、指番号指定変数ifigに値「0」を格納する(ステップS1001)。
次に、CPU201は、ステップS1006で指番号指定変数ifigの値を+1ずつしながら、ステップS1002で変数ifigの値が片手の指の最大数「5」に達したと判定するまで、ステップ1003からS1005の一連の処理を実行する。なお、変数ifigの各値の意味は、図7の場合と同じである。
CPU201は、現在のパートiH(ステップS901、S902、S909参照)および現在の指番号ifigが示す押鍵対象演奏情報ポインタ変数Hand[iH][ifig]の値が未定義値Nullでないか否かを判定する(ステップS1003)。なお、図10中の「!=」は、その両辺の値同士が「等しくない」ことを検査する演算子である。前述のように、押鍵対象演奏情報ポインタ変数Hand[iH][ifig]は、現在のパートiHのifigで表される指が押鍵中である場合の演奏情報へのポインタ変数であるので、このHand[iH][ifig]の値がNullでない場合は、その指が押鍵中であることを意味する。
ステップS1003の判定がNOならば、Hand[iH][ifig]の値がNullでありその指は押鍵中では無いので、CPU201は、ステップS1006の処理に移行し、次の指の処理に移行する。
押鍵対象演奏情報ポインタ変数Hand[iH][ifig]の値が未定義値でなくステップS1003の判定がYESならば、CPU201は、ポインタ変数Hand[iH][ifig]が指す演奏情報の発音開始時刻Time(図3参照)にその演奏情報の発音継続時間Gateを加算することにより、その演奏情報の発音終了時刻を算出する。そして、CPU201は、ポインタ変数Hand[iH][ifig]が指す演奏情報の上記発音終了時刻が、演奏情報検索ポインタ変数meTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報の発音開始時刻Timeよりも前である(小さい)か否かを判定する(ステップS1004)。
ポインタ変数Hand[iH][ifig]が指す演奏情報の発音終了時刻がmeTail[iH]が示す演奏情報の発音開始時刻Timeよりも前でステップS1004の判定がYESならば、CPU201は、ポインタ変数Hand[iH][ifig]に未定義値NULLを格納して、現在の指番号ifigが示す指を離鍵状態にする(ステップS1005)。
その後、CPU201は、ステップS1006の処理に移行し、次の指の処理に移行する。
5本全ての指についての確認が終了してステップS1002の判定がNOになると、CPU201は、図10のフローチャートで示される図9のステップS906の離鍵確認の処理を終了する。
以上のようにして、図10のフローチャートの処理の例で示される図9のステップS906の離鍵確認の処理によって、押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]が示す現在のパートiHの各指で押鍵中とされている演奏情報のうち、現在処理中のmeTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報の発音開始時刻よりも発音終了時刻が前となる指について、離鍵状態とされる。
図11は、図9のステップS907の押鍵検索の処理の例を示すフローチャートである。
CPU201はまず、演奏情報検索用変数iに、現在の処理対象のmeTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報のインデックス番号index(図3参照)の値をセットする。つまり、同時発音を行う演奏情報を検索するための開始位置が、現在処理対象の演奏情報自身とされる(ステップS1101)。
次に、CPU201は、ステップS1108で演奏情報検索用変数iの値を+1ずつしながら、ステップS1102で変数iの値が演奏情報の最大数(図3の例では、演奏情報の最大数=N)に達したと判定するまで、ステップS1103からS1107までの一連の処理を実行する。
CPU201はまず、演奏情報検索用変数iが示す演奏情報Note[i]中の右手または左手を示すトラック番号Hand(図3参照)(図8中では「Note[i].Hand」と記載)が、パート検索用変数iHの値が示す現在のパート(図9のステップS901、S902、S912参照)に等しいか否かを判定する(ステップS1103)。
ステップS1103の判定がNOならば、演奏情報検索用変数iが示す演奏情報Note[i]は、現在処理中のパート(右手・左手の別)ではないので、CPU201は、ステップS1108の処理に移行して、次の演奏情報の検索に進む。
ステップS1103の判定がYESならば、CPU201は、演奏情報検索用変数iが示す演奏情報Note[i]中の発音開始時刻Time(図3参照)(図11中では「Note[i].Time」と記載)が、現在処理対象の演奏情報検索ポインタ変数meTail[iH]が示す演奏情報の発音開始時刻Time(図3参照)(図11中では「meTail[iH].Time」と記載)と同時刻であるか否かを判定する(ステップS1104)。
同時刻の演奏情報が見つかりステップS1104の判定がYESならば、CPU201は、指番号指定変数ifigに、現在検索されている演奏情報Note[i]中の指番号Finger(図11中では「Note[i].Finter」と記載)を格納する(ステップS1105)。なお、最初の処理では、「i=meTail[iH]のインデックス番号」であるから(ステップS1101参照)、ステップS1104の判定は、「Note[i].Time=meTail[iH].Time==meTail[iH].Time?」という自分自身を自分自身と比較する判定になる。このため、ステップS1104の判定は、必ずYESとなる。
次に、CPU201は、検索された演奏情報Note[i]の指番号Finger(図3参照)を、現在の指番号ifigに格納する(ステップS1105)。
その後、CPU201は、現在の指番号ifigが示す押鍵対象演奏情報ポインタ変数Hand[iH][ifig]に、検索された演奏情報Note[i]へのポインタを格納する(ステップS1106)。前述したように、最初の処理では、ステップS1105の判定は必ずYESとなるため、現在処理対象の演奏情報検索ポインタ変数meTail[iH]が示す演奏情報へのポインタは、必ず押鍵対象演奏情報ポインタ変数Hand[iH][ifig]に登録されることになる。
最後に、CPU201は、検索された演奏情報Note[i]に対応する指番号ifig(ステップS1105参照)が示す指に対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]を更新する処理を実行する(ステップS1107)。この処理の例は、前述した図8のフローチャートで示される。ただし、図8のステップS802では、CPU201は、演奏情報検索用変数iに、検索された現在の演奏情報のカウンタ値iに+1した値を格納する。これは、検索された同時発音を行う現在の演奏情報Note[i]の次の演奏情報から、次に押鍵される演奏情報の検索が行われるという意味である。
ステップS1107の処理の後、CPU201は、ステップS1108の処理に移行して、次の演奏情報の検索に進む。
ここで、図3で説明したように、演奏情報Note[0]、Note[1]、・・・、Note[N]は、発音開始時刻Timeの順に並ぶように、インデックス番号(0、1、・・・、N)が付与されている。従って、ステップS1104の判定で、現在の演奏情報検索用変数iが示す演奏情報Note[i]中の発音開始時刻Timeが、現在処理対象のmeTail[iH]が示す演奏情報の発音開始時刻Timeと同時刻ではなく、判定結果がNOならば(ステップS1104の判定がNO)、現在の演奏情報検索用変数iが示す演奏情報Note[i]以降には同時刻の演奏情報は存在しない。そこでこの場合には、CPU201は、押鍵検索の処理を終了する。この場合、同時発音を行うとして検索された演奏情報については、図9のステップS908では、現在の処理対象のmeTail[iH]が示す演奏情報とともに、押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]にセットされて一括して処理される。このため、以降は図9のステップS902からS909までの処理ループを実行する必要はない。このため、CPU201は、現在のパートiHの処理対象の演奏情報検索ポインタ変数meTail[iH]に、同時発音を行う演奏情報のグループを飛び越えて、最後に捨てS1104の判定がNOとなったときの演奏情報検索用変数iが示す演奏情報Note[i]へのポインタを設定する(ステップS1110)。
ただし、このステップS1110の処理が実行されるのは、現在のパートiHが他方のパートと同じかそれよりも早い押鍵動作のタイミングであって現在のパートiHに対応する押鍵動作フラグ変数pushKey[iH]に値「1」が設定されている場合のみとする(ステップS1109の判定がYES)。現在のパートiHが他方のパートよりも遅い押鍵動作のタイミングであって現在のパートiHに対応する押鍵動作フラグ変数pushKey[iH]に値「0」が設定されている場合には、ステップS1109の判定はNOとなる。この場合には、現在のパートiHの処理対象の演奏情報検索ポインタ変数meTail[iH]の内容は更新されずに、図11のフローチャートで示される図9のステップS907の押鍵検索の処理を終了する。後述するように、図6のステップS607の動作データ出力の処理では、pushKey[iH]に値「0」が設定されていて右手パートと左手パートの衝突が発生していないときには動作データ出力の処理は実行されない(図18のステップS1803の判定がNOとなる)。このため、pushKey[iH]に値「0」が設定されているときには、図11のステップS1109の判定がNOとなって演奏情報検索ポインタ変数meTail[iH]の内容は更新されず、そのパートiHに関しては、図5のステップS603でpushKey[iH]に値「1」が設定されるまでmeTail[iH]の更新による演奏ガイドの表示進行が待たれることになる。
ステップS1110の処理の後、CPU201は、図11のフローチャートで示される図9のステップS907の押鍵検索の処理を終了する。
また、全ての演奏情報についての検索が終了してステップS1102の判定がNOになった場合も、CPU201は、図11のフローチャートで示される図9のステップS907の押鍵検索の処理を終了する。
図12から図15は、図9のステップS908の準備確認の処理の例を示すフローチャートである。
この図12から図15の準備確認の処理を通して、prep[iH][0]〜prep[iH][4]には、図6のステップS607の動作データ出力の処理において図4の動作データを出力するために対象となる現在のパートiHの各指の演奏情報が格納される。この場合の演奏情報には、対応する動作データの出力タイミングにおいて、現在のパートiHの各指で押鍵を行う演奏情報と、次の動作タイミングでの押鍵の準備動作を行う演奏情報がある。まず、CPU201は、図12のステップS1201からS1208までの一連の処理によって、押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]の内容を、いったん出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]にコピーする。このコピー処理では、まずは押鍵対象となっている演奏情報が格納されているポインタ変数Hand[iH][0]〜Hand[iH][4]の内容がprep[iH][0]〜prep[iH][4]にコピーされる。その後、図13から図15のフローチャートでは、現在のパートiHの各指の次タイミング演奏情報ポインタNext[iH][0]〜Next[iH][4]の中から準備動作の対象となる演奏情報が判別される。そして、その判別された演奏情報が、後述する図15のステップS1239で、prep[iH][0]〜prep[iH][4]に追加的に登録される。
CPU201はまず、準備動作判定用変数Moving、Passingに、共に値「0」を格納する(ステップS1201)。
次に、CPU201は、指番号指定変数ifigと押鍵指数カウンタ変数figuseに、共に値「0」を格納する(ステップS1202)。
その後、CPU201は、ステップS1208で指番号指定変数ifigの値を+1ずつしながら、ステップS1203で変数ifigの値が片手の指の最大数「5」に達したと判定するまで、ステップS1204からS1207までの一連の処理を実行する。
まず、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]に、共に未定義値NULLを格納する。また、CPU201は、現在の指番号ifigに対応するステップデータstep[ifig]に値「−1」を格納する(以上、ステップS1204)。ステップデータstep[ifig]は、現在の指番号ifigに対応する指が、どの押鍵段階にあるかを示す。step[ifig]=0ならばその指を今回押鍵すべきであることを示し、step[ifig]=1,2,・・・ならばその指を次回、その次、・・・で押鍵すべきであることを示す。ステップS1204で設定されるstep[ifig]=−1は、その指についてはまだ押鍵段階が決定されていないことを示す。
次に、CPU201は、現在のパートiHの現在の指番号ifigに対応する押鍵対象演奏情報ポインタ変数Hand[iH][ifig]の内容を出力バッファ用演奏情報ポインタ変数prep[iH][ifig]にコピーする(ステップS1205)。
次に、CPU201は、現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の内容が未定義値NULLでないか否かを判定する(ステップS1206)。
prep[iH][ifig]の内容が未定義値NULLでなくステップS1206の判定がYESならば、現在のパートiHの現在の指番号ifigに対応する押鍵対象演奏情報ポインタ変数Hand[iH][ifig]の内容がNULLではなかったということなので、CPU201は、現在の指番号ifigに対応するステップデータstep[ifig]に今回押鍵を示す値「0」を格納する。さらに、CPU201は、押鍵指数カウンタ変数figuseの値を+1インクリメントする(図12中では「++」という演算子で記載)(以上、ステップS1207)。
prep[iH][ifig]の内容が未定義値NULLであってステップS1206の判定がNOである場合、またはステップS1207の処理の後、CPU201は、ステップS1208の処理に移行し、次の指に対する処理を実行する。
以上のステップS1203からS1208までの一連の処理の後、5本の指についてのコピー処理が終了しステップS1203の判定がNOとなった時点で、押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]のうち押鍵を示す演奏情報へのポインタが出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]にコピーされている。この場合、ステップデータstep[0]〜step[4]のうち押鍵状態にある指に対応するデータには値「0」が格納され、それ以外の指に対応するデータには未定義状態を示す値「−1」が格納される状態となる。
図12のステップS1203の判定がNOとなった後、CPU201は、図13のステップS1209からS1219の一連の処理を実行する。ここでは、現在のパートiHの各指の次タイミング演奏情報ポインタ変数Next[iH][0]〜Next[iH][4]のうちから、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]において演奏情報へのポインタが定義されていない指に対応するデータであって、かつ発音開始時刻が最も早い演奏情報へのポインタとそれに対応する指番号が、それぞれ変数NotePreとfigに取得される。
すなわち、CPU201はまず、押鍵指数カウンタ変数figuseの値が5より小さいか否かを判定する(ステップS1209)。
もし、押鍵指数カウンタ変数figuseの値が5になっていると、現在のパートiHの5本全ての指が押鍵中を示していることになり(図12のステップS1206とS1207参照)、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]において演奏情報へのポインタが定義されていない指はない。この場合には、図13のステップS1209の判定がNOとなって、CPU201は、図9のステップS908の準備確認の処理を終了する。この場合は、準備動作判定用変数Moving、Passingの値は図12のステップS1201で共に値「0」とされたままになる。そして、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]に設定されている5つの演奏情報は、全て押鍵対象演奏情報ポインタ変数Hand[iH][0]〜Hand[iH][4]に設定されていた、同時刻に発音開始する5つの演奏情報がそのまま格納される。この結果、後述する図6のステップS607の動作データ出力の処理(後述する図19のステップS1815→S1816参照)において、各指の状態status[0]〜status[4](図4参照)として共に押鍵を示す値「1」が設定される。すなわち、後述する図19のステップS1817→S1818の処理は一度も実行されず、各指の状態status[0]〜status[4](図4参照)のいずれにも、準備動作を示す値「−1」は設定されないことになる。
押鍵指数カウンタ変数figuseの値が5より小さくステップS1209の判定がYESならば、CPU201は、現在の押鍵比較段階変数stepに初期値「1」を格納する(ステップS1210)。押鍵比較段階変数stepの値は、現在の押鍵タイミングで押鍵中とされる演奏情報に対して何タイミング後に押鍵される演奏情報の比較が行われるかを示す。step=1であれば、現在押鍵中の演奏情報に対して次のタイミングにて押鍵される演奏情報の比較が行われることを示す。step=2であれば、現在押鍵中の演奏情報に対して次の次のタイミングにて押鍵される演奏情報の比較が行われることを示す。押鍵比較段階変数stepの値は、ステップS1209で値「1」に初期設定された後、後述する図15のステップS1240で+1ずつインクリメントされ、ステップS1211からS1219の探索が繰り返し実行される。
次に、CPU201は、現在の押鍵比較段階stepにおいて、まだ押鍵や準備動作が決定されていない指のうちで発音開始時刻が最も早い演奏情報へのポインタを格納する変数NotePreに未定義値NULLを格納し、それに対応する指番号を格納する変数figにどの指でもないことを示す値「−1」を格納する(ステップS1211)。
次に、CPU201は、ステップS1212で指番号指定変数ifigに初期値「0」(親指)を設定した後、ステップS1219でifigの値を+1ずつインクリメントしながら、ステップS1213で片手の指の最大数「5」に達したと判定するまで、以下のステップS1214からS1218の一連の処理を実行する。
CPU201はまず、現在の指番号ifigに対応するステップデータstep[ifig]の値が、指番号ifigの指についてはまだ押鍵段階が決定されていないことを示す値「−1」(図12のステップS1204参照)であるか否かを判定する(ステップS1214)。
現在の指番号ifigに対応するステップデータstep[ifig]の値が「−1」以外でありステップS1214の判定がNOならば、その指番号ifigの指は押鍵または押鍵の準備動作をすることが決定済みであるため、CPU201は、ステップS1219の処理に移行し、次の指番号の処理に進む。
現在の指番号ifigに対応するステップデータstep[ifig]の値が「−1」でありステップS1214の判定がYESならば、CPU201は、現在のパートiHの現在の指番号ifigに対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]の値が未定義値NULLでないか否かを判定する(ステップS1215)。
Next[iH][ifig]の値が未定義値NULLであってステップS1215の判定がNOならば、その指番号ifigに対応する指について次以降のタイミングで押鍵されることはない。このため、CPU201は、ステップS1219の処理に移行し、次の指番号の処理に進む。
Next[iH][ifig]の値が未定義値NULLではなくステップS1215の判定がYESならば、CPU201は、まだ押鍵や準備動作が決定されていない指のうちで発音開始時刻が最も早い演奏情報へのポインタを格納する変数NotePreの内容が未定義値NULLではなく、かつ変数NotePreが示す演奏情報の発音開始時刻Time(図13中では「NotePre.Time」と記載)が現在の指番号ifigに対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]が示す演奏情報の発音開始時刻Time(図13中では「Next[iH][ifig].Time」と記載)よりも早い(小さい)か否かを判定する(ステップS1216)。
ステップS1216の判定がYESならば、現在の変数NotePreが示す演奏情報の発音開始時刻のほうが、現在の指番号ifigに対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]が示す演奏情報の発音開始時刻よりも早い。この場合には、CPU201は、変数NotePreの内容をそのまま維持し、ステップS1219の処理に移行し、次の指番号の処理に進む。
ステップS1216の判定がNOならば、現在の変数NotePreがまだ定義されていなかった(NULL)か、または、現在のパートiHの現在の指番号ifigに対応する次タイミング演奏情報ポインタ変数Next[iH][ifig]が示す演奏情報の発音開始時刻が、現在の変数NotePreが示す演奏情報の発音開始時刻より早いことになる。そこでこの場合には、CPU201は、Next[iH][ifig]に格納されているポインタ値を変数NotePreにコピーする(ステップS1217)。
さらに、CPU201は、現在の指番号指定変数ifigの値を変数NotePreに対応する指番号を保持する変数figにコピーする(ステップS1218)。
その後、CPU201は、ステップS1219の処理に移行し、次の指番号ifigに対する処理に進む。
以上のステップS1214からS1218までの一連の処理が、各指番号ifigについて繰り返し実行され、やがて指番号ifigの値が5になってステップS1213の判定がNOとなった時点で、変数NotePreに、まだ押鍵や準備動作が決定されていない指のうちで、その指による次の押鍵が他の指と比べて、現在の押鍵比較段階stepにおいて発音開始時刻が最も早い演奏情報へのポインタが得られる。また、変数figに、NotePreが示す演奏情報に対応する指番号が得られる。最初は、押鍵比較段階step=1である(ステップS1210参照)。従って、変数NotePreとfigには、現在の押鍵に対して次に押鍵されるべき、発音開始時刻が最も早い演奏情報へのポインタと、それに対応する指番号が得られる。
ステップS1213の判定がNOになると、CPU201は、図14のフローチャートのステップS1220からS1237までの一連の処理を実行する。ここでは、上述の変数NotePreに得られた演奏情報に対応する演奏状態が、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]のうち押鍵を示す演奏情報の演奏状態と比較される。
まず、CPU201は、変数NotePreの内容が未定義値NULLでないか否かを判定する(ステップS1220)。図13のステップS1213からS1219の実行状態によっては、変数NotePreの内容が図13のステップS1211で未定義値NULLに設定された後、全ての指番号ifigについて、図13のステップS1216の判定がYESにならず、ステップS1213の判定がNOになる場合があり得る。この場合には、変数NotePreには発音開始時刻が最も早い演奏情報へのポインタが得られない状態となり、NotePreの値は未定義値NULLとなる。これによりステップS1220の判定がNOとなった場合には、CPU201は、図9のステップS908の準備確認の処理を終了する。
変数NotePreの内容が未定義値NULLでなくステップS1220の判定がYESならば、CPU201は、変数NotePreの内容を出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]のいずれかへ登録するか否かを示すセット変数setに、登録を示す値「1」をひとまず格納する(ステップS1221)。このセット変数setの値は、後述する各種演奏状態の判断において非登録を示す値「0」にされ得る(図14のステップS1230、S1233、S1236)。
次に、CPU201は、現在の押鍵に対して次に押鍵されるべき発音開始時刻が最も早い演奏情報の指番号figに対応するステップデータstep[ifig]に、現在の押鍵比較段階変数stepの値(初回は値「1」)を格納する(ステップS1222)。これは、2回目以降に実行される図13のステップS1214の判定において、すでに処理された指番号については再度その判定がYESとなって選択されてしまわないようにするための制御である。また、ステップデータstep[0]〜step[4]の各値を見れば、各指が現在の押鍵タイミング以降の何番目に押鍵されるべき演奏情報であるかを知ることができ、演奏ガイドの制御に活用することも可能になるというメリットも有する。
次に、CPU201は、ステップS1223で指番号指定変数ifigに初期値「0」(親指)をセットした後、ステップS1237でifigの値を+1ずつインクリメントしながら、ステップS1224で指番号ifigの値が片手の指の最大数「5」に達したと判定するまで、以下のステップS1225からS1236までの一連の処理を実行する。この処理では、図13のステップS1214からS1218の一連の処理で得られた、まだ押鍵や準備動作が決定されていない指による次の押鍵情報に対して、現在押鍵している指(音)との関係がチェックされる。
CPU201はまず、指番号ifigの値が現在の押鍵に対して次に押鍵されるべき発音開始時刻が最も早い演奏情報の指番号figに等しくなく、かつ現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の値が未定義値NULLでなく、かつ指番号ifigに対応するステップデータstep[ifig]が押鍵を示す値「0」に等しいか否か(図12のステップS1207参照)を判定する(ステップS1225)。一番目の条件は、同じ指同士の関係は調べる必要が無いので、ifigとfigが異なっていることをチェックしている。二番目の条件は、調査対象とする指番号ifigの演奏情報がまだ決定されておらず、prep[iH][ifig]がNULLの場合は、そのような指ifigとの関係を調べる必要が無いからである。三番目の条件は、調査対象とする指番号ifigが押鍵されている指かどうかを調べているものである。この判定は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]が示す演奏情報が押鍵を示す演奏情報であるか否かの判定である。
ステップS1225の判定がNOならば、prep[iH][ifig]は押鍵を示す演奏情報を示してはいないため、ステップS1237の処理に移行し、次の指番号の処理に進む。
prep[iH][ifig]が示す演奏情報が押鍵を示す演奏情報であってステップS1225の判定がYESならば、CPU201は、prep[iH][ifig]が示す押鍵の演奏情報と、変数NotePreが示す、まだ押鍵や準備動作が決定されていない指のうちで現在の押鍵に対して次に押鍵されるべき発音開始時刻が最も早い演奏情報と、の鍵盤距離を取得する(ステップS1226)。鍵盤距離は、指番号が大きいほうの演奏情報の音高Pitch(図3参照)を鍵盤番号に換算した値から、指番号が小さいほうの演奏情報の音高Pitchを鍵盤番号に換算した値を減算した結果として算出される。この処理の詳細は、図16のフローチャートを用いて後述する。
次に、CPU201は、ステップS1226で取得した鍵盤距離が0よりも小さいか否かを判定する(ステップS1227)。
鍵盤距離が0よりも小さくステップS1227の判定がYESならば、現在関係を調査している2つの指の位置関係が、正常な手の向きにおける指の位置と逆転していることを表している。そこでこの場合、CPU201は、現在の押鍵に対して次に押鍵されるべき発音開始時刻が最も早い演奏情報の指番号figと現在の押鍵の指番号ifigのいずれかが親指の指番号「0」であるか否かを判定する(ステップS1228)。すなわち、現在関係を調査している2つの指のいずれかが、親指であるかを調べる。
ステップS1228の判定がYESの場合には、CPU201は、親指で押鍵中に親指以外の指で親指の上を越えて移動させて次以降のタイミングにて押鍵する第1の状態である、または、親指以外の指で押鍵中に親指で親指以外の指の下をくぐらせて移動させて次以降のタイミングにて押鍵する第2の状態であると判定する。
この場合には、CPU201は、準備動作判定用変数の一つである指の交差を示す指交差変数Passingに値「1」を格納する(ステップS1229)。
その後、CPU201は、ステップS1237の処理に移行し、次の指番号を有する押鍵の演奏情報との比較処理に進む。
ステップS1228の判定がNOの場合には、CPU201は、親指以外の指同士の交差はあり得ないとして、変数NotePreの内容を出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]のいずれかへ登録するか否かを示すセット変数setに、非登録を示す値「0」を格納する(ステップS1230)。すなわち、変数NotePreが示す演奏情報は、現在押鍵している指との関係上、指を交差させないと準備ができない音であることが判ったので、この音については、準備動作をする演奏情報としては登録されない。
その後、CPU201は、ステップS1237の処理に移行し、次の指番号を有する押鍵の演奏情報との比較処理に進む。
鍵盤距離が0よりも小さくなくステップS1227の判定がNOならば、CPU201は、ステップS1226で取得した鍵盤距離が基準値よりも大きいか否かを判定する(ステップS1231)。基準値は例えば、指の間隔×半音での2〜4鍵分程度の値である。例えば、親指と小指の間隔としては、指の間隔(4−0)×2〜4半音で、8半音〜16半音程度とすることができ、12半音とすれば1オクターブを基準とすることとなる。
鍵盤距離が基準値よりも大きくステップS1231の判定がYESならば、CPU201は、鍵盤を弾く手の移動範囲が大きいと判断して、セット変数setに、非登録を示す値「0」を格納する(ステップS1232)。すなわち、変数NotePreが示す演奏情報は、準備動作をする演奏情報としては登録されない。
次に、CPU201は、押鍵比較段階変数stepの値が「1」であるか否かを判定する(ステップS1233)。
ステップS1233の判定がYES、すなわち鍵盤の移動が現在の押鍵の次の動作タイミングで実行されると判定された場合には、鍵盤距離が基準値よりも大きい音が、現在の押鍵のすぐ次の動作タイミングで実行されることから、指の跳躍が必要となる場合である。そこで、CPU201は、準備動作判定用変数の一つである指の手の移動(跳躍)を示す移動変数Movingに値「1」を格納する(ステップS1234)。
このように、変数NotePreが示す演奏情報は、準備動作をする演奏情報としては登録されないが、移動変数Movingと一時バッファ用演奏情報ポインタ変数pList[NotePre.Finger]へのセットが行われる。
鍵盤距離が基準値よりも大きくはなくステップS1231の判定がNOならば、CPU201は、ステップS1226で取得した鍵盤距離が0で、かつ押鍵比較段階変数stepの値が「1」ではないか否かを判定する(ステップS1235)。この判定がYESとなる場合は、任意の指で押鍵中の鍵と同じ鍵を、現在押鍵中の指とは異なる指で、次ではない、より先のタイミングで押鍵することを表している。
ステップS1235の判定がNOの場合には、CPU201は、セット変数setに登録を示す値「1」が格納された状態を維持する。すなわち、変数NotePreが示す演奏情報は、準備動作をする演奏情報として登録可能な状態にされる。その後、CPU201は、ステップS1237の処理に移行し、次の指番号を有する押鍵の演奏情報との比較処理に進む。
任意の指で押鍵中の鍵と同じ鍵を、次の次以降のタイミングにてその任意の指以外の指で押鍵する状態であってステップS1235の判定がYESとなる場合は、CPU201は、セット変数setに非登録を示す値「0」を格納する(ステップS1236)。すなわち、変数NotePreが示す演奏情報は、準備動作をする演奏情報としては登録されない。
その後、CPU201は、ステップS1237の処理に移行し、次の指番号を有する押鍵の演奏情報との比較処理に進む。
CPU201は、以上のステップS1225からS1236までの一連の処理を、0から4までの指番号ifigについて実行する。これにより、CPU201は、変数NotePreに得られた演奏情報に対応する演奏状態を、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]のうち押鍵を示す演奏情報の演奏状態と比較する。そして、CPU201は、NotePreが示す演奏情報へのポインタを、準備動作をする演奏情報へのポインタとしてprep[iH][0]〜prep[iH][4]に登録可能かどうかを判別し、セット変数setへの値のセットを行う。
現在の変数NotePreの演奏情報について、0から4までの全ての指番号ifigに対応する上述の制御動作が終了し、ステップS1224の判定がNOになると、CPU201は、図15のフローチャートの制御処理を実行する。
図15において、CPU201は、セット変数setに値「1」がセットされているか否か、つまり登録可能であると判定されているか否かを判定する(ステップS1238)。
ステップS1238の判定がYESならば、CPU201は、変数NotePreが示す演奏情報中の指番号Finger(図3参照)(図15では「NotePre.Finger」と記載)に対応する出力バッファ用演奏情報ポインタ変数prep[iH][NotePre.Finger]に、変数NotePreの値を格納する(ステップS1239)。このようにして、変数NotePreが示す演奏情報へのポインタが、準備動作を行う演奏情報へのポインタとして、prep[iH][NotePre.Finger]に登録される。
セット変数setの値が「0」でステップS1238の判定がNOならば、ステップS1239の実行はスキップされ、変数NotePreが示す演奏情報は、準備動作をする演奏情報としては出力バッファ用演奏情報ポインタ変数prep[iH][NotePre.Finger]へは登録されない。
ステップS1239の処理の後またはステップS1238の判定がNOならば、CPU201は、押鍵比較段階変数stepの値を+1インクリメントする(ステップS1240)。いままで、step=1、すなわち現在の押鍵の動作タイミングの次の動作タイミングに対応する準備動作に関する処理であったなら、これ以降、step=2となることにより、現在の押鍵の動作タイミングの次の次の動作タイミングに対応する準備動作に関する処理が実行されることになる。
CPU201は、図15のステップS1240の処理の後、図13のステップS1211の処理に戻る。そして、CPU201は、図13のステップS1211からS1219までの一連の処理によって、次タイミング演奏情報ポインタ変数Next[iH][0]〜Next[iH][4]のうちから、出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]において演奏情報へのポインタが定義されていない指に対応するデータであって、かつ上述のように最初に変数NotePreに得られた演奏情報の次に発音開始時刻が早い演奏情報へのポインタとそれに対応する指番号を、それぞれ変数NotePreとfigに取得する。そして、CPU201は、これらの変数NotePreおよびfigについて、図14および図15のフローチャートの処理を再度実行する。この結果、CPU201は、変数NotePreが示す現在の押鍵に対して次の次のタイミングで押鍵されるべき発音開始時刻が最も早い演奏情報へのポインタが、準備動作を行う演奏情報へのポインタとして、prep[iH][NotePre.Finger]に登録される。
CPU201は、以上の制御処理を繰り返し実行する結果、図13のフローチャートの実行において変数NotePreに演奏情報へのポインタが得られなくなり、図14のステップS1220の判定がNOになると、図9において演奏情報検索ポインタ変数meTail[iH]が示す現在のパートiHで最も早く押鍵が行われる演奏情報に対応するステップS908の準備確認の処理を終了する。
図16は、図14のステップS1226の鍵盤距離の取得の処理の例を示すフローチャートである。
CPU201はまず、図14の出力バッファ用演奏情報ポインタ変数prep[iH][ifig]が示す演奏情報と、変数NotePreが示す演奏情報のうち、指番号Finger(図3参照)が大きいほうの演奏情報を変数notefにセットし、指番号Fingerが小さいほうの演奏情報を変数notetにセットする(ステップS1601)。
次に、CPU201は、演奏情報notefの音高Pitch(図3参照)(図16中では「notef.Pitch」と記載)をピッチ変数pfに格納する。そして、CPU201は、次式により鍵盤位置を算出し鍵盤位置変数keyfに格納する(ステップS1602)。
keyf←OctDist×(pf/12)+KeyDist[pf%12]
・・・(1)
ここで、OctDistは定数であり値「14」を持つ。KeyDist[]={0,1,2,3,4,6,7,8,9,10,11,12}であり、KeyDist[0]=0、KeyDist[1]=1、KeyDist[2]=2、KeyDist[3]=3、KeyDist[4]=4、KeyDist[5]=6、KeyDist[6]=7、KeyDist[7]=8、KeyDist[8]=9、KeyDist[9]=10、KeyDist[10]=11、KeyDist[11]=12という値を有する。上記(1)式において、KeyDist[pf%12]は、ピッチ変数pfの値を12で除算した剰余「pf%12」(「%」は剰余演算を示す)をインデックスとするKeyDist[pf%12]値である。なお、定数OctDistは、1オクターブの鍵盤距離を表す定数である。1オクターブ間は12半音であり、OctDistも12とすることも可能であるが、ここでは、便宜上、全ての白鍵−白鍵間の鍵盤距離を2とみなして、つまり、ミ−ファ間、シ−ド間も2半音であるとみなして、OctDistとして14という値を用いている。
続いて、CPU201は、ステップS1602と同様に、演奏情報notetについても、その音高Pitch(図16中では「notet.Pitch」と記載)をピッチ変数ptに格納する。そして、CPU201は、次式により鍵盤位置を算出し鍵盤位置変数keytに格納する(ステップS1603)。
keyt←OctDist×(pt/12)+KeyDist[pt%12]
・・・(2)
その後、CPU201は、ステップS1602で算出した鍵盤位置変数keyfの値からステップS1603で算出した鍵盤位置変数keytの値を減算し、その減算結果を鍵盤距離変数distに格納する(ステップS1604)。
次に、CPU201は、現在のパート検索用変数iH(図9のステップS902とS912参照)の値が2であるか否か、すなわち、現在のパートが左手であるか否かを判定する(ステップS1605)。
CPU201は、現在のパートが左手でステップS1605の判定がYESならば、鍵盤距離変数distの値を−1倍する、すなわち符号を逆にする(ステップS1606)。右手は低音側(左側)から順に親指、人差し指、・・・、小指の順になっているが、左手は高音側(右側)から順に親指、人差し指、・・・、小指の順になっていることを加味して、後述するように、演算上、効率良く処理するためである。
CPU201は、ステップS1606の処理の後、またはステップS1605の判定がNOの場合に、図16のフローチャートで示される図14のステップS1226の鍵盤距離の取得の処理を終了する。
鍵盤距離の取得においては、指番号が大きい指の鍵盤位置から指番号が小さい指の鍵盤位置を減算して鍵盤距離distを算出している。従って、右手の場合、例えば人差し指の鍵盤位置が親指の鍵盤位置よりも大きな音高の位置にあれば、鍵盤距離distは正の値となる。また、右手において、親指で押鍵中に人差し指を親指の上を越えて親指の左側の鍵盤位置を押鍵しようとしているときには、指番号の大きい人差し指の鍵盤位置から親指の鍵盤位置を減算して得られる鍵盤距離distは0より小さい値となる。同様に、人差し指で押鍵中に親指を人差し指の下をくぐって人差し指の右側の鍵盤位置を押鍵しようとしているときには、指番号の大きい人差し指の鍵盤位置から親指の鍵盤位置を減算して得られる鍵盤距離distはやはり0より小さい値となる。
左手については、得られた鍵盤距離distの値を−1倍することにより、右手と全く同じ関係にすることができる。すなわち、左手の場合、普通に左手を鍵盤上に置くと、人差し指の鍵盤位置は親指の鍵盤位置よりも小さい音高の位置になるため、その場合、指番号の大きな人差し指の鍵盤位置から親指の鍵盤位置を減算するとマイナスになってしまう。これを右手と同じ関係にするために、−1を乗算することによりプラス値にしている。この状態で、左手において、親指で押鍵中に人差し指を親指の上を越えて親指の右側の鍵盤位置を押鍵しようとしているときには、指番号の大きい人差し指の鍵盤位置から親指の鍵盤位置を減算して得られる鍵盤距離distは0より大きな値となり、これを−1倍することにより、最終的な鍵盤距離distはマイナス値となる。同様に、人差し指で押鍵中に親指を人差し指の下をくぐって人差し指の左側の鍵盤位置を押鍵しようとしているときには、指番号の大きい人差し指の鍵盤位置から親指の鍵盤位置を減算して得られる鍵盤距離distはやはり0より大きな値となり、これを−1倍することにより、最終的な鍵盤距離distはマイナス値となる。
以上のようにして、親指がからんだ指越えまたは指くぐりが行われたときだけ、図16のフローチャートにより算出される鍵盤距離変数distの値が0より小さい値となるようにすることができる。この状態が、図14のステップS1227で判定される。
図17は、図6のステップS606のパート同士の状態比較の処理の例を示すフローチャートである。
CPU201はまず、パート間の状態補正フラグ変数conflictに、異常がないことを示す値「0」を初期設定する(ステップS1701)。
次に、CPU201は、右手パートに対応する出力バッファ用演奏情報ポインタ変数prep[0][0]〜prep[0][4]の指し示す演奏情報のうち、親指を含む最も親指に近い演奏情報を変数meRに格納する(ステップS1702)。具体的には、右手の各指のうち、押鍵または準備で使用している指のうち、もっとも親指に近いものを取得してmeRに格納する。
同様に、CPU201は、左手パートに対応する出力バッファ用演奏情報ポインタ変数prep[1][0]〜prep[1][4]の指し示す演奏情報のうち、親指を含む最も親指に近い演奏情報を変数meLに格納する(ステップS1703)。具体的には、左手の各指のうち、押鍵または準備で使用している指のうち、もっとも親指に近いものを取得してmeLに格納する。
その後、CPU201はまず、変数meLが示す演奏情報の音高Pitch(図3参照)(図17中では「meL.Pitch」と表記)が、変数meRが示す演奏情報の音高Pitch(図17中では「meR.Pitch」と表記)よりも、高い音高であるか否かを判定する(ステップS1704)。右手の親指と左手の親指は、それぞれ、他方の手に最も近い位置にある指であり、従って、これは、左手パートの指が右手パートの指の演奏領域に入り込んでいるか否かを判定していることになる。
ステップS1704の判定がYESならば、CPU201は次に、右手パートの押鍵動作フラグ変数pushKey[0]および左手パートの押鍵動作フラグ変数pushKey[1]ともに値「1」であるか否か、すなわち、両パートとも同時に押鍵を行う状態となっているか否かを判定する(ステップS1705)(図9のステップS903〜S905を参照)。
ステップS1705の判定がYESならば、CPU201は、パート間の状態補正フラグ変数conflictに異常(左右パートの衝突)が発生したことを示す値「1」をセットする。また、CPU201は、右手パート用の鍵盤奥行き方向状態補正値zOffset[0]または左手パート用の鍵盤奥行き方向状態補正値zOffset[1]のうち、鍵盤奥行き方向で、奥方向(黒鍵側)にあるパートに対応する鍵盤奥行き方向状態補正値に、例えば正の値「1」または「2」等をセットし、手前方向(白鍵側)にあるパートに対応する鍵盤奥行き方向状態補正値に、例えば負の値「−1」または「−2」等をセットする(以上、ステップS1706)。
ステップS1705の判定がNOならば、CPU201は次に、右手パートの押鍵動作フラグ変数pushKey[0]の値が「1」であるか否かを判定する(ステップS1707)。ステップS1705で両パートとも同時に押鍵を行う状態となっているか否かを判定しているため、ステップS1707での判定は右手パートのみが押鍵を行う状態となっているか否かの判定となる。この場合は、左手パートは、押鍵の準備を行う状態となっている。
ステップS1707の判定がYESならば、CPU201は、パート間の状態補正フラグ変数conflictに異常(左右パートの衝突)が発生したことを示す値「1」をセットする。また、CPU201は、左手パート用の鍵盤横方向状態補正値xOffset[1]に、ステップS1704で判定された音高の差に応じた量だけ左側方向への移動を指示するための補正値をセットする(以上、ステップS1708)。すなわちこの処理では、右手パートが押鍵を行う状態となっているので、その右手パートに衝突しそうな左手パートの押鍵準備指を、鍵盤横方向の左側方向に逃がすことにより、衝突を防止する調整が行われる。
ステップS1707の判定がNOならば、CPU201は最後に、左手パートの押鍵動作フラグ変数pushKey[1]の値が「1」であるか否かを判定する(ステップS1709)。ステップS1709での判定は左手パートのみが押鍵を行う状態となっているか否かの判定となる。この場合は、右手パートは、押鍵の準備動作を行う状態となっている。
ステップS1709の判定がYESならば、CPU201は、パート間の状態補正フラグ変数conflictに異常(左右パートの衝突)が発生したことを示す値「1」をセットする。また、CPU201は、右手パート用の鍵盤横方向状態補正値xOffset[0]に、ステップS1704で判定された音高の差に応じた量だけ右側方向への移動を指示するための補正値をセットする(以上、ステップS1710)。すなわちこの処理では、左手パートが押鍵を行う状態となっているので、その左手パートに衝突しそうな押鍵の準備動作の状態となっている右手パートの各指を、鍵盤横方向の右側方向に逃がすことにより、衝突を防止する調整が行われる。
図18および図19は、図6のステップS607の動作データ出力の処理の例を示すフローチャートである。
CPU201はまず、パート検索用変数iHに値0を設定する(ステップS1801)。前述したように、パート検索用変数iHの値は、0なら右手、1なら左手を示す。その後、CPU201は、図19のステップS1826でパート検索用変数iHの値を+1しながら、図18のステップS1802で変数iHの値が2に達したと判定するまで、変数iHが示す右手および左手の各パート毎に、以下の図18のステップS1803から図19のS1825の一連の処理を実行して、動作データ(図4参照)を一括して生成する。
始めに、CPU201は、現在のパートiHに対応する押鍵動作フラグ変数pushKey[iH]の値が「1」であるか、またはパート間の状態補正フラグ変数conflictに異常(左右パートの衝突)が発生したことを示す値「1」がセットされているか否かを判定する(ステップS1803)。
ステップS1803の判定がYESならば、CPU201は、図18のステップS1804から図19のステップS1826までの一連の処理を実行して、動作データ(図4参照)の出力処理を実行する。すなわち、現在のパートiHに対応する押鍵動作フラグ変数pushKey[iH]の値が「1」である、つまり現在のパートiHが押鍵を行う状態になっているならば、無条件に動作データの出力処理が実行される。また、現在のパートiHが押鍵を行う状態になっておらず押鍵の準備動作を行う状態になっている場合であっても、conflictに異常が発生したことを示す値「1」がセットされている、つまり左右パートの衝突が発生しそうな状態になっているならば、動作データの出力処理が実行される。これは、他方のパートが押鍵を行う状態になっていてその状態が変化する毎に、現在のパートiHのほうも衝突しないように押鍵の準備動作を行う各指の位置を移動させ、その移動後の状態で押鍵の準備動作を行う現在のパートiHのほうもガイド表示する必要があるためである。ただし、図11のステップS1109からステップS1110に移行する処理の説明で前述したように、現在のパートiHが押鍵を行う状態になっておらず押鍵の準備動作を行う状態になっていて押鍵動作フラグ変数pushKey[iH]の値が「1」でなければ、現在のパートiHの演奏情報検索ポインタ変数meTail[iH]の内容は更新されない。つまり、現在のパートiHが押鍵を行う状態になって押鍵動作フラグ変数pushKey[iH]の値が「1」になるまでは、以下に説明する動作データの出力処理では、現在のパートiHの各指の演奏位置は、衝突回避のための補正をした上で同じ押鍵の準備動作の状態を表示し続けることになる。
この動作データの出力処理では、現在のパートiHについて、図6のステップS606のパート同士の状態比較の処理でセットされた、鍵盤奥行き方向状態補正値zOffset[iH](図17のステップS1706の説明を参照)、または鍵盤横方向状態補正値xOffset[iH](図17のステップS1708または1710の説明を参照)に基づいて修正が行われる。すなわち、出力される動作データの奥行き位置frame[i].Zposの修正(図19のステップS1823)と、または出力される動作データの各指の演奏位置(鍵盤番号)frame[i].position[ifig]の修正(図19のステップS1814)が行われる。
なお、ステップS1803の判定がNO、すなわち、現在のパートiHの各指が押鍵の準備動作の状態となっていて押鍵動作フラグ変数pushKey[iH]の値が「1」ではなく、かつ左右パートの衝突が発生しておらずconflict=1でなければ、図18のフローチャートの処理を終了して、パートiHについては、動作データの出力は行われない(図18のステップS1803:NO)。この場合には、前述した図6のステップS605のパート毎の状態確認の処理における図9のステップS907の押鍵検索の処理において、押鍵を行う指ifig(図11のステップS1105)の検索および押鍵対象演奏情報ポインタ変数Hand[iH][ifig]への設定が行われた後に、図11のステップS1109の判定が行われる。ステップS1109では、現在のパートiHの押鍵動作フラグ変数pushKey[iH]が値「1」か否かが判定される。そして、ステップS1109の判定がNOならば、図11のステップS1110が実行されない結果、現在のパートiHの処理対象の演奏情報検索ポインタ変数meTail[iH]の内容は更新されずに、やがて図6のステップS603に戻る。この結果、図6のステップS603での次の演奏情報の検索において、再び同じ演奏情報が検索されることになり、これがやがて他のパートの演奏情報よりも発音開始時刻が早くなって押鍵の状態を示すようになったときに、そのタイミングで図18のステップS1803の判定がYESとなって動作データが出力される。
図18のステップS1803の判定がYESになると、始めに、CPU201は、ステップS1804からS1810の一連の処理を実行する。ここでは、変数の初期設定と、今回出力する動作データframe[i]のための今回の動作開始時間start、動作終了時間term、トラック番号Handの算出と設定等が行われる。
まず、CPU201は、動作データ(図4)の各フレームframe[i]を指示するためのフレームカウント用変数iに、現時点におけるフレームの総数FrameCountの値を格納する(ステップS1804)。このフレームの総数FrameCountは、図6のステップS601で値「0」に初期化され、後述する図19のステップS1824で+1ずつインクリメントされる。これにより、動作データの数が順次増やされてゆく。
次に、CPU201は、ステップS1805からS1810で、今回の動作タイミングにおける動作データframe[i]を生成するときの、トラック番号Hand、動作開始時間startと動作終了時間term(図4参照)を決定する。今回の検索ポインタ変数mePtrに対応する演奏情報、およびそれと同時に押鍵または準備動作される出力バッファ用演奏情報ポインタ変数prep[iH][0]〜prep[iH][4]が示す各演奏情報に対して、演奏ガイドを行うためには、次のような制御が必要となる。すなわち、その演奏ガイドは、mePtrが指す演奏情報の発音開始時刻mePtr.Timeより前からガイド表示を開始し、発音開始時刻mePtr.Timeでガイドを終了(実際に押鍵)する必要がある。
そこで、CPU201はまず、現在のパートiHに対応する動作開始時間start[iH](同名の変数に格納されている)が、今回の演奏情報の発音開始時刻mePtr.Timeよりも大きいか否かを判定する(ステップS1805)。動作開始時間start[iH]は、一番最初は図6のステップS601で値「0」に初期設定されている。また、動作途中では、一つ前の検索ポインタ変数mePtrの値における動作データ出力の処理の最後の図19のステップS1825で、次の検索ポインタ変数mePtrの値のための動作開始時間start[iH]が算出されている(後述する図21参照)。
上述のようにして算出されている今回の動作開始時間start[iH]が今回の演奏情報の発音開始時刻mePtr.Timeよりも後(大きい値)になっているときは、演奏ガイドは今回の演奏情報の発音開始時刻mePtr.Timeよりも前になければならないので、動作開始時間start[iH]の修正が必要となる。
すなわち、CPU201は、ステップS1805の判定がYESならばさらに、現在のパートiHに対応する前回の演奏情報の発音開始時刻laston[iH](同名の変数に格納されている)が、今回の演奏情報の発音開始時刻mePtr.Timeよりも小さいか否かを判定する(ステップS1806)。
ステップS1806の判定がYESならば、CPU201は、前回発音開始時刻laston[iH]から、前回発音開始時刻laston[iH]から今回の演奏情報の発音開始時刻mePtr.Timeまでの経過時間に所定の比率RATIO(例えば80%=0.8)を乗算して得られる時間だけ経過した時点を、動作開始時間start[iH]として設定する(ステップS1808)。すなわち、次式の演算が実行される。
start[iH]←laston[iH]
+(mePtr.Time−laston[iH])
×RATIO ・・・(3)
これにより、前回の音の発音開始時刻から、今回の音の発音開始時刻までの時間の、例えば80%(RATIOで表される比率)だけ経過した時点を、動作開始時間start[iH]として設定することとなる。
一方、前回発音開始時刻laston[iH]がmePtr.Timeよりも小さくなくステップS1806の判定がNOの場合には、仕方がないので、前回発音開始時刻laston[iH]を今回の動作開始時間start[iH]にセットする(ステップS1807)。
算出されている動作開始時間start[iH]が今回の演奏情報の発音開始時刻mePtr.Timeよりも大きくはなくステップS1805の判定がNOの場合には、CPU201は、その算出されている動作開始時間start[iH]をそのまま使用する。
以上のようにして今回の動作開始時間start[iH]が決定した後、CPU201は、mePtrの次の値による次回の処理のために、今回の演奏情報の発音開始時刻mePtr.Timeを前回発音開始時刻laston[iH]としてセットする(ステップS1809)。
その後、CPU201は、フレームカウント用変数iの値に対応する動作データframe[i]のトラック番号Hand(図18では「frame[i].Hand」と記載)に、現在のパート検索用変数iHの値(図18のステップS1802,図19のS1826参照)を格納する。また、CPU201は、動作データframe[i]の動作開始時間start(図18では「frame[i].start」と記載)に、上述のように算出した今回の動作開始時間start[iH]を格納する。さらに、CPU201は、動作データframe[i]の動作終了時間term(図18では「frame[i].term」と記載)に、今回の演奏情報の発音開始時刻mePtr.Timeを格納する(以上、ステップS1810)。
ステップS1810の後、CPU201は、図19のステップS1811からS1825までの一連の処理を実行する。ここでは、今回の動作データframe[i]のための5本の各指の演奏位置「position[0]〜position[4]」(指を置くべき鍵盤番号)、各指の状態「status[0]〜status[4]」(それぞれ、値「−1」が準備動作、値「1」が押鍵)、奥行き方向の位置「Zpos」などの情報の生成と設定が行われる(図4参照)。
CPU201は、ステップS1811で指番号指定変数ifigに初期値「0」(親指)を設定した後、ステップS1821でifigの値を+1ずつインクリメントしながら、ステップS1812で片手の指の最大数「5」に達したと判定するまで、以下のステップS1813からS1820の一連の処理を実行する。
まず、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の値が未定義値NULLでないか否かを判定する(ステップS1813)。
ステップS1813の判定がYESならば、現在処理中の指ifigについて、出力用の演奏情報prep[iH][ifig]が決定されているので、CPU201は、prep[iH][ifig]の音高Pitch(図3参照)(図19中では「prep[iH][ifig].Pitch」と記載)に、現在のパートiHの鍵盤横方向状態補正値xOffset[iH]を加算して得られる値を、今回の動作データframe[i]の指番号ifigに対応する演奏位置position[ifig](図19中では「frame[i].position[ifig]」と記載)に格納する(ステップS1814)。すなわち、現在処理中の指ifigに関しての指位置(position)のデータとして、prep[iH][ifig]で決定されている演奏情報の音高に対して、前述した右手パートと左手パートの衝突を考慮した鍵盤横方向の補正値(図17のステップS1708およびS1710の説明を参照)を考慮して補正した値を格納する。
次に、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]が示す演奏情報の発音開始時刻Time(図19中では「prep[iH][ifig].Time」と記載)が、今回の演奏情報の発音開始時刻mePtr.Timeと等しいか否か、すなわちprep[iH][ifig]とmePtrが指す演奏情報の各発音開始時刻Timeが等しいか否かを判定する(ステップS1815)。これは、指番号ifigの押鍵がmePtr.Timeの押鍵と同時であるか否かを判定することとなる。
ステップS1815の判定がYESならば、CPU201は、今回の動作データframe[i]の指番号ifigに対応する状態status[ifig](図19中では「frame[i].status[ifig]」と記載)に、押鍵を示す値「1」を格納する(ステップS1816)。
その後、CPU201は、ステップS1821の処理に移行し、次の指番号の処理に進む。
ステップS1815で、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の発音開始時刻Timeが、今回の演奏情報mePtrの発音開始時刻Timeと等しくなく、ステップS1815の判定がNOならば、CPU201は、prep[iH][ifig]>mePtr.Timeであるか否かを判定する(ステップS1817)。
ステップS1817の判定がYESならば、現在のパートiHの現在の指番号ifigに対応するprep[iH][ifig]が示す演奏情報は、準備動作を行うべきものである。このため、CPU201は、今回の動作データの指番号ifigに対応する状態frame[i].status[ifig]に、準備動作を示す値「−1」を格納する(ステップS1818)。
その後、CPU201は、ステップS1821の処理に移行し、次の指番号の処理に進む。
ステップS1817の判定がNOならば、現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]には演奏情報へのポインタが格納されていないことを意味する。この場合には、CPU201は、今回の動作データの指番号ifigに対応する状態frame[i].status[ifig]に、データ無しを示す値「0」を格納する(ステップS1819)。
その後、CPU201は、ステップS1821の処理に移行し、次の指番号の処理に進む。
ステップS1813に戻って、現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の値が未定義値NULLであって、ステップS1813の判定がNOならば、CPU201は、今回の動作データの指番号ifigに対応する演奏位置frame[i].position[ifig]に、データ無しを示す値「−1」を格納し、また、状態frame[i].status[ifig]に、データ無しを示す値「0」を格納する(ステップS1820)。
その後、CPU201は、ステップS1821の処理に移行し、次の指番号の処理に進む。
以上のステップS1813からS1820までの一連の処理が、5本の全ての指番号ifigについて実行されると、ステップS1812の判定がNOとなる。
この結果、CPU201は、奥行き位置計算の処理を実行し、その結果得られる奥行き方向の位置を、変数zposに得る(ステップS1822)。この奥行き位置計算の処理の詳細については、図20を用いて後述する。
CPU201は、変数zposに得た奥行き方向の位置に、現在のパートiHの鍵盤奥行き方向状態補正値zOffset[iH]を加算して得られる値を、現在の動作データにframe[i].Zpos(図4参照)として格納する(ステップS1823)。ここでは、前述した右手パートと左手パートの衝突を考慮しないで算出された奥行き方向の位置zposが、衝突を考慮した鍵盤奥行き方向の補正値(図17のステップS1706の説明を参照)で補正され、その補正結果がframe[i].Zposに格納される。
CPU201は、動作データframe[i]のフレームの総数FrameCountを+1インクリメントする(ステップS1824)。
最後に、CPU201は、次回開始時刻の計算の処理を実行し、次の検索ポインタ変数mePtrの値のための動作開始時間start[iH]を算出する(ステップS1825)。この次回開始時刻の算出処理の詳細については、図21を用いて後述する。
その後、CPU201は、ステップS1826でパート検索用変数iHの値を+1ずつインクリメントしながら、図18のステップS1802で変数iHの値が2に達したと判定するまで、変数iHが示す右手および左手の各パート毎に、以下の図18のステップS1803から図19のS1825の一連の処理を実行し、図18のステップS1802で変数iHの値が2に達したと判定されると(ステップS1802:NO)、図18および図19のフローチャートで示される図6のステップS607の動作データ出力の処理を終了する。
図20は、図19のステップS1822の奥行き位置計算の処理の例を示すフローチャートである。この処理では、現在の各指の押鍵や準備動作の状態から、手を鍵盤の奥行き方向に対して、どの位置に置くのが相応しいかを判定する。ここでは、鍵盤奥行き方向の手の位置として、zpos=1〜4の4段階で手の位置を定義し、このいずれの奥行き位置が相応しいかを判断している。
まず、CPU201は、奥行き位置変数zposに暫定的に値「1」を格納する(ステップS2001)。この値は、鍵盤上の手前側に手を置き、全部の指が白鍵を押鍵する位置にあることを指示する。
次に、CPU201は、親指に対応する出力バッファ用演奏情報ポインタ変数prep[iH][0]の値が未定義値NULLでないか否かを判定する(ステップS2002)。
ステップS2002の判定がYESならば、親指に対応する演奏情報が存在することになるので、CPU201は、prep[iH][0]が示す演奏情報の音高データprep[iH][0].Pitchを、ピッチ変数pに格納する(ステップS2003)。
さらに、CPU201は、ピッチ変数pの値に対応する黒鍵判定定数BlackKey[p]の値が「1」であるか否か、すなわち親指に対応する演奏情報が示す音高Pitchが黒鍵であるか否かを判定する(ステップS2004)。いま、黒鍵判定定数BlackKey[]={0,1,0,1,0,0,1,0,1,0,1,0}である。値「0」は白鍵を示し、値「1」は黒鍵を示す。この配列の並びは、実際の鍵盤楽器における白鍵と黒鍵の一般的な並びに対応している。この配列値を、ピッチ変数pをキー値として調べることにより、演奏情報が示す音高Pitchが黒鍵であるか否かを判定することができる。実際には、音高データprep[iH][0].Pitchの値を、12で除した余りの値を用いる等して、オクターブ内での音高を算出して判定を行う。
ステップS2004の判定がYESならば、親指に対応する演奏情報が黒鍵であることになるので、CPU201は、奥行き位置変数zposに値「4」を格納する(ステップS2005)。この値は、片手の5本の指全てを鍵盤上の黒鍵が押せる程度奥側に寄せて置くことを指示する。すなわち、親指が黒鍵側(奥側)に置かれるということは、5本の全ての指が自然に黒鍵が押せる程度の奥側に置かれることを意味する。
ステップS2005の処理の後、CPU201は、図20のフローチャートで示される図19のステップS1822の奥行き位置計算の処理を終了する。
一方、ステップS2002に戻って、親指に対応する出力バッファ用演奏情報ポインタ変数prep[iH][0]の値が未定義値NULLになっておりステップS2002の判定がNOならば、CPU201は、小指に対応する出力バッファ用演奏情報ポインタ変数prep[iH][4]の値が未定義値NULLでないか否かを判定する(ステップS2006)。
ステップS2006の判定がYESならば、小指に対応する演奏情報が存在することになるので、CPU201は、prep[iH][4]が示す演奏情報の音高データprep[iH][4].Pitchを、ピッチ変数pに格納する(ステップS2007)。
さらに、CPU201は、ピッチ変数pの値に対応する黒鍵判定定数BlackKey[p]の値が「1」であるか否か、すなわち小指に対応する演奏情報が示す音高Pitchが黒鍵であるか否かを判定する(ステップS2008)。
ステップS2008の判定がYESならば、小指に対応する演奏情報が黒鍵であることになるので、CPU201は、奥行き位置変数zposに値「3」を格納する(ステップS2009)。この値は、人差し指、中指、薬指、小指の4本の指を鍵盤上の黒鍵が押せる程度奥側に寄せて置くことを指示する。すなわち、小指が黒鍵側(奥側)に置かれるということは、上記4本の指が自然に黒鍵が押せる程度の奥側に置かれることを意味する。
ステップS2009の処理の後、CPU201は、図20のフローチャートで示される図19のステップS1822の奥行き位置計算の処理を終了する。
親指に加えて、小指に対応する出力バッファ用演奏情報ポインタ変数prep[iH][4]の値が未定義値NULLになっておりステップS2006の判定がNOならば、CPU201は、ステップS2010で変数iに値「1」を設定した後、ステップS2016で変数iの値を+1ずつインクリメントしながら、ステップS2011で変数iの値が4に達したと判定するまで、以下のステップS2012からS2015までの一連の処理を実行する。
まずCPU201は、変数iの値が示す指(「1」なら人差し指、「2」なら中指、「3」なら薬指)に対応する出力バッファ用演奏情報ポインタ変数prep[iH][i]の値が未定義値NULLでないか否かを判定する(ステップS2012)。
ステップS2012の判定がYESならば、CPU201は、prep[iH][i]が示す演奏情報の音高データprep[iH][i].Pitchを、ピッチ変数pに格納する(ステップS2013)。
さらに、CPU201は、ピッチ変数pの値に対応する黒鍵判定定数BlackKey[p]の値が「1」であるか否か、すなわち変数iの値に対応する指の演奏情報が示す音高Pitchが黒鍵であるか否かを判定する(ステップS2014)。
ステップS2014の判定がYESならば、CPU201は、奥行き位置変数zposに値「2」を格納する(ステップS2015)。この値は、人差し指、中指、薬指の3本の指を鍵盤上の黒鍵が押せる程度奥側に寄せて置くことを指示する。すなわち、上記3本の何れかの指が黒鍵側(奥側)に置かれるということは、上記3本の指が自然に黒鍵が押せる程度の奥側に置かれることを意味する。
ステップS2015の処理の後、CPU201は、図20のフローチャートで示される図19のステップS1822の奥行き位置計算の処理を終了する。
変数iの値が4になりステップS2011の判定がNOになった場合も、CPU201は、図20のフローチャートで示される図19のステップS1822の奥行き位置計算の処理を終了するが、この場合は、いずれの指も黒鍵ではない場合に相当するので、奥行き位置変数zposの値は、ステップS2001で初期設定された値「1」となっている。
以上の奥行き位置計算の処理では、各指が押鍵をするのか準備動作をするのかにかかわらず、手を置く位置が計算される。
図21は、図19のステップS1825の次回開始時刻の計算の処理の例を示すフローチャートである。
CPU201は、以下のステップS2101からS2112の一連の処理によって、演奏情報検索用変数iHの次の値に対応する次回の図18および図19の動作データ出力の処理のために、次回の動作開始時間start[iH]を算出する。ここでは、現在発音されている演奏情報のうち、最も早く離鍵される音の演奏情報を基に、次回の動作開始時間start[iH]が設定される。
まず、CPU201は、今回の演奏情報の発音開始時刻mePtr.Timeを暫定的に次回の動作開始時間start[iH]に設定する(ステップS2101)。
次に、今回の演奏情報の発音開始時刻mePtr.Timeに今回の演奏情報の発音継続時間mePtr.Gate(図3参照)を加算した値が、その演奏情報のノートオフ時刻NoteOff(同名の変数に格納される)として設定される(ステップS2102)。
次に、CPU201は、ステップS2103で指番号指定変数ifigに初期値「0」(親指)を設定した後、ステップS2110でifigの値を+1ずつインクリメントしながら、ステップS2104で片手の指の最大数「5」に達したと判定するまで、以下のステップS2105からS2109までの一連の処理を実行する。
まず、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]の値が未定義値NULLでないか否かを判定する(ステップS2105)。
ステップS2105の判定がYESならば、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数が示す演奏情報の、発音開始時刻prep[iH][ifig].Timeが、今回の演奏情報の発音開始時刻mePtr.Time以下か否か、すなわち指番号ifigの押鍵がmePtr.Timeの押鍵と同時若しくは、prep[iH][ifig]に入っている音が、今回の演奏情報mePtrよりも前に押鍵されて、まだ押鍵持続中である音のいずれかであるか否かを判定する(ステップS2106)。
ステップS2106の判定がYESならば、CPU201は、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数が示す演奏情報の発音開始時刻prep[iH][ifig].Timeに、同じ演奏情報の発音継続時間prep[iH][ifig].Gateに比率RATIO(例えば80%=0.8)を乗算して得た値を加算し、その加算結果を、現在調査中の演奏情報prep[iH][ifig]の動作終了時間として、termに設定する(ステップS2107)。
その後、CPU201は、次回の動作開始時間start[iH]が、現在調査中の演奏情報prep[iH][ifig]の動作終了時間termよりも小さく、かつ、現在調査中の演奏情報prep[iH][ifig]の動作終了時間termがノートオフ時刻NoteOffよりも小さいか否かを判定する(ステップS2108)。
ステップS2108の判定がYESならば、ステップS2107で算出した動作終了時間termが、現在発音されている演奏情報の中で、ここまでに調べた音のうち暫定的に最も早く離鍵するものである。この場合、CPU201は、その動作終了時間termを新たなノートオフ時刻NoteOffとして設定する(ステップS2109)。
ステップS2108の判定がNOならば、CPU201は、現在のノートオフ時刻NoteOffを維持する。
ステップS2109の処理の後、またはステップS2108の処理の判定がNOである場合、または、現在のパートiHの現在の指番号ifigに対応する出力バッファ用演奏情報ポインタ変数prep[iH][ifig]が示す演奏情報が、同時若しくはそれ以前に押鍵されるものではなくステップS2106の判定がNOの場合、あるいはprep[iH][ifig]が未定義値NULLでステップS2105の判定がNOならば、CPU201は、ステップS2110の処理に移行し、ifigの値を+1インクリメントして、次の指番号の処理に進む。
全ての指番号ifigに対する処理が終了しステップS2104の判定がNOになると、CPU201は、次回の動作開始時間startがノートオフ時刻NoteOffよりも前(小さい)か否かを判定する(ステップS2111)。
ステップS2111の判定がYESならば、CPU201は、ノートオフ時刻NoteOffを次回の動作開始時間start[iH]に設定し、NOならば、現在の動作開始時間start[iH]の値を維持して、図21のフローチャートで示される図19のステップS1825の次回開始時刻の計算の処理を終了する。
以上説明した図5から図21のフローチャートにより、RAM203上に生成される、図4で説明した動作データframe[0]〜frame[FrameCount−1]は、動作タイミング毎に、どの指を押鍵するかという情報のみならず、どの指を次の押鍵のために準備するかという情報も、各指の状態status[0]〜status[4]として保有することが特徴である。このような動作データを用いることにより、CPU201は、表示部205のディスプレイ上で、次のような演奏動作ガイドを実現することができる。
例えば、親指の状態を示すstatus[0]に押鍵を示す値「1」がセットされ、親指以外の指の状態を示すstatus[1]〜status[4]のうちのいずれかに準備動作を示す値「−1」がセットされている場合、CPU201は、親指の位置position[0]で表される鍵を親指で押鍵するとともに、親指以外の指の状態を示すstatus[1]〜status[4]のうち準備動作を示す値「−1」がセットされている指について、その指に対応するposition[1]〜position[4]のいずれかで表される鍵の位置で、その指を準備(配置)させるように動作する。この場合において、親指の位置position[0]と、準備すべき他の指の位置position[1]〜position[4]の鍵の位置との関係によっては、通常の指の左右の位置関係と逆転した位置関係になっている場合がある。このような場合、CPU201は、「親指以外の指を親指の上を越えて次の押鍵位置まで移動させておきなさい」という準備動作をガイド表示させることが可能である。
また例えば、親指以外の指の状態を示すstatus[1]〜status[4]のうちのいずれかに押鍵を示す値「1」がセットされ、親指の状態を示すstatus[0]に準備動作を示す値「−1」がセットされている場合も同様に、押鍵を示す指の鍵の位置と、親指が準備動作を行うべき鍵の位置との位置関係によっては、CPU201は、「親指を親指以外の指の下をくぐらせて次の押鍵位置まで移動させておきなさい」という準備動作をガイド表示させることが可能である。
これらの演奏ガイド表示は、演奏動作上のテクニックに関する動作情報であるということができる。このようにして、本実施形態の制御処理によって、演奏情報に付加されている運指情報(図3の「指番号」)から演奏動作上のテクニックに関する動作情報を自動的に抽出することが可能となり、それにより運指とともに演奏動作上のテクニックも演奏ガイドすることが可能となる。
図22は、演奏情報の記憶例を示す図、図23は、図22の演奏情報に対応して、準備動作を考慮しないときの動作データの出力例を示す図、図24は、図22の演奏情報に対応して、図5から図21のフローチャートで示される制御処理により、準備動作を考慮したときの動作データの出力例を示す図、図25は、演奏ガイドの表示例を示す図である。ただし、この例の場合は、片手のみのデータであるので、上記の実施例中で、右手と左手の衝突に関する調整(例えば図17のパート同士の状態比較の処理)は必要としていない場合の例である。図23および図24において、濃いグレー色のデータ部分は押鍵動作が指定されている部分である。図24において、薄いグレー色のデータ部分は押鍵の準備動作が指定されている部分である。
図22の演奏情報は、図3で説明したデータ構成例に従って、1行に1組の演奏情報、すなわち1行につき1音のデータが並んでいる。
この演奏データに対して、準備動作を考慮しない場合には、図23に例示されるように、各指の演奏位置position[0]〜position[4]毎に、音高が設定されると共に(濃い灰色部分)(値「−1」(色無しの部分)は音高設定無しを示す)、該当する状態status[0]〜status[4]に、押鍵を行う場合は値「1」(濃い灰色部分)が、行わない場合は値「0」(色無しの部分)が設定されるだけである。従って、このような動作データに基づいて、演奏ガイドの表示が行われる場合には、図23の例えば*の行位置では、音高67の鍵がposition[0]の親指で押鍵された後に、*の次の行位置で、音高「67」の鍵の左隣りの音高「66」の鍵がposition[1]の人差し指で押鍵される。これは、親指の押鍵に対して人差し指によって指越えを行って次の押鍵を行う演奏テクニックを必要とする例である。しかし、図22に例示される準備動作を考慮しない動作データでは、現在の押鍵に対して次にどのような押鍵がなされるかは知ることができないため、単純な演奏ガイド表示しか行うことができない。
これに対して、図22に例示される演奏データに対して、本実施形態の制御処理により準備動作を考慮した場合には、図24に例示されるように、各指の演奏位置position[0]〜position[4]毎に、押鍵を行う指の音高(濃い灰色部分)と準備動作を行う指の音高(薄い灰色部分)が設定されると共に(値「−1」(色無しの部分)は音高設定無しを示す)、該当する状態status[0]〜status[4]に、押鍵を行う場合は値「1」(濃い灰色部分)が、準備動作を行う場合は値「−1」(薄い灰色部分)が、どちらも行わない場合は値「0」(色無しの部分)を設定することが可能となる。従って、このような動作データに基づいて、演奏ガイドの表示が行われる場合には、図24の例えば*の位置に示されるように、音高「67」の鍵がposition[0]の親指で押鍵されるときに(濃い灰色部分)、音高「67」の鍵の左隣りの音高「66」の鍵をposition[1]の人差し指で押鍵する準備動作に入るべきことを、status[1]に設定される値「−1」と、position[1]に設定される音高「66」とで指定することができる(薄い灰色部分)。そして、親指が関係していることが認識されることによって、演奏ガイドの表示においては、現在の親指の押鍵に対して人差し指が指越えを行って次の押鍵を行う準備に入ることを表示させることが可能となる。これにより、ユーザは、押鍵時の演奏テクニックを習得することが可能となる。この場合、演奏情報としては、図22に例示されるように、演奏テクニックのための特別な情報を持たせる必要はなく、指番号Fingerの情報から、準備動作の情報を自動的に生成することが可能となる。
図25は、演奏ガイドの表示例を示す図であり、右手の演奏ガイド表示を示している。鍵盤上の5個の丸い印は、右手の各指のポジションを示しており、左端の少し大きい丸印は親指を示し、右に向かって人差し指、中指、薬指、小指にそれぞれ対応する小さい丸印が示されている。左手の場合は、方向が逆になる。また、押鍵状態のときは、鍵盤が濃い色になる。
図25(a)の例では、親指が押鍵状態で、その他の指は準備状態であることが示されている。このとき、図18のフローチャートで示した奥行き位置計算処理によって、図25(a)の演奏ガイド例では、zposに値「1」が格納されることにより、全ての指を白鍵上に置く指示が表示される。
図25(b)の例も、親指が押鍵状態で、その他の指は準備状態であることが示されているが、図20のフローチャートで示した奥行き位置計算処理によって、図25(b)の演奏ガイド例では、zposに値「2」が格納されることにより、人差し指、中指、薬指の3本を黒鍵上に置き、親指と小指を白鍵上に置く指示が表示される。そして、人差し指は親指よりも半音低い黒鍵上に置いて準備する指示が表示されるため、演奏者は、自然に親指越えをして人差し指をF#の黒鍵上に置いて準備する状態をとることができる。
なお、指越えや指くぐりが発生したときに、それらを明示的に示すような表示がなされてもよい。例えば、画面上に矢印や特殊なマークを表示するようにしても良い。あるいは、対象となる指(例えば、親指や人差し指)を点滅させたり、別の色で表示する等しても良い。
図26は、左手の押鍵ガイドがその演奏進行に伴って右手の押鍵の準備ガイドに衝突しうる楽譜例を示す図である。図26において、ト音記号が付与された上段のパートは右手パートを示し、ヘ音記号が付与された下段のパートは左手パートを示している。各音符の上に付与されている1から5の範囲の数字は、押鍵時の指番号を示しており、1は親指、2は人差し指、3は中指、4は薬指、5は小指で押鍵がされる音符であることを示している。図27は、図26の楽譜例に対応し、衝突回避制御を行わないときの衝突が発生する場合の右手パートに関する動作データの出力例(その1)を示す図である。図28は、図26の楽譜例に対応し、衝突回避制御を行うときの衝突が発生する場合の右手パートに関する動作データの出力例(その1)を示す図である。図27および図28において、図23および図24の場合と同様に、濃い灰色のデータ部分は押鍵動作が指定される部分、薄い灰色のデータ部分は押鍵の準備動作が指定される部分である。また、図27および図28において、左端の「No」列は各行の動作データのフレーム番号(図4のframe[0]、frame[1]、・・・、frame[FrameCount−1]に対応)を示している。以下の説明では、例えばフレーム番号として0が付与されている行の動作データを、「第0フレームの動作データ」と記載する。
図26において、第1小節から第4小節までは、右手パートのみで演奏が行われ、それに伴い、第0フレームから第28フレームまでの動作データが、それぞれの押鍵タイミングに先行するタイミングで出力され、その動作データに基づいて演奏ガイドの表示が行われてゆく。このとき、左手パートは、第1小節から第5小節までは休符となっているため、その動作データは、特には図示しないが、押鍵の準備動作を示し、それに基づく演奏ガイド表示がなされる。
図26において、第5小節から第10小節までは、右手パートは休符状態に入る。この区間に対応して、もし衝突回避制御を行わないとしたときの右手パートの動作データは、図27の第29フレームの動作データとして示されるように、第11小節の先頭の2つの音符に対応するPositionの値が「0」(親指)で音高が「60」の「ド」音およびPositionが「1」(人差し指)で音高が「62」の「レ」音の押鍵の準備動作を指示する動作データが出力される。この第29フレームの動作データは、start項目の時間値「7.54」とterm項目の時間値「17.508」として示されるように、第5小節から第10小節までずっと同じ演奏ガイド状態を維持する。。
一方、左手パートについては、図26において、第5小節から第9小節までは、押鍵動作が行われる。そして、第7小節の先頭音(音高が「62」の「レ」音)の発音に先行してその押鍵が指示されるタイミングで、左手パートの親指に最も近い指である親指自身に対して設定される動作データが、図26上の第7小節の4番目の音符(音高が「67」の「ソ」音)の押鍵の準備動作を指示する。この結果、この左手パートの親指の演奏情報の音高が、右手パートの親指に最も近い指である親指自身に対して設定される演奏情報の音高「60」(「ド」音)よりも高くなる。この結果、右手パートに関して、図26の第7小節以降も、図27に示されるように、もし衝突回避制御が行われずに第29フレームの動作データにより演奏ガイド表示が継続された場合には、左手パートの押鍵または押鍵の準備動作の演奏ガイドにおける指の指定位置が、右手パートの演奏ガイドにおける指の指定位置に衝突してしまい、演奏ガイドがうまく表示できず、このため演奏者は演奏をうまく行えなくなる。
そこで、本実施形態では、上述の状態では、図6のステップS606のパート同士の状態比較の処理における図17のステップS1704の判定がYESとなる。さらに、第7小節の先頭音に対する演奏ガイドの開始時点で、右手パートで押鍵の準備動作の指示がされている演奏情報のうち発音開始時刻が最も早いものは第11小節の先頭の音符のものであり、左手パートで押鍵または押鍵の準備動作の指示がされている指のうち発音開始時刻が最も早いものは第7小節の先頭の音符のものである。このため、図6のステップS605のパート毎の状態確認の処理における図9のフローチャートの処理において、iH=0(右手パート)のときにはステップS903の判定はNOとなって(図6のステップS603参照)、ステップS905で押鍵動作フラグ変数pushKey[0]に値「0」がセットされ、iH=1(左手パート)のときにはステップS903の判定はYESとなって、ステップS905でpushKey[1]に値「1」がセットされる。この結果、図17のステップS1705の判定がNO、ステップS1707の判定がNO、ステップS1709の判定がYESとなって、ステップS1710で、右手パート用の鍵盤横方向状態補正値xOffset[0]に、ステップS1704で判定された音高の差に応じた量だけ右側方向への移動を指示するための補正値がセットされる。これにより、図6のステップS607の動作データ出力の処理における図18と図19のフローチャートにおいて、iH=0(右手パート)のときに、ステップS1814で、押鍵または押鍵の準備動作を指示する動作データframe[i]の各指ifigの演奏位置(鍵盤番号)position[ifig]が、右手パート用の鍵盤横方向状態補正値xOffset[0]の分だけ鍵盤右横方向に移動させられる。
この結果、本実施形態では、衝突回避制御が行われる図28の動作データ例に基づいて動作が実行される。図27の衝突回避制御が行われないとした場合の動作データ例と図28の衝突回避制御が行われる動作データ例では、衝突の発生が検知されない第0フレームから第28フレームまでは、同じ動作データ群が出力される。そして、第29フレームの出力が開始された後、図26の第7小節の先頭音(音高が「62」の「レ」音)の発音に先行してその押鍵が指示されるタイミングで、上述のように衝突が検知されて、右手パートの鍵盤横方向状態が補正された第30フレームの動作データが出力される。すなわち、図28に示されるように、第29フレームの動作データでは、第11小節の先頭の2つの音符(音高が「60」の「ド」音および音高が「62」の「レ」音)に対応するPositionの値が「0」(親指)と「1」(人差し指)での押鍵の準備動作を指示する動作データが出力される。続いて、衝突が検知された第30フレームの動作データでは、上記2つの音符を順次右に2半音ずつずらした音高が「62」の「レ」音、音高が「64」の「ミ」音、さらにもう1音加えて音高が「66」の「ファ#」音(右手パートの第11小節の第3音目に対応)に対応するPositionの値が「0」(親指)と「1」(人差し指)と「2」(中指)での押鍵の準備動作を指示する動作データが出力される。
以下、図26の第7小節において、左手パートが鍵盤右横方向に順次押鍵されてゆくに従って、上述の衝突に対する制御によって、左手パートの指が右手パートの指に重なる分だけ、右手パートの押鍵の準備動作を指示する各指の音高が鍵盤右横方向に移動させられる動作が順次実行されてゆく。この結果、左手パートの鍵盤右横方向への押鍵移動に従って、右手パートの押鍵の準備動作の演奏ガイドも鍵盤右横方向へ移動してゆく。その後、図26の第7小節から第8小節にかけて、左手パートが鍵盤左横方向に順次押鍵されてゆくに従って、上述の衝突に対する制御によって、左手パートの指が右手パートの指に重なる分だけ、右手パートの押鍵の準備動作を指示する各指の音高が鍵盤右横方向に移動させられる動作が順次実行されてゆく。この結果、左手パートの鍵盤左横方向への押鍵移動に従って、右手パートの押鍵の準備動作の演奏ガイドも鍵盤左横方向へ移動してゆく。以上の衝突回避制御の動作が、図26および図28の破線枠で囲まれた範囲で実行されることになる。
最後に、左手パートと右手パートの衝突が検知されなくなる図28の第47フレームの動作データの出力タイミングで、衝突の回避制御をしないとした場合の図27の第30フレームの動作データと同じ動作データが出力される状態に戻る。そして、このように構成された図28の動作データに基づいて、図25に示したような演奏ガイドの表示を行うことができる。具体的には、図24の動作データから図25の演奏ガイド表示を生成したのと同様の手順で、図28の動作データに基づく演奏ガイドの表示を行うことができる。これにより、ユーザは、押鍵時の演奏テクニックを習得することが可能となる。
図29は、同じ押鍵タイミングでの右手および左手の接近により両者の演奏ガイドが衝突しうる楽譜例を示す図である。図29において、図26の場合と同様に、ト音記号が付与された上段のパートは右手パートを示し、ヘ音記号が付与された下段のパートは左手パートを示している。図26の場合と同様に、各音符の上に付与されている1から5の範囲の数字は、押鍵時の指番号を示している。図30は、図29の楽譜例に対応し、衝突回避制御を行わないときの衝突が発生する場合の動作データの出力例(その2)を示す図であり、図30(a)が右手パート、図30(b)が左手パートである。図31は、図29の楽譜例に対応し、衝突回避制御を行うときの衝突が発生する場合の動作データの出力例(その2)を示す図であり、図31(a)が右手パート、図31(b)が左手パートである。図30および図31において、図23および図24の場合と同様に、濃い灰色のデータ部分は押鍵動作が指定される部分、薄い灰色のデータ部分は押鍵の準備動作が指定される部分である。また、図30および図31において、図27および図28の場合と同様に、左端の「No」列は各行の動作データのフレーム番号を示している。
図29において、第2小節から第3小節にかけての破線枠で囲まれた部分の3つの押鍵タイイングに先行する動作データの出力タイミングにおいて、右手パートでは、音高「62」の「レ」音と音高「68」の「ソ#」音と音高「71」の「シ」音の押鍵が指示される。一方、左手パートでは、音高「52」の「ミ」音と音高「64」の「ミ」音の押鍵が指示される。この結果、右手パートの音高「62」の「レ」音と左手パートの音高「64」の「ミ」音で、左手パートの音高のほうが高くなって、右手パートと左手パートで衝突が発生する。
この場合、もし衝突開始の制御が行われない場合は、例えば図30の動作データ群が出力される。すなわち、右手パートについては、図29の破線枠の部分に対応する図30(a)の第3フレームから第7フレームの動作データ群が出力され、左手パートについては、図29の破線枠の部分に対応する図30(b)の第1フレームから第5フレームの動作データ群が出力される。このとき、図6のステップS607の動作データ出力の処理における図19のステップS1822の奥行き計算の処理(図20のフローチャートの処理)により、右手パートの第3フレームから第7フレームの動作データ群の奥行き方向の位置Zposとして、値「2」が設定される(図30(a)の太実線枠部分)。Zpos=2の場合、人差し指、中指、薬指の3本の指を鍵盤上の奥側の黒鍵上に置くことが指示される。この結果、図30(a)において、右手の親指(Position=0)は音高「62」の「レ」音の白鍵を押鍵し、右手の人差し指(Position=1)は音高「68」の「ソ#」音の黒鍵を押鍵し、右手の薬指(Position=3)は音高「71」の「シ」音の白鍵をそれぞれ押鍵することが指示される。同じく、ステップS1822の奥行き計算の処理により、左手パートの第1フレームから第5フレームの動作データ群の奥行き方向の位置Zposとして、値「1」が設定される(図30(b)の太実線枠部分)。Zpos=1の場合、5本の指全てを鍵盤上の手前側の白鍵上に置くことが指示される。この結果、図30(b)において、左手の小指(Position=4)は音高「52」の「ミ」音の白鍵を押鍵し、左手の親指(Position=0)は音高「64」の「ミ」音の白鍵を押鍵することが指示される。
この結果、衝突回避制御を行わないとした場合の図30の動作データの例では、図29の破線枠に対応する右手パートに対応する図30(a)の第3フレームから第7フレームの動作データと左手パートに対応する図30(b)の第1フレームから第5フレームの動作データの出力タイミングにおいて、右手パートの親指に対する音高「62」の「レ」音の白鍵の押鍵指示と、左手パートの親指に対する音高「64」の「ミ」音の白鍵の押鍵指示とが、親指同士がクロスして衝突が発生してしまう。従って、演奏ガイドがうまく表示できず、このため演奏者は、うまく演奏を行うことができなくなってしまう。
そこで、本実施形態では、以下に示す衝突回避制御によって、例えば図31(a)(右手パート)および図31(b)(左手パート)の動作データが生成され、その動作データに基づいて演奏ガイドが実行される。すなわち、上述の状態では、図6のステップS606のパート同士の状態比較の処理における図17のステップS1704の判定がYESとなる。さらに、図29の破線枠の演奏ガイドの開始時点で、右手パートと左手パートでは同時に押鍵が発生するため、図6のステップS605のパート毎の状態確認の処理における図9のフローチャートの処理において、iH=0(右手パート)およびiH=1(左手パート)ともにステップS903の判定はYESとなって(図6のステップS603参照)、ステップS904で押鍵動作フラグ変数pushKey[0]およびpushKey[1]ともに値「1」がセットされる。この結果、図17のステップS1705の判定がYESとなって、ステップS1706で、鍵盤奥方向(黒鍵側)にある右手パートに対応する鍵盤奥行き方向状態補正値zOffset[0]に、例えば正の値「2」がセットされ、手前方向(白鍵側)にある左手パートに対応する鍵盤奥行き方向状態補正値zOffset[1]には、現在の奥行き方向の位置が最低値「1」であるから、補正無しを示す値「0」がセットされる。この結果、図6のステップS607の動作データ出力の処理における図18と図19のフローチャートにおけるステップS1823の処理により、iH=0(右手パート)のときに、奥行き方向の位置zpos=2(図30(a)の太実線枠)に鍵盤奥行き方向状態補正値zOffset[0]=2が加算され、iH=0(左手パート)のときに、奥行き方向の位置zpos=1(図30(b)の太実線枠)に鍵盤奥行き方向状態補正値zOffset[1]=0が加算される。
以上の制御処理により、右手パートについては、図29の破線枠の部分に対応する図31(a)の第3フレームから第7フレームの動作データ群において、太実線枠として示されるように、奥行き方向の位置Zposとして、値「4」が設定される。また、左手パートについては、図29の破線枠の部分に対応する図31(b)の第1フレームから第5フレームの動作データ群において、太実線枠として示されるように、奥行き方向の位置Zposとして、値「1」が設定される。Zpos=4の場合、5本の指全てを鍵盤上の奥側の黒鍵上に置くことが指示される。この結果、右手パート全体が鍵盤奥の黒鍵側に移動させられ、左手パート全体は鍵盤手前の白鍵側に置かれるため、両手間の衝突が回避されることになる。すなわち、衝突回避制御が行われた場合の図31の動作データの例では、図29の破線枠に対応する右手パートに対応する図31(a)の第3フレームから第7フレームの動作データと左手パートに対応する図31(b)の第1フレームから第5フレームの動作データの出力タイミングにおいて、右手パートの親指に対する音高「62」の「レ」音の白鍵の押鍵指示と、左手パートの親指に対する音高「64」の「ミ」音の白鍵の押鍵指示において、親指同士のクロスによる衝突を回避でき、演奏者は、うまく演奏を行うことが可能となる。そして、このように構成された図31の動作データに基づいて、図25に示したような演奏ガイドの表示を行うことができる。具体的には、図24の動作データから図25の演奏ガイド表示を生成したのと同様の手順で、図31の動作データに基づく演奏ガイドの表示を行うことができる。これにより、ユーザは、押鍵時の演奏テクニックを習得することが可能となる。
以上説明したように、本実施形態によれば、演奏情報と運指情報のみから、押鍵のための情報にとどまらない、演奏動作を遂行する上でのテクニックに相当する情報を生成することが可能となるため、それにより運指とともに演奏動作上のテクニックも演奏ガイドすることが可能となる。また、準備に必要な箇所についてのユーザへの注意を喚起する情報を自動で生成できるなどの、楽器演奏の練習についての有用な情報の提供が可能になる。さらに、演奏情報に、熟達者による付加情報をつける必要がなくなるというメリットも生まれる。
さらに本実施形態では、左手と右手のパートで練習を行うための演奏ガイドを実行するときに、楽譜上、左手パートと右手パートの間で、演奏される指同士が衝突しそうになったり、あるいは次に演奏する準備を行うべき指を置く場所と演奏中の指が衝突しそうになった場合に、それらの状態を検知して補正することが可能となる。
以上の各実施形態に関して、更に以下の付記を開示する。
(付記1)
楽曲を構成する楽音夫々の発音タイミング情報と、音高情報と、演奏に用いる手及び指を示す情報と、を含む演奏情報を記憶する記憶部から読み出す読み出し手段と、
当該読み出された演奏情報それぞれに基づいて、前記右手及び左手の指夫々が複数の演奏操作子のいずれの位置にあるかを示す指位置を推定する位置推定手段と、
前記位置推定手段により推定された前記右手及び左手の指位置同士の関係が予め定められた条件を満たすか否か判別する判別手段と、
前記判別手段にて条件を満たすと判別された場合に、前記位置推定手段にて推定された前記右手及び左手の位置のうち、少なくとも一方の手の指位置を補正する位置補正手段と、
前記読み出された演奏情報及び前記各手の指位置に基づいて、演奏操作ガイド情報を生成するガイド情報生成手段と、
を備えることを特徴とする演奏操作ガイド装置。
(付記2)
前記判定手段は、前記指位置推定手段により推定された右手の各指位置と左手の各指位置のうち、前記左手の親指位置が、前記右手の親指位置より右側にあるか否かを判別する、
ことを特徴とする付記1に記載の演奏操作ガイド装置。
(付記3)
前記指位置補正手段は、
前記読み出された演奏情報に含まれる発音タイミング情報に基づき、前記演奏装置を演奏している指が前記右手及び左手のいずれに存在しているかを判別する演奏指判別手段をさらに有する、
ことを特徴とする付記1または2のいずれかに記載の演奏操作ガイド装置。
(付記4)
前記指位置補正手段は、
前記演奏指判別手段により、前記右手に前記演奏装置を演奏している指が存在していると判別された場合は、前記左手の指位置を、当該左手方向に補正する一方、前記左手に前記演奏装置を演奏している指が存在していると判別された場合は、前記右手の指位置を、当該右手方向に補正する、
ことを特徴とする付記3に記載の演奏操作ガイド装置。
(付記5)
前記指位置補正手段は、
前記演奏指判別手段により、前記右手及び左手の両方に前記演奏装置を演奏している指が存在していると判別された場合は、前記右手及び左手の少なくとも一方の指位置を、当該右手方向及び左手方向以外の方向に補正する、
ことを特徴とする付記3または4のいずれかに記載の演奏操作ガイド装置。
(付記6)
付記1から5のいずれかに記載の演奏操作ガイド装置と、
演奏者に演奏操作を行わせる演奏操作子と、
前記演奏操作子における演奏操作に応じて楽音を生成して出力する楽音出力部とを備える電子楽器。
(付記7)
演奏操作ガイド装置が、
楽曲を構成する楽音夫々の発音タイミング情報と、音高情報と、演奏に用いる手及び指を示す情報と、を含む演奏情報を記憶する記憶部から読み出し、
当該読み出された演奏情報それぞれに基づいて、前記右手及び左手の指夫々が複数の演奏操作子のいずれの位置にあるかを示す指位置を推定し、
前記推定された前記右手及び左手の指位置同士の関係が予め定められた条件を満たすか否か判別し、
前記条件を満たすと判別された場合に、前記推定された右手及び左手の位置のうち、少なくとも一方の手の指位置を補正し、
前記読み出された演奏情報及び前記各手の指位置に基づいて、演奏操作ガイド情報を生成する、演奏操作ガイド方法。
(付記8)
楽曲を構成する楽音夫々の発音タイミング情報と、音高情報と、演奏に用いる手及び指を示す情報と、を含む演奏情報を記憶する記憶部から読み出す読み出しステップ、
当該読み出された演奏情報それぞれに基づいて、前記右手及び左手の指夫々が複数の演奏操作子のいずれの位置にあるかを示す指位置を推定する位置推定ステップと、
前記推定された前記右手及び左手の指位置同士の関係が予め定められた条件を満たすか否か判別する判別ステップと、
前記条件を満たすと判別された場合に、前記推定された右手及び左手の位置のうち、少なくとも一方の手の指位置を補正する位置補正ステップと、
前記読み出された演奏情報及び前記各手の指位置に基づいて、演奏操作ガイド情報を生成するガイド情報生成ステップと、
をコンピュータに実行させる演奏操作ガイドプログラム。