(57)【要約】【課題】  繰り返し構造に着目した楽曲の分割を常に適切に行うための技術を提供する。【解決手段】  楽曲の分割、つまり関連付けるべきフレーズの抽出は、始めに先頭の音符が所定数以上、一致する部分をマーキングした後、マーキングした部分以降に一致している部分を確認していくことで行う。それにより、楽曲のなかで演奏内容が類似性を有する部分を抽出する。【選択図】      図１０
2006085090.tif 000002
【特許請求の範囲】
【請求項１】
楽曲の構造の解析を行う楽曲構造解析装置において、
前記楽曲の演奏内容を音符単位で示す演奏情報を取得する演奏情報取得手段と、
前記演奏情報取得手段が取得した演奏情報が示す部分的な演奏内容の類似性に着目した解析を行い、前記楽曲から演奏内容が類似する複数の演奏区間を抽出する構造解析手段と、
を具備することを特徴とする楽曲構造解析装置。
【請求項２】
前記構造解析手段は、音符による発音時間の相違を考慮して前記解析を行う、
ことを特徴とする請求項１記載の楽曲構造解析装置。
【請求項３】
前記構造解析手段は、前記演奏区間として抽出されない部分に存在する音符のなかで所定の条件を満たす音符は該演奏区間に含める、
ことを特徴とする請求項１、または２記載の楽曲構造解析装置。
【請求項４】
楽曲の構造の解析を行う楽曲構造解析装置に実行させるプログラムであって、
前記楽曲の演奏内容を音符単位で示す演奏情報を取得する機能と、
前記取得する機能により取得した演奏情報が示す部分的な演奏内容の類似性に着目した解析を行い、前記楽曲から演奏内容が類似する複数の演奏区間を抽出する機能と、
を実現させるためのプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、楽曲の演奏内容を音符単位で示す演奏情報を参照して、その楽曲の構造解析を行うための技術に関する。
【背景技術】
【０００２】
従来、楽曲の構造解析を行う楽曲構造解析装置としては、例えば特許文献１に記載されたものがある。その特許文献１に記載された楽曲構造解析装置では、音符の発音時間である音符長の変化に着目して、楽曲の分割を行うようにしている。
【０００３】
音符長の変化に着目することにより、楽曲全体を部分的な複数の演奏区間に分割することができる。しかし、そのような分割が、確認を望む構造の確認が容易なように常に適切に行えるとは限らない。むしろ、その分割を常に適切に行うためには、確認したい構造に着目して行うのが望ましいと言える。その構造として、類似する演奏内容の演奏が異なる複数の部分で行われる繰り返し構造も重要なものの一つであると考えられる。
【特許文献１】特開２００２−１３２２５５号公報
【発明の開示】
【発明が解決しようとする課題】
【０００４】
本発明の課題は、繰り返し構造に着目した楽曲の分割を常に適切に行うための技術を提供することにある。
【課題を解決するための手段】
【０００５】
本発明の楽曲構造解析装置は、楽曲の構造の解析を行うことを前提とし、楽曲の演奏内容を音符単位で示す演奏情報を取得する演奏情報取得手段と、演奏情報取得手段が取得した演奏情報が示す部分的な演奏内容の類似性に着目した解析を行い、楽曲から演奏内容が類似する複数の演奏区間を抽出する構造解析手段と、を具備する。
【０００６】
なお、上記構造解析手段は、音符による発音時間の相違を考慮して解析を行う、ことが望ましい。また、演奏区間として抽出されない部分に存在する音符のなかで所定の条件を満たす音符は該演奏区間に含める、ことが望ましい。
【０００７】
本発明のプログラムは、上記楽曲構造解析装置が具備する手段を実現させるための機能を搭載している。
【発明の効果】
【０００８】
本発明は、楽曲の演奏内容を音符単位で示す演奏情報を取得し、その演奏情報が示す部分的な演奏内容の類似性に着目した解析を行い、楽曲から演奏内容が類似する複数の演奏区間を抽出する。そのように演奏内容が類似性（関連性）を有する演奏区間を抽出することにより、楽曲の繰り返し構造が容易に確認できるようになる。このため、その繰り返し構造を通して、フレーズ構造の確認も容易に行えるようになる。
【発明を実施するための最良の形態】
【０００９】
以下、本発明の実施の形態について、図面を参照しながら詳細に説明する。
＜第１の実施の形態＞
図１は、第１の実施の形態による楽曲構造解析装置の構成を説明する図である。
【００１０】
その楽曲構造解析装置は、図１に示すように、装置全体の制御を行うＣＰＵ１０１と、そのＣＰＵ１０１がワークに用いるＲＡＭ１０２と、ＣＰＵ１０１が実行するプログラムや各種制御用データを格納したＲＯＭ１０３と、例えば各種キー等の操作子を有するキーボードやポインティングデバイス等である入力装置１０４と、例えば液晶表示装置である表示装置１０５と、外部装置との間でデータの入出力を行うインターフェース（Ｉ／Ｆ）１０６と、を備えて構成されている。
【００１１】
上記Ｉ／Ｆ１０６は、例えば光ディスク装置や光磁気ディスク装置などの記録媒体駆動装置との間でデータの入出力を行うものか、或いは通信ネットワークを介した通信を行う通信制御装置である。ここでは、前者であるとの前提で説明を行うことにする。
【００１２】
上述したような構成の楽曲構造解析装置は、例えばパーソナルコンピュータ（ＰＣ）、或いはＰＤＡといったデータ処理装置である。その解析装置は、後述するような動作を行わせるプログラム（アプリケーション・プログラム。以降「アプリケーション」と略記）をＣＰＵ１０１に実行させることで実現される。ここでは便宜的に、そのアプリケーションはＲＯＭ１０３に格納されていることとする。
【００１３】
そのアプリケーションは、楽曲の演奏内容を示す楽曲データを参照し、その楽曲データが示す部分的な演奏内容の類似性に着目した構造解析を行い、演奏内容が類似すると見なす演奏区間を楽曲から抽出する。それにより、他に類似するものが存在する演奏区間とそうでない部分（演奏区間）とに大別する。
【００１４】
そのように演奏内容が類似する演奏区間を抽出することにより、楽曲の繰り返し構造が容易に確認できるようになる。その繰り返し構造を通して、フレーズ構造の確認も容易に行えるようになる。演奏を行っていく際の指の運びである運指を示す運指情報の生成では、例えば演奏内容が同一の演奏区間ではその前後の部分に係わらずに同一の運指情報の生成を行えるようになる。それにより、演奏内容が同じでありながら前、或いは後の部分の違いによって運指が異なることに違和感を覚えるような人に対しては、違和感を与えないような運指情報を生成できることとなる。演奏区間の抽出は、その演奏区間に存在する音符をグループ化することに相当する。その演奏区間については以降「フレーズ」と呼ぶことにする。
【００１５】
図２は、上記楽曲データの構成を説明する図である。
その楽曲データは、Ｉ／Ｆ１０６を介して読み込まれ、ＲＡＭ１０２に格納される。楽曲の演奏内容を音符単位で示すデータ（以降「音符データ」と呼ぶ）の集合体として構成されている。図中に括弧を付して表記の「Ｎｏｔｅ」はその音符データを表している。括弧内の数値は、音符データを指定するインデックス（値）である。以降、インデックスが判明している音符データには「Ｎｏｔｅ」、及びそれに続けて括弧内にインデックスを示す数値、或いは変数のシンボルを表記したものを付して例えば「音符データＮｏｔｅ［０］」といったように記載し、そのインデックスが判明していない音符データには単に「Ｎｏｔｅ」を付して記載することとする。これは他でも同様である。
【００１６】
その音符データＮｏｔｅは、「ｉＴｉｍｅ」と表記の発音開始ティック（時刻）、「ｉＧａｔｅ」と表記のゲートタイム（発音継続時間）、「Ｐｉｔｃｈ」と表記のピッチ（ノート番号）、「ｐＰａｒｅｎｔ」と表記の当該音符データＮｏｔｅが属するグループの先頭に位置する音符データＮｏｔｅのインデックス、「ｐＳｔａｒｔ」と表記のそのグループと演奏内容が類似しているとして関連付けられた他のグループの先頭に位置する音符データＮｏｔｅのインデックス、「ｉＳｔａｔｕｓ」と表記のグループ化された状態を示すフラグ、「ｐＮｅｘｔ」と表記の次に処理対象となる音符データＮｏｔｅのインデックス、及び「ｐＲｅｖ」と表記の前に処理対象となる音符データＮｏｔｅのインデックス、の各データを備えた構成となっている。それらのなかで、データｉＴｉｍｅ、ｉＧａｔｅ、Ｐｉｔｃｈ、ｐＮｅｘｔ、及びｐＲｅｖはＩ／Ｆ１０６を介して読み込んだ楽曲データを構成するデータか、或いはそれから生成されるデータである。
【００１７】
グループ間の対応関係を管理するために、本実施の形態では、図３に示すフレーズデータを生成しＲＡＭ１０２に確保した領域に保存するようにしている。図中に括弧を付して表記の「Ｐｈｒａｓｅ」はそのフレーズデータを表している。括弧内の数値は、フレーズデータを指定するインデックス（値）である。以降、同様にインデックスが判明しているフレーズデータには「Ｐｈｒａｓｅ」、及びそれに続けて括弧内にインデックスを示す数値、或いは変数のシンボルを表記したものを付して記載することとする。
【００１８】
そのフレーズデータＰｈｒａｓｅは、「ｐＯｒｇＰａｒｅｎｔ」と表記の大元となるグレープの先頭に位置する音符データＮｏｔｅのインデックス、「ｐＳｔａｒｔ」と表記の対応するグループの先頭に位置する音符データＮｏｔｅのインデックス、「ｉＮｏｔｅＣｎｔ」と表記のグループに属する音符データＮｏｔｅ数、「ＩＴｏｔａｌＴｉｃｋ」と表記のグループの総演奏時間（合計時間）、「ｐＮｅｘｔＧｒｏｕｐ」と表記の次のグループデータＰｈｒａｓｅのインデックス、の各データを備えた構成となっている。
【００１９】
以降は、図４〜図９に示す各種処理のフローチャート、及び図１０に示す説明図を参照しつつ、楽曲構造解析装置の動作について詳細に説明する。
図４は、構造解析処理のフローチャートである。始めに図４を参照して、その解析処理について詳細に説明する。その解析処理は、ＣＰＵ１０１がＲＯＭ１０３に格納されたアプリケーションを実行することで実現される。
【００２０】
そのアプリケーションは起動されると、先ず、ステップＳＡ１で各種データ（変数を含む）の初期化を行う。続くステップＳＡ２では、例えばＩ／Ｆ１０６により記録媒体駆動装置にセットされた記録媒体から楽曲データの読み込みを行い、図２に示すようなデータ構成でＲＡＭ１０２に格納する。その後に移行するステップＳＡ３では、楽曲をフレーズ（類似するものが他に存在するフレーズ）に分割するフレーズ分割処理を実行する。一連の処理はその後に終了する。
【００２１】
図５は、上記ステップＳＡ３として実行されるフレーズ分割処理のフローチャートである。次にその分割処理について、図５に示すそのフローチャートを参照して詳細に説明する。
【００２２】
先ず、ステップＳＢ１では、楽曲データを構成する各音符データＮｏｔｅのデータｐＰａｒｅｎｔ、ｐＳｔａｒｔにＮＵＬＬ（値としては０である）を代入する。次のステップＳＢ２では、変数ｐＲｅｆＮｏｔｅに、楽曲データの先頭に位置する音符データＮｏｔｅのインデックスを代入し、変数ｐＲｅｆＬａｓｔに、その音符データＮｏｔｅから定数ＭａｒｋｉｎｇＮｏｔｅｓだけ先の音符データＮｏｔｅのインデックス値を代入する。ステップＳＢ３にはその後に移行する。定数ＭａｒｋｉｎｇＮｏｔｅｓは、グループと見なさない最小の音符数として定義したものである。
【００２３】
ステップＳＢ３では、変数ｐＲｅｆＬａｓｔの値で指定される音符データＮｏｔｅ（図中「Ｎｏｔｅ［ｐＲｅｆＬａｓｔ］」と表記。以降、その表記法も用いることにする。これは他でも同様である）のデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、つまりその音符データＮｏｔｅが最後のものであった場合、判定はＮＯとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＢ４に移行する。
【００２４】
ステップＳＢ４では、変数ｐＲｅｆＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＳｔａｒｔの値がＮＵＬＬか否か判定する。その音符データＮｏｔｅがグループ化されていない場合、その値はＮＵＬＬであることから、判定はＹＥＳとなり、ステップＳＢ５で変数ｉＭａｒｋＣｎｔに０を代入し、更にステップＳＢ６で関連付けるグループの先頭位置を検索するための先頭位置検索処理を実行してからステップＳＢ７に移行する。そうでない場合には、判定はＮＯとなってステップＳＢ９に移行する。
【００２５】
上記変数ｉＭａｒｋＣｎｔは、検索により抽出した先頭位置の数を計数するためのものである。ステップＳＢ７では、その値が０でないか否か判定する。その先頭位置が抽出された場合、その値は０より大きい値に更新されることから、判定はＹＥＳとなり、ステップＳＢ８でグループ化処理を実行し、次のステップＳＢ９で変数ｐＲｅｆＮｏｔｅに、変数ｐＲｅｆＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値、変数ｐＲｅｆＮｏｔｅに、その音符データＮｏｔｅから定数ＭａｒｋｉｎｇＮｏｔｅｓだけ先の音符データＮｏｔｅのデータｐＮｅｘｔの値を代入してから上記ステップＳＢ３に戻る。そうでない場合には、判定はＮＯとなり、次にそのステップＳＢ９に移行する。
【００２６】
このようにして、フレーズ分割処理では、変数ｐＲｅｆＮｏｔｅの値を順次、更新しながら、その値で指定される音符（音符データＮｏｔｅ）が先頭位置に存在するグループ（フレーズ）を大元のグループとして、そのグループと関連付けられる他のグループを探すようになっている。その他のグループが探し出せた場合、大元のグループ、及びその他のグループの登録を行っている。
【００２７】
次に、上記ステップＳＢ６として実行される先頭位置検索処理について、図６に示すそのフローチャートを参照して詳細に説明する。
先ず、ステップＳＣ１では、変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＲｅｆＬａｓｔ］．ｐＮｅｘｔ（変数ｐＲｅｆＬａｓｔの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔ）の値を代入する。次のステップＳＣ２では、変数ｐＬｏｏｋｕｐＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬでない場合、判定はＹＥＳとなってステップＳＣ５に移行する。そうでない場合には、判定はＮＯとなってステップＳＣ３に移行する。
【００２８】
ステップＳＣ３では、変数ｉＭａｒｋＣｎｔの値が０より大きいか否か判定する。その値が０より大きい場合、判定はＹＥＳとなってステップＳＣ４に移行し、フレーズデータＰｈｒａｓｅの登録を行うためのフレーズデータの登録処理を実行した後、一連の処理を終了する。そうでない場合には、判定はＮＯとなり、ここで一連の処理を終了する。
【００２９】
ステップＳＣ５では、変数ｊｄｇに論理値ＴＲＵＥを代入する。続くステップＳＣ６では、変数ｉに定数ＭａｒｋｉｎｇＮｏｔｅｓを代入する。その次のステップＳＣ７では、変数ｐＮｏｔｅｔｍｐに変数ｐＬｏｏｋｕｐＮｏｔｅの値、変数ｐＲｅｆｔｍｐに変数ｐＲｅｆＮｏｔｅの値をそれぞれ代入する。その後に移行するステップＳＣ８では、変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｉの値が０より大きいか否か判定する。変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｉの値が０より大きい場合、判定はＹＥＳとなってステップＳＣ９に移行する。そうでない場合には、つまり変数ｊｄｇの値がＦＡＬＳＥか、或いは変数ｉの値が０以下であった場合には、判定はＮＯとなってステップＳＣ１６に移行する。
【００３０】
ステップＳＣ９では、変数ｐＲｅｆＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬでない場合、つまりそれ以降の音符データＮｏｔｅが存在しない場合、判定はＹＥＳとなってステップＳＣ１０に移行する。そうでない場合には、判定はＮＯとなり、ステップＳＣ１５で変数ｊｄｇにＦＡＬＳＥを代入し、更にステップＳＣ１４で変数ｉの値をデクリメント（図中「−−」と表記）してから上記ステップＳＣ８に戻る。
【００３１】
ステップＳＣ１０では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅ［ｐＲｅｆｔｍｐ］．Ｐｉｔｃｈの値とＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．Ｐｉｔｃｈの値が等しければ（変数ｐＲｅｆｔｍｐ、ｐＮｏｔｅｔｍｐの各値で指定される音符のピッチが等しければ）ＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。続くステップＳＣ１１では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ＩＴｉｍｅの値を引いた値に対し、Ｎｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いて得られる値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅ未満であれば（それら発音開始ティックの時間間隔の差が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅとして用意した閾値未満であれば）ＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。その次のステップＳＣ１２では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＧａｔｅの値をＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＧａｔｅの値で割った値を１から引いた値の絶対値が定数ＩＧａｔｅＴｉｍｅＲａｔｉｏ未満であれば（それらのゲートタイム比が許容範囲内であれば）ＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。その後は、ステップＳＣ１３において、変数ｐＮｏｔｅｔｍｐにＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ｐＮｅｘｔの値、変数ｐＲｅｆｔｍｐにＮｏｔｅ［ｐＲｅｆｔｍｐ］．ｐＮｅｘｔの値をそれぞれ代入してからステップＳＣ１４に移行する。
【００３２】
このようにして、本実施の形態では、音符のピッチが等しい、発音開始ティック間の時間間隔の差が許容範囲内、ゲートタイム比が許容範囲内、という条件を全て満たしていなければ変数ｊｄｇにはＦＡＬＳＥを代入するようにしている。それにより、抽出する先頭位置としては、それらの条件を音符毎に全て満足する音符数が定数ＭａｒｋｉｎｇＮｏｔｅｓ以上となっている音符群を対象にしている。その対象となる条件については便宜的に「フレーズ成立条件」と呼び、音符毎に満足すべき全ての条件については「音符成立条件」と呼ぶことにする。フレーズ成立条件は、定数ＭａｒｋｉｎｇＮｏｔｅｓ以上、連続して音符成立条件が満たされた場合に満たすことになる。
【００３３】
上記ステップＳＣ８の判定がＮＯとなって移行するステップＳＣ１６では、変数ｊｄｇの値がＴＲＵＥか否か判定する。その値がＴＲＵＥであった場合、つまりフレーズ成立条件を満たす、抽出すべき先頭位置が抽出できた場合、判定はＹＥＳとなり、ステップＳＣ１８でＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ｐＰａｒｅｎｔに変数ｐＲｅｆＮｏｔｅの値を代入し、ステップＳＣ１９で変数ｉＭａｒｋＣｎｔの値をインクリメント（図中「＋＋」と表記）し、更にステップＳＣ２０で変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ｐＮｅｘｔの値を代入してから上記ステップＳＣ２に戻る。そうでない場合には、判定はＮＯとなり、ステップＳＣ１７で変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ｐＮｅｘｔの値を代入してから上記ステップＳＣ２に戻る。
【００３４】
このようにして、変数ｐＲｅｆＮｏｔｅの値で指定される音符（音符データＮｏｔｅ）を大元のフレーズの先頭位置と想定し、そのフレーズとフレーズ成立条件を満たす各フレーズの先頭位置の音符データＮｏｔｅにデータｐＰａｒｅｎｔとして変数ｐＲｅｆＮｏｔｅの値をそれぞれ設定するようにしている。その設定により、先頭位置の音符をマーキングしている。
【００３５】
図７は、上記ステップＳＣ４として実行されるフレーズデータの登録処理のフローチャートである。次に図７を参照して、その登録処理について詳細に説明する。
先ず、ステップＳＤ１では、変数ｉＰに０を代入する。続くステップＳＤ２では、その変数ｉＰの値で指定されるフレーズデータＰｈｒａｓｅのデータｐＯｒｇＰａｒｅｎｔの値がＮＵＬＬか否か判定する。その値がＮＵＬＬでない場合、判定はＮＯとなり、ステップＳＤ３で変数ｉＰの値をインクリメントしてから、再度ステップＳＤ２の判定処理を行う。そうでない場合には、判定はＹＥＳとなってステップＳＤ４に移行し、Ｐｈｒａｓｅ［ｉＰ］．ｐＯｒｇＰａｒｅｎｔ、及びＰｈｒａｓｅ［ｉＰ］．ｐＳｔａｒｔとして変数ｐＲｅｆＮｏｔｅの値、Ｐｈｒａｓｅ［ｉＰ］．ｉＮｏｔｅＣｎｔとして定数ＭａｒｋｉｎｇＮｏｔｅｓ、Ｐｈｒａｓｅ［ｉＰ］．ＩＴｏｔａｌＴｉｃｋとして、Ｎｏｔｅ［ｐＲｅｆＬａｓｔ］．ＩＴｉｍｅの値にＮｏｔｅ［ｐＲｅｆＬａｓｔ］．ＩＧａｔｅの値を加算した値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いて得られる値（定数ＭａｒｋｉｎｇＮｏｔｅｓ分の総演奏時間）をそれぞれ代入する。一連の処理はその後に終了する。
【００３６】
図８は、図５に示すフレーズ分割処理内でステップＳＢ８として実行されるグループ化処理のフローチャートである。次にそのグループ化処理について、図８を参照して詳細に説明する。
【００３７】
先ず、ステップＳＦ１では、変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＲｅｆＬａｓｔ］．ｐＮｅｘｔの値を代入する。次のステップＳＦ２では、変数ｐＬｏｏｋｕｐＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬでない場合、判定はＹＥＳとなってステップＳＦ３に移行する。そうでない場合には、判定はＮＯとなり、ここで一連の処理を終了する。
【００３８】
ステップＳＦ３では、変数ｐＬｏｏｋｕｐＮｏｔｅの値で指定される音符データＮｏｔｅのデータｐＰａｒｅｎｔの値が変数ｐＲｅｆＮｏｔｅの値と等しいか否か判定する。それらの値が等しくない場合、判定はＮＯとなり、ステップＳＦ４で変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＲｅｆＬａｓｔ］．ｐＮｅｘｔの値を代入した後、上記ステップＳＦ２に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＦ５に移行する。それにより、関連付けられるフレーズの先頭位置としてマーキングされた音符の抽出を行う。
【００３９】
ステップＳＦ５では、変数ｐＮｏｔｅｔｍｐに変数ｐＬｏｏｋｕｐＮｏｔｅの値、変数ｐＲｅｆｔｍｐに変数ｐＲｅｆＮｏｔｅの値をそれぞれ代入する。次のステップＳＦ６では、変数ｊｄｇにＴＲＵＥを代入する。その後は、ステップＳＦ７で変数ｉに１を代入してからステップＳＦ８に移行する。
【００４０】
ステップＳＦ８では、変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｐＮｏｔｅｔｍｐの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値がＮＵＬＬか否か判定する。変数ｊｄｇの値がＴＲＵＥでないか、或いはそのデータｐＮｅｘｔの値がＮＵＬＬであった場合、判定はＮＯとなってステップＳＦ１４に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＦ９に移行する。
【００４１】
ステップＳＦ９〜ＳＦ１２では、図６に示すステップＳＣ１０〜ＳＣ１３と同様の処理が行われる。ステップＳＦ１２の処理の実行後は、ステップＳＦ１３に移行して、変数ｉの値をインクリメントしてから上記ステップＳＦ８に戻る。それにより、連続して音符成立条件を満たす音符数のカウントを継続させる。
【００４２】
上記ステップＳＦ８の判定がＮＯとなって移行するステップＳＦ１４では、変数ｉの値が定数ＭａｒｋｉｎｇＮｏｔｅｓより大きいか否か判定する。その値が定数ＭａｒｋｉｎｇＮｏｔｅｓ以下であった場合、判定はＮＯとなり、ステップＳＦ１５でＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ｐＰａｒｅｎｔとしてＮＵＬＬを設定し、ステップＳＦ１６で変数ｐＬｏｏｋｕｐＮｏｔｅにＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ｐＮｅｘｔの値を代入してから上記ステップＳＦ２に戻る。一方、そうでない場合には、つまり変数ｉの値が定数ＭａｒｋｉｎｇＮｏｔｅｓより大きい場合には、判定はＹＥＳとなってステップＳＦ１７に移行する。
【００４３】
ステップＳＦ１７では、フレーズデータ間の関連付けを行いつつ、フレーズデータの登録を行うフレーズデータへのグループ登録処理を実行する。続くステップＳＦ１８では、変数ｐＮｏｔｅＲｓｌｔに変数ｐＬｏｏｋｕｐＮｏｔｅの値を代入する。その後はステップＳＦ１９に移行する。
【００４４】
ステップＳＦ１９では、変数ｐＮｏｔｅｔｍｐの値が変数ｐＮｏｔｅＲｓｌｔの値と等しくないか否か判定する。それらの値が等しい場合、判定はＮＯとなってステップＳＦ１６に移行する。そうでない場合には、判定はＹＥＳとなり、ステップＳＦ２０でＮｏｔｅ［ｐＮｏｔｅＲｓｌｔ］．ｐＳｔａｒｔに変数ｐＬｏｏｋｕｐＮｏｔｅの値、Ｎｏｔｅ［ｐＮｏｔｅＲｓｌｔ］．ｐＰａｒｅｎｔに変数ｐＲｅｆＮｏｔｅの値をそれぞれ代入し、次のステップＳＦ２１で変数ｐＮｏｔｅＲｓｌｔにＮｏｔｅ［ｐＮｏｔｅＲｓｌｔ］．ｐＮｅｘｔの値を代入してから上記ステップＳＦ１９に戻る。それにより、大元のフレーズと関連付けられたフレーズを構成する各音符データＮｏｔｅのデータｐＳｔａｒｔとして、その大元のフレーズの先頭位置の音符データＮｏｔｅを指定する値が設定される。データｐＰａｒｅｎｔとしては、属するフレーズの先頭位置の音符データＮｏｔｅを指定する値が設定される。
【００４５】
図１０は、楽曲の分割方法を説明する図である。
楽曲の分割、つまり関連付けるべきフレーズの抽出は、図１０に示すように、始めに先頭位置検索により、先頭部分の音符が全て音符成立条件を満たすフレーズの先頭位置の音符に対してマーキングを行い、その後、音符成立条件を満たさなくなるまでの範囲をフレーズの範囲として再度、特定（検索）することで行われる。先頭位置の音符に対するマーキングは、図６に示す先頭位置検索処理の実行により行われ、再度の検索はグループ化処理を実行することで行われる。
【００４６】
図９は、上記ステップＳＦ１７として実行されるフレーズデータへのグループ登録処理のフローチャートである。最後に図９を参照して、その登録処理について詳細に説明する。
【００４７】
先ず、ステップＳＥ１では、変数ｉＰに０を代入する。続くステップＳＥ２では、その変数ｉＰの値で指定されるフレーズデータＰｈｒａｓｅのデータｐＯｒｇＰａｒｅｎｔの値が変数ｐＲｅｆＮｏｔｅの値と等しいか否か判定する。それらの値が一致する場合、判定はＹＥＳとなってステップＳＥ６に移行する。そうでない場合には、判定はＮＯとなってステップＳＥ３に移行する。
【００４８】
ステップＳＥ３では、変数ｉＰの値で指定されるフレーズデータＰｈｒａｓｅのデータｐＯｒｇＰａｒｅｎｔの値がＮＵＬＬか否か判定する。その値がＮＵＬＬでない場合、判定はＮＯとなり、ステップＳＥ４で変数ｉＰの値をインクリメントしてから上記ステップＳＥ２に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＥ５に移行し、Ｐｈｒａｓｅ［ｉＰ］．ｐＯｒｇＰａｒｅｎｔとして変数ｐＲｅｆＮｏｔｅの値、Ｐｈｒａｓｅ［ｉＰ］．ｐＳｔａｒｔとして変数ｐＬｏｏｋｕｐＮｏｔｅの値、Ｐｈｒａｓｅ［ｉＰ］．ｉＮｏｔｅＣｎｔとして変数ｉの値、Ｐｈｒａｓｅ［ｉＰ］．ＩＴｏｔａｌＴｉｃｋとして、Ｎｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＴｉｍｅの値にＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＧａｔｅの値を加算した値からＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ＩＴｉｍｅの値を引いて得られる値（フレーズ全体での総演奏時間）をそれぞれ代入する。一連の処理はその後に終了する。
【００４９】
上記ステップＳＥ２の判定がＹＥＳとなって移行するステップＳＥ６では、Ｐｈｒａｓｅ［ｉＰ］．ｉＮｏｔｅＣｎｔの値が変数ｉの値未満か否か判定する。変数ｉＰの値で指定されるフレーズの音符数が変数ｉの値以上であった場合、判定はＮＯとなってステップＳＥ３に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＥ７に移行し、Ｐｈｒａｓｅ［ｉＰ］．ｉＮｏｔｅＣｎｔとして変数ｉの値、Ｐｈｒａｓｅ［ｉＰ］．ＩＴｏｔａｌＴｉｃｋとして、Ｎｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＴｉｍｅの値にＮｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＧａｔｅの値を加算した値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いて得られる値をそれぞれ代入する。また、変数ｐＲｅｆＮｏｔｅの値で指定される音符データＮｏｔｅから変数ｉの値分の音符データＮｏｔｅに対し、データｐＰａｒｅｎｔ、ｐＳｔａｒｔとして変数ｐＲｅｆＮｏｔｅの値をそれぞれ設定する。一連の処理はその後に終了する。
【００５０】
このようにして、本実施の形態では、関連付けたフレーズ間で総演奏時間が異なる場合、フレーズのなかで最も長い総演奏時間のものを各フレーズの総演奏時間とさせている。それにより、基本的には同じと見なすべきフレーズのなかで最後を他と変化させたようなものはその変化させた部分の存在を過大に評価しないようにさせている。
＜第２の実施の形態＞
上記第１の実施の形態では、音符を一対一に対応付けてフレーズ間の対比を行っている。これに対し、第２の実施の形態は、音符長を考慮してフレーズ間の対比を行うようにしたものである。
【００５１】
楽曲では、実質的には同じフレーズであってもその一部を変更させることがある。具体的には、発音される楽音を複数の楽音に置き換えたり（分割）、或いはその逆に、複数の楽音をまとめて１つの楽音とさせたり（結合）することがある。このようなことから、第２の実施の形態では、そのような分割や結合にも適切に対応できるように、音符長を考慮したフレーズ間の対比を行うようにしている。
【００５２】
第２の実施の形態における楽曲構造解析装置の構成は、基本的に第１の実施の形態におけるそれと同じである。動作も大部分は同じか、或いは基本的に同じである。このことから、第１の実施の形態で付した符号をそのまま用いて、第１の実施の形態から異なる部分についてのみ説明する。
【００５３】
第２の実施の形態では、図８に示すグループ化処理において、ステップＳＦ７〜ＳＦ１０間が第１の実施の形態から異なっている。このことから、その異なる部分について、図１１に示すフローチャートを参照して詳細に説明する。
【００５４】
第２の実施の形態では、ステップＳＦ７から移行するステップＳＦ８の判定がＹＥＳとなると、次にステップＳＧ１に移行して、変数ＴｉｃｋＤｉｆに、Ｎｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ＩＴｉｍｅの値を引いた値に対し、Ｎｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いた値を減算して得られる値（フレーズ間における、異なる音符間の発音開始ティックの時間間隔の差）を代入する。その後に移行するステップＳＧ２では、変数ＴｉｃｋＤｉｆの値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより大きいか否か判定する。その値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより大きい場合、つまり関連付けされるフレーズのほうが大元のフレーズより時間間隔が無視できない差で長い場合、判定はＹＥＳとなってステップＳＧ４に移行し、そうでない場合には、判定はＮＯとなってステップＳＧ３に移行する。
【００５５】
ステップＳＧ３では、変数ＴｉｃｋＤｉｆの値が負の値の定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さいか否か判定する。その値が負の値の定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さい場合、つまり関連付けされるフレーズのほうが大元のフレーズより時間間隔が無視できない差で短い場合、判定はＹＥＳとなってステップＳＧ１０に移行し、そうでない場合には、判定はＮＯとなってステップＳＦ９に移行する。
【００５６】
上記ステップＳＧ４では、変数ｐＮｏｔｅＳｋｉｐに、Ｎｏｔｅ［ｐＲｅｆｔｍｐ］．ｐＮｅｘｔの値を代入する。次のステップＳＧ５では、Ｎｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＴｉｍｅの値が、Ｎｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ＩＴｉｍｅの値より大きいか否か判定する。前者が後者以下であった場合、判定はＮＯとなってステップＳＧ３に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＧ６に移行する。
【００５７】
ステップＳＧ６では、変数ＴｉｃｋＤｉｆ２に、Ｎｏｔｅ［ｐＮｏｔｅｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ＩＴｉｍｅの値を引いた値に対し、Ｎｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いた値を減算して得られる値を代入する。その後に移行するステップＳＧ７では、変数ＴｉｃｋＤｉｆの値の絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さいか否か判定する。その絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さい場合、つまり２つのフレーズ間における時間間隔の差が許容範囲内であった場合、判定はＹＥＳとなり、ステップＳＧ９で変数ｎＲｅｆｔｍｐに変数ｐＮｏｔｅＳｋｉｐの値を代入した後、ステップＳＧ３に移行する。そうでない場合には、判定はＮＯとなってステップＳＧ８に移行し、変数ｐＮｏｔｅＳｋｉｐにＮｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ｐＮｅｘｔの値を代入する。その後はステップＳＧ５に戻る。それにより、大元のフレーズ側で着目する音符を先に進めることで時間的な調整が可能か否かの確認を再度、行う。そのような確認により、例えば大元のフレーズでは２個の八分音符が存在する演奏区間に、関連付けられるフレーズでは１個の四分音符が存在しているのであれば、２個の八部音符を１個の四分音符と対応付けて両者の演奏時間は対比されることとなる。
【００５８】
ステップＳＧ３の判定がＹＥＳとなって移行するステップＳＧ１０では、変数ｉＳｋｉｐに１を代入する。続くステップＳＧ１１では、変数ｐＮｏｔｅＳｋｉｐにＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ｐＮｅｘｔの値を代入する。その後はステップＳＧ１２に移行して、Ｎｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ＩＴｉｍｅの値が、Ｎｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ＩＴｉｍｅの値より大きいか否か判定する。前者が後者以下であった場合、判定はＮＯとなってステップＳＧ９に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＧ１３に移行する。
【００５９】
ステップＳＧ１３では、変数ＴｉｃｋＤｉｆ２に、Ｎｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＬｏｏｋｕｐＮｏｔｅ］．ＩＴｉｍｅの値を引いた値に対し、Ｎｏｔｅ［ｐＲｅｆｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅ［ｐＲｅｆＮｏｔｅ］．ＩＴｉｍｅの値を引いた値を減算して得られる値を代入する。その後に移行するステップＳＧ１４では、変数ＴｉｃｋＤｉｆの値の絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さいか否か判定する。その絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅより小さい場合、つまり２つのフレーズ間における時間間隔の差が許容範囲内であった場合、判定はＹＥＳとなってステップＳＧ１７に移行する。そうでない場合には、判定はＮＯとなり、ステップＳＧ１５で変数ｉＳｋｉｐの値をインクリメントし、ステップＳＧ１６で変数ｐＮｏｔｅＳｋｉｐにＮｏｔｅ［ｐＮｏｔｅＳｋｉｐ］．ｐＮｅｘｔの値を代入する。その後はステップＳＧ１２に戻る。それにより、大元のフレーズと関連付けられるフレーズ側で着目する音符を先に進めることで時間的な調整が可能か否かの確認を再度、行う。
【００６０】
ステップＳＧ１７では、変数ｉＳｋｉｐの値が０より大きいか否か判定する。その値が０より大きい場合、判定はＹＥＳとなり、ステップＳＧ１８でＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ｉＳｔａｔｕｓとして１を設定し、ステップＳＧ１９で変数ｐＮｏｔｅｔｍｐにＮｏｔｅ［ｐＮｏｔｅｔｍｐ］．ｐＮｅｘｔの値を代入し、更にステップＳＧ２０で変数ｉＳｋｉｐの値をデクリメントしてからステップＳＧ１７に戻る。それにより、大元のフレーズ側で該当する音符が存在しない音符の全てにデータｉＳｔａｔｕｓとして１を設定する。
＜第３の実施の形態＞
上記第１、及び第２の実施の形態では、基本的に、音符成立条件が満足しなくなったところでフレーズの範囲を区切るようにしている。これに対し、第３の実施の形態は、その条件を満たさない音符のなかでフレーズに加えるべき条件を満たしているものを近傍のフレーズに加えるようにしたものである。それにより、他の関連付けるべきフレーズと一部のピッチを変化させたような音符はその変化を無視する形で本来、属すると見なすべきフレーズに帰属させるようにしている。そのようにすることにより、第２の実施の形態と同じく、不要なフレーズ分割をより回避できるようになる。
【００６１】
第３の実施の形態における楽曲構造解析装置の構成は、第２の実施の形態と同様に、基本的に第１の実施の形態におけるそれと同じである。動作も大部分は同じか、或いは基本的に同じである。このことから、第１の実施の形態で付した符号をそのまま用いて、第１の実施の形態から異なる部分についてのみ説明する。
【００６２】
第３の実施の形態では、図４に示す構造解析処理内でステップＳＡ３として実行されるフレーズ分割処理が第１の実施の形態から異なっている。このことから、始めに、第３の実施の形態におけるフレーズ分割処理について、図１２に示すそのフローチャートを参照して詳細に説明する。
【００６３】
図１２において、ステップＳＨ１〜ＳＨ８の処理は図５に示すステップＳＢ１〜ＳＢ８のそれと基本的に同じであり、ステップＳＨ１０の処理はステップＳＢ９のそれと基本的に同じである。第３の実施の形態では、ステップＳＨ８、ＳＨ１０間に、ステップＳＨ９として端数処理を実行するようになっている。その端数処理は、ステップＳＨ８のグループ化処理の実行時に、本来、帰属させるべきフレーズから除外された音符をそのフレーズに帰属させるための処理である。
【００６４】
図１３は、その端数処理のフローチャートである。次に図１４を参照して、その端数処理について詳細に説明する。
先ず、ステップＳＩ１では、変数ｐＮｏｔｅＰｔｒに、楽曲データの先頭に位置する音符データＮｏｔｅのインデックス値を代入する。次のステップＳＩ２では、変数ｐＮｏｔｅＰｔｒの値で指定される音符データＮｏｔｅのデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＹＥＳとなり、ここで一連の処理を終了する。そうでない場合には、判定はＮＯとなってステップＳＩ３に移行する。
【００６５】
ステップＳＩ３では、Ｎｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＰａｒｅｎｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ステップＳＩ１７で変数ｐＮｏｔｅＰｔｒにＮｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＮｅｘｔの値を代入してから上記ステップＳＩ２に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＩ４に移行する。
【００６６】
ステップＳＩ４では、変数ｐＨｅａｄにＮｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＳｔａｒｔの値を代入する。続くステップＳＩ５では、Ｎｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＳｔａｒｔの値が変数ｐＨｅａｄの値と等しいか否か判定する。それらの値が等しい場合、判定はＹＥＳとなり、ステップＳＩ６で変数ｐＮｏｔｅＰｔｒにＮｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＮｅｘｔの値を代入してから上記ステップＳＩ５に戻る。それにより、同じフレーズに属する音符が続く部分のスキップを行う。一方、そうでない場合には、判定はＮＯとなってステップＳＩ７に移行する。
【００６７】
ステップＳＩ７では、変数ｐＴａｉｌに変数ｐＮｏｔｅＰｔｒの値を代入する。次のステップＳＩ８では、変数ｉＣｎｔに０を代入する。その次のステップＳＩ９では、Ｎｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＳｔａｒｔの値がＮＵＬＬであり、且つ変数ｉＣｎｔの値が定数ｉＩｇｎｏｒｅＮｏｔｅｓ未満か否か判定する。定数ｉＩｇｎｏｒｅＮｏｔｅｓはフレーズに特別に帰属させる音符数の上限値として定義したものである。このことから、変数ｐＮｏｔｅＰｔｒの値で指定される音符が何れのフレーズにも属しておらず、且つ変数ｉＣｎｔでカウントした音符数が上限値を下回っている場合、判定はＹＥＳとなり、ステップＳＩ１０で変数ｉＣｎｔの値をインクリメントし、ステップＳＩ１１で変数ｐＮｏｔｅＰｔｒにＮｏｔｅ［ｐＮｏｔｅＰｔｒ］．ｐＮｅｘｔの値を代入してから上記ステップＳＩ９に戻る。それにより、上限値を下回る範囲内で、直前のフレーズの最後に位置する音符以降に続く音符であり、且つフレーズに属さない音符の数のカウントを行う。一方、そうでない場合には、判定はＮＯとなってステップＳＩ１２に移行する。
【００６８】
ステップＳＩ１２では、変数ｉＣｎｔの値が定数ｉＩｇｎｏｒｅＮｏｔｅｓ未満か否か判定する。その値が定数ｉＩｇｎｏｒｅＮｏｔｅｓ以上であった場合、判定はＮＯとなってステップＳＩ１７に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＩ１３に移行し、変数ｉＣｎｔの値が０より大きいか否か判定する。その値が０より大きい場合、判定はＹＥＳとなってステップＳＩ１４に移行し、そうでない場合には、判定はＮＯとなってステップＳＩ１７に移行する。
【００６９】
ステップＳＩ１４では、Ｎｏｔｅ［ｐＴａｉｌ］．ｐＳｔａｒｔとして変数ｐＨｅａｄの値、Ｎｏｔｅ［ｐＴａｉｌ］．ｉＳｔａｔｕｓとして２、Ｎｏｔｅ［ｐＴａｉｌ］．ｐＰａｒｅｎｔとしてＮｏｔｅ［ｐＮｏｔｅＰｔｒ−１］．ｐＰａｒｅｎｔの値をそれぞれ設定する。続くステップＳＩ１５では、変数ｐＴａｉｌにＮｏｔｅ［ｐＴａｉｌ］．ｐＮｅｘｔの値を代入する。その代入後は、ステップＳＩ１６で変数ｉＣｎｔの値をデクリメントした後、上記ステップＳＩ１３に戻る。それにより、変数ｉＣｎｔでカウントした分の音符を直前にフレーズに帰属させるための設定を行う。
【００７０】
このように、本実施の形態では、帰属可能な音符数の上限値として定数ｉＩｇｎｏｒｅＮｏｔｅｓを定め、その上限値以上、フレーズに属さない音符が直前のフレーズから続く場合、フレーズへの音符の帰属は行わないようにしている。これは、その上限値以上、続く音符列は別のフレーズとして扱うべき可能性が考えられるためである。その上限値を考慮することにより、フレーズへの音符の帰属をより適切に行えるようにさせている。
【００７１】
図１４は、フレーズ分割結果の表示例を示す図である。
その表示例は、楽譜上にフレーズ分割結果を表す情報を併せて表示させた場合のものである。図中、「−」が間に挿入された２つの数字は、前側は関連付けられたフレーズに割り当てた番号、後側はフレーズが出現する順番、をそれぞれ表している。それにより、例えば「１−１」「１−２」が付された２小節の長さの部分は共に、関連付けられたフレーズの区間であり、それら２つのフレーズの間に「２−１」「２−２」が付された別と関連付けられたフレーズが演奏されることを表している。この図１４に示すような表示例を表示させることにより、楽曲の構造は視覚的にも容易に理解させることができる。
＜第４の実施の形態＞
上記第１〜第３の実施の形態では、フレーズ間の類似性による関連付けのために音符（音符データＮｏｔｅ）単位で対比を行っている。これに対し、第４の実施の形態は、発音タイミングに着目した別データを生成することにより、同一と見なせる一つ以上の音符は１つの別データとして管理し、その別データを対比に利用するようにしたものである。
【００７２】
第４の実施の形態における楽曲構造解析装置の構成は、他の実施の形態と同様に、基本的に第１の実施の形態におけるそれと同じである。このことから、第１の実施の形態で付した符号をそのまま用いて説明を行うことにする。
【００７３】
第４の実施の形態では、上記他の実施の形態と同じく、楽曲データ、及びフレーズデータを扱っている。その他に、時系列データ、ノートデータ、及びフレーズブロックデータを扱っている。それらは全てＲＡＭ１０２に格納されるデータである。それら各データは以下のようなものである。
【００７４】
図１５は、第４の実施の形態で扱われる楽曲データの構成を説明する図である。
その楽曲データは、Ｉ／Ｆ１０６を介して読み込み、ＲＡＭ１０２に格納されるものである。楽曲の演奏内容を音符単位で示す音符データは、図中、括弧を付して表記の「ＭｉｄｉＥｖｅｎｔ」で表している。その音符データＭｉｄｉＥｖｅｎｔは、データｉＴｉｍｅ、ｉＴｙｐｅ、ｉＧａｔｅ、Ｐｉｔｃｈ、及びｐＮｅｘｔの、の各データを備えた構成となっている。データｉＴｙｐｅは、音符データＭｉｄｉＥｖｅｎｔの種類を表すものである。楽音の発音を指示する種類（ノートデータ）では０、テンポを指定する種類（テンポデータ）では１となっている。
【００７５】
図１６は、第４の実施の形態で扱われる時系列データの構成を説明する図である。
その時系列データＮｏｔｅＧｒｏｕｐは、上記別データに相当するものである。対応する１つ以上の音符による発音（演奏）開始ティックを示すデータＩＴｉｍｅ、その終了ティックを示すデータＩＴｅｒｍ、対応する時系列データがグループ化されているか否かを示すフラグであるデータｉＧｒｏｕｐＦｌａｇ、対応するノートデータへのポインタとなるインデックス値であるデータＮｏｔｅＥｖ、次の時系列データへのポインタとなるインデックス値であるデータＮｅｘｔ、前の時系列データへのポインタとなるインデックス値であるデータｐｒｅｖ、の各データから構成される。データＮｏｔｅＥｖは、対応するノートデータ数分、存在する。
【００７６】
図１７は、ノートデータの構成を説明する図である。
そのノートデータＮｏｔｅは、対応する音符データＭｉｄｉＥｖｅｎｔへのポインタとなるインデックス値であるデータｐＥｖ、そのピッチを示すデータＰｉｔｃｈ、次のノートデータＮｏｔｅのインデックス値であるデータｎｅｘｔ、前のノートデータＮｏｔｅのインデックス値であるデータｐｒｅｖ、の各データから構成される。
【００７７】
図１８は、フレーズ管理用データの構成を説明する図である。図１８（ａ）はフレーズデータＰｈｒａｓｅ、図１８（ｂ）はフレーズブロックデータＰｈＢｌｏｃｋ、の構成をそれぞれ表している。
【００７８】
フレーズデータＰｈｒａｓｅは、対応するフレーズの発音（演奏）開始ティックを示すデータＩＴｉｍｅ、その終了ティックを示すデータＩＴｅｒｍ、フレーズの切れ目（区切り）の種類（分類）を示すデータｉＴｙｐｅ、関連するフレーズデータのなかで先頭のもののインデックス値であるデータｐＦｉｒｓｔ、その最後のもののインデックス値であるデータｐＥｎｄ、次のフレーズデータＰｈｒａｓｅのインデックス値であるデータｎｅｘｔ、前のフレーズデータＰｈｒａｓｅのインデックス値であるデータｐｒｅｖ、の各データから構成される。
【００７９】
フレーズブロックデータＰｈＢｌｏｃｋは、関連付けられたフレーズの数であるデータｉＰｈｒａｓｅ、そのなかで先頭に位置するフレーズデータＰｈｒａｓｅのインデックス値であるデータｐＦｉｒｓｔ、次のフレーズブロックデータＰｈＢｌｏｃｋのインデックス値であるデータｎｅｘｔ、前のフレーズブロックデータＰｈＢｌｏｃｋのインデックス値であるデータｐｒｅｖ、の各データから構成される
本実施の形態では、図１５に示す楽曲データから図１６〜図１８に示す各データを生成し、構造解析を行うようになっている。以降は、図１９〜図２４に示す各種処理のフローチャートを参照して、第４の実施の形態による楽曲構造解析装置の動作について詳細に説明する。
【００８０】
図１９は、構造解析処理のフローチャートである。始めに図１９を参照して、その解析処理について詳細に説明する。その解析処理は、ＣＰＵ１０１がＲＯＭ１０３に格納されたアプリケーションを実行することで実現される。
【００８１】
そのアプリケーションは起動されると、先ず、ステップＳＪ１で例えばＩ／Ｆ１０６により記録媒体駆動装置にセットされた記録媒体から楽曲データの読み込みを行い、図１６に示すようなデータ構成の時系列データＮｏｔｅＧｒｏｕｐを生成してＲＡＭ１０２に格納する時系列データの生成処理を実行する。その後に移行するステップＳＪ２では、フレーズ分割処理を実行する。その実行後、一連の処理を終了する。
【００８２】
図２０は、上記ステップＳＪ１として実行される時系列データの生成処理のフローチャートである。次に図２０を参照して、その生成処理について詳細に説明する。図１６に示す時系列データＮｏｔｅＧｒｏｕｐ、及び図１７に示すノートデータＮｏｔｅは、その生成処理の実行によって生成される。
【００８３】
先ず、ステップＳＫ１では、各種変数を対象にした初期化を行う。変数ｎｇｒ、ｎｔｍｐ、ｍｅ、及びｐｈｔｍｐなどにはＲＡＭ１０２の対応する領域のなかで先頭に位置するデータを指定するためのインデックス値が代入される。それに続くステップＳＫ２では、変数ｍｅの値で指定される音符データＭｉｄｉＥｖｅｎｔのデータｐＮｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＫ３に移行する。
【００８４】
ステップＳＫ３では、変数ＩＴＰｒｏｇに、変数ｍｅの値で指定される音符データＭｉｄｉＥｖｅｎｔのデータＩＴｉｍｅの値を代入し、変数ｎＨａｒｍに、ノートデータＮｏｔｅを格納できる空きエリアのインデックス値を代入する。次のステップＳＫ４では、変数ｎｇｒの値で指定される時系列データＮｏｔｅＧｒｏｕｐのデータＮｏｔｅＥｖとして変数ｎＨａｒｍの値、そのデータＩＴｉｍｅとして変数ＩＴＰｒｏｇの値、そのデータＩＴｅｒｍとしてＭｉｄｉＥｖｅｎｔ［ｍｅ］．ＩＧａｔｅの値に変数ＩＴＰｒｏｇの値を加算した値、をそれぞれ設定する。変数ｎＨａｒｍの値で指定されるノートデータＮｏｔｅでは、データｐＥｖとして変数ｍｅの値、データｐｉｔｃｈとしてＭｉｄｉＥｖｅｎｔ［ｍｅ］．Ｐｉｔｃｈの値、データｐｒｅｖとして変数ｎＴｍｐの値、それぞれ設定する。変数ｎＴｍｐの値で指定されるノートデータＮｏｔｅのデータｎｅｘｔとしては変数ｎＨａｒｍの値を設定する。それらデータの設定（対応する領域内へのデータの格納）を行い、更に変数ｎＴｍｐに変数ｎＨａｒｍの値を代入した後はステップＳＫ５に移行する。
【００８５】
ステップＳＫ５では、変数ＩＴＰｒｏｇの値からＭｉｄｉＥｖｅｎｔ［ＭｉｄｉＥｖｅｎｔ［ｍｅ］．ｐＮｅｘｔ］．ＩＴｉｍｅの値を引いた値の絶対値が定数ＮＯＴＥＯＮＯＦＦＳＥＴ未満か否か判定する。定数ＮＯＴＥＯＮＯＦＦＳＥＴは和音の構成音間で許容範囲とする発音開始ティックの時間間隔として定めたものである。このことから、その絶対値が示す時間間隔が許容範囲内であった場合、判定はＹＥＳとなってステップＳＫ６に移行し、そうでない場合には、判定はＮＯとなり、ステップＳＫ１１で変数ｍｅにＭｉｄｉＥｖｅｎｔ［ｍｅ］．ｐＮｅｘｔの値を代入してから上記ステップＳＫ２に戻る。
【００８６】
ステップＳＫ６では、変数ｍｅＨａｒｍに、ＭｉｄｉＥｖｅｎｔ［ｍｅ］．ｐＮｅｘｔの値を代入し、変数ｎＨａｒｍに、ノートデータＮｏｔｅを格納できる空きエリアのインデックス値を代入する。その後に移行するステップＳＫ７では、変数Ｔに、ＭｉｄｉＥｖｅｎｔ［ｍｅＨａｒｍ］．ＩＴｉｍｅの値にＭｉｄｉＥｖｅｎｔ［ｍｅＨａｒｍ］．ＩＧａｔｅの値を加算した値を代入し、その変数Ｔの値がＮｏｔｅＧｒｏｕｐ［ｎｇｒ］．ＩＴｅｒｍの値より大きければ、そのＮｏｔｅＧｒｏｕｐ［ｎｇｒ］．ＩＴｅｒｍとして変数Ｔの値を設定する。ステップＳＫ８にはその後に移行する。
【００８７】
ステップＳＫ８では、変数ｎＨａｒｍの値で指定されるノートデータＮｏｔｅにおいて、データｐＥｖとして変数ｍｅの値、データｐｉｔｃｈとしてＭｉｄｉＥｖｅｎｔ［ｍｅ］．Ｐｉｔｃｈの値、データｐｒｅｖとして変数ｎＴｍｐの値、をそれぞれ設定する。変数ｎＴｍｐの値で指定されるノートデータＮｏｔｅのデータｎｅｘｔとしては変数ｎＨａｒｍの値を設定する。続くステップＳＫ９では、ＮｏｔｅＧｒｏｕｐ［ｎｇｒ］．ＮｏｔｅＥｖとして変数ｍｅＨａｒｍの値を追加し、データＮｏｔｅＥｖを対応する音符のピッチ順にソートする。その後は、ステップＳＫ１０に移行して、変数ｍｅに変数ｍｅＨａｒｍの値、変数ｎｔｍｐに変数ｎＨａｒｍの値をそれぞれ代入した後、上記ステップＳＫ５に戻る。それにより、和音の構成音と見なす複数の音符は１つの時系列データＮｏｔｅＧｒｏｕｐにより管理する。
【００８８】
図２１は、図１９に示す構造解析処理内でステップＳＪ２として実行されるフレーズ分割処理のフローチャートである。次に図２１を参照して、その分割処理について詳細に説明する。
【００８９】
先ず、ステップＳＬ１では、変数ｎｇＲｅｆに時系列データＮｏｔｅＧｒｏｕｐのなかで先頭のものを指定するインデックス値を代入する。続くステップＳＬ２では、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＬ３に移行する。
【００９０】
ステップＳＬ３では、変数ｎｇＳｒｃに、変数ｎｇＲｅｆの値より規定数先の時系列データＮｏｔｅＧｒｏｕｐのデータｎｅｘｔの値を代入する。次のステップＳＬ４では、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ステップＳＬ９で変数ｎｇＲｅｆに、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆ］．ｎｅｘｔの値を代入してから上記ステップＳＬ２に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＬ５に移行する。上記規定数とは定数ＭａｒｋｉｎｇＮｏｔｅｓである。
【００９１】
ステップＳＬ５では、変数ｉＭａｒｋＣｎｔに０を代入する。続くステップＳＬ６では、先頭位置検索処理を実行する。その後に移行するステップＳＬ７では、変数ｉＭａｒｋＣｎｔの値が０でないか否か判定する。その値が０であった場合、判定はＮＯとなってステップＳＬ９に移行する。そうでない場合には、判定はＹＥＳとなり、ステップＳＬ８でグループ化処理を実行した後、上記ステップＳＬ２に戻る。
【００９２】
図２２は、上記ステップＳＬ６として実行される先頭位置検索処理のフローチャートである。次にその検索処理について、図２２に示すそのフローチャートを参照して詳細に説明する。
【００９３】
先ず、ステップＳＭ１では、ＮｏｔｅＧｒｏｕｐ「ｎｇＳｒｃ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＹＥＳとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＭ２に移行する。
【００９４】
ステップＳＭ２では、変数ｊｄｇに論理値ＴＲＵＥを代入する。続くステップＳＭ３では、変数ｉに定数ＭａｒｋｉｎｇＮｏｔｅｓを代入する。その次のステップＳＭ４では、変数ｎｇＲｅｆｔｍｐに変数ｎｇＲｅｆの値、変数ｎｇＳｒｃｔｍｐに変数ｎｇＳｒｃの値をそれぞれ代入する。その代入後に移行するステップＳＭ５では、変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｉの値が０より大きいか否か判定する。変数ｊｄｇの値がＴＲＵＥでないか、或いは変数ｉの値が０以下であった場合、判定はＮＯとなってステップＳＭ１６に移行する。そうでない場合には、つまり変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｉの値が０より大きい場合には、判定はＹＥＳとなってステップＳＭ６に移行する。
【００９５】
ステップＳＭ６では、ＮｏｔｅＧｒｏｕｐ「ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ステップＳＭ１５で変数ｊｄｇにＦＡＬＳＥを代入し、更にステップＳＭ１４で変数ｉの値をデクリメントした後、上記ステップＳＭ５に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＭ７に移行する。
【００９６】
ステップＳＭ７では、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ＮｏｔｅＥｖの値を変数ＲｅｆＮｏｔｅｔｍｐに代入し、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ＮｏｔｅＥｖの値を変数ＳｒｃＮｏｔｅｔｍｐに代入する。その後に移行するステップＳＭ８では、変数ｎｇＲｅｆｔｍｐの値で指定される時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが無いか（図中「ＥｖＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］≠ＮＵＬＬ」と表記）、或いは変数ｎｇＳｒｃｔｍｐの値で指定される時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが無いか（図中「ＥｖＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］≠ＮＵＬＬ」と表記）が無いか否か判定する。それらのうちの少なくとも一方の時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが存在しなかった場合、判定はＮＯとなり、ステップＳＭ１１に移行する。そうでない場合には、つまりそれの両方に他のデータＮｏｔｅＥｖが存在している場合には、判定はＹＥＳとなってステップＳＭ９に移行する。
【００９７】
ステップＳＭ９では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅ［ＲｅｆＮｏｔｅｔｍｐ］．ｐｉｔｃｈの値がＮｏｔｅ［ＳｒｃＮｏｔｅｔｍｐ］．ｐｉｔｃｈの値と等しければ変数ｊｄｇにＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。次のステップＳＭ１０では、Ｎｏｔｅ［ＲｅｆＮｏｔｅｔｍｐ］．ｎｅｘｔの値を変数ＲｅｆＮｏｔｅｔｍｐ、Ｎｏｔｅ［ＳｒｃＮｏｔｅｔｍｐ］．ｎｅｘｔの値を変数ＳｒｃＮｏｔｅｔｍｐにそれぞれ代入する。その代入後は上記ステップＳＭ８に戻る。それにより、データＮｏｔｅＥｖが複数、存在している時系列データＮｏｔｅＧｒｏｕｐ間では、各データＮｏｔｅＥｖ毎にその値で指定される音符間のピッチのチェックを行う。
【００９８】
一方、ステップＳＭ１１では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆ］．ＩＴｉｍｅの値を引いた値に対し、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃ］．ＩＴｉｍｅの値を引いた値を減算して得られる値の絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅ未満であれば変数ｊｄｇにＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。次のステップＳＭ１２では、変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｎｇＲｅｆｔｍｐ、ｎｇＳｒｃｔｍｐの各値で指定される時系列データＮｏｔｅＧｒｏｕｐで示されるゲートタイムの比を１から引いた値の絶対値が定数ＧａｔｅＴｉｍｅＲａｔｉｏ未満であれば変数ｊｄｇにＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。ステップＳＭ１３にはその後に移行して、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ｎｅｘｔの値を変数ｎｇＲｅｆｔｍｐ、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値を変数ｎｇＳｒｃｔｍｐ、にそれぞれ代入する。ステップＳＭ１４にはその代入後に移行する。
【００９９】
上記ステップＳＭ５の判定がＮＯとなって移行するステップＳＭ１６では、変数ｊｄｇの値がＴＲＵＥか否か判定する。その値がＴＲＵＥであった場合、判定はＹＥＳとなってステップＳＭ１７に移行する。そうでない場合には、判定ＮＯとなり、ステップＳＭ２２で変数ｎｇＳｒｃに、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃ］．ｎｅｘｔの値を代入した後、上記ステップＳＭ１に戻る。
【０１００】
ステップＳＭ１７では、変数ｉＭａｒｋＣｎｔの値が０か否か判定する。その値が０であった場合、判定はＹＥＳとなり、ステップＳＭ１８でフレーズデータ登録処理を実行し、次のステップＳＭ１９で変数ｉＭａｒｋＣｎｔの値をインクリメントし、その次のステップＳＭ２０でフレーズデータ登録処理を実行し、更にステップＳＭ２１で変数ｎｇＳｒｃに、変数ｎｇＳｒｃの値より規定数先の時系列データＮｏｔｅＧｒｏｕｐのデータｎｅ
ｘｔの値を代入する。その後は上記ステップＳＭ１に戻る。
【０１０１】
上記フレーズデータ登録処理は、ステップＳＭ１８では大元のフレーズを対象にして、ステップＳＭ２０ではそれと関連付けるフレーズを対象にして行われる。次にその登録処理について、図２３に示すそのフローチャートを参照して詳細に説明する。その登録処理を実行することにより、図１８（ａ）に示すフレーズデータＰｈｒａｓｅ、図１８（ｂ）に示すフレーズブロックデータＰｈＢｌｏｃｋが生成される。
【０１０２】
先ず、ステップＳＮ１では、フレーズデータＰｈｒａｓｅのなかで先頭に位置しているもののインデックス値を変数ｐｈに代入する。次のステップＳＮ２では、変数ｐｈｎｅｗに、フレーズデータＰｈｒａｓｅが格納されていないエリア（空バッファ）のインデックス値、変数ｐｈｂｎｅｗに、フレーズブロックデータＰｈＢｌｏｃｋが格納されていないエリア（空バッファ）のインデックス値をそれぞれ代入する。その後はステップＳＮ３に移行する。
【０１０３】
ステップＳＮ３では、変数ｉＭａｒｋＣｎｔの値が０か否か判定する。その値が０でなかった場合、判定はＮＯとなってステップＳＮ９に移行する。そうでない場合には、判定はＹＥＳとなってステップＳＮ４に移行する。
【０１０４】
ステップＳＮ４では、変数ｎｇｉｎｓに変数ｎｇＲｅｆの値、変数ｎｇＴｅｒｍに変数ｎｇＲｅｆｔｍｐの値、をそれぞれ代入する。続くステップＳＮ５では、Ｐｈｒａｓｅ［ｐｂｎｅｗ］．ＩＴｉｍｅとしてＮｏｔｅＧｒｏｕｐ［ｎｇｉｎｓ］．ＩＴｉｍｅの値、Ｐｈｒａｓｅ［ｐｈｎｅｗ］．ＩＴｅｒｍとしてＮｏｔｅＧｒｏｕｐ［ｎｇｉｎｓ］．ＩＴｅｒｍの値、Ｐｈｒａｓｅ［ｐｈｎｅｗ］．ｉＴｙｐｅとして０、Ｐｈｒａｓｅ［ｐｈｎｅｗ］．ｐＦｉｒｓｔとして変数ｎｇｉｎｓの値、Ｐｈｒａｓｅ［ｐｈｎｅｗ］．ｐＥｎｄとして変数ｎｇＴｅｒｍの値、をそれぞれ設定し、変数ｐｈｂに変数ｐｈｂｎｅｗの値を代入する。ステップＳＮ６には、その後に移行する。
【０１０５】
ステップＳＮ６では、Ｐｈｒａｓｅ［Ｐｈ］．ｎｅｘｔの値がＮＵＬＬでなく、且つＰｈｒａｓｅ［Ｐｈ］．ＩＴｉｍｅの値がＰｈｒａｓｅ［ｎｇｉｎｓ］．ＩＴｉｍｅの値より大きいか否か判定する。Ｐｈｒａｓｅ［Ｐｈ］．ｎｅｘｔの値がＮＵＬＬか、或いはＰｈｒａｓｅ［Ｐｈ］．ＩＴｉｍｅの値がＰｈｒａｓｅ［ｎｇｉｎｓ］．ＩＴｉｍｅの値以下であった場合、判定はＮＯとなり、ステップＳＮ７で変数ｐｈにＰｈｒａｓｅ［ｐｈ］．ｎｅｘｔの値を代入した後、そのステップＳＮ６に戻る。そうでない場合には、つまりＰｈｒａｓｅ［Ｐｈ］．ｎｅｘｔの値がＮＵＬＬでなく、且つＰｈｒａｓｅ［Ｐｈ］．ＩＴｉｍｅの値がＰｈｒａｓｅ［ｎｇｉｎｓ］．ＩＴｉｍｅの値より大きい場合には、判定はＮＯとなり、ステップＳＮ８で変数ｐｈｎｅｗの値で指定されるフレーズデータＰｈｒａｓｅを変数ｐｈの値で指定されるフレーズデータＰｈｒａｓｅより後になるように挿入させる形で格納した後、一連の処理を終了する。
【０１０６】
上記ステップＳＮ３の判定がＮＯとなって移行するステップＳＮ９では、ＰｈＢｌｏｃｋ［ｐｈｂｎｅｗ］．ｐｒｅｖとして変数ｐｈｂの値、ＰｈＢｌｏｃｋ［ｐｈｂ］．ｎｅｘｔとして変数ｐｈｂｎｅｗの値、をそれぞれ設定し、変数ｐｈｂに変数ｐｈｂｎｅｗの値を代入し、ＰｈＢｌｏｃｋ［ｐｈｂ］．ｐＦｉｒｓｔとして変数ｐｈｒｅｆの値を設定する。その後は、ステップＳＮ１０で変数ｎｇｉｎｓに変数ｎｇＳｒｃ、変数ｎｇＴｅｒｍに変数ｎｇＳｒｃｔｍｐの値をそれぞれ代入してからステップＳＮ５に移行する。
【０１０７】
図２４は、図２１に示すグループ分割処理内でステップＳＬ８として実行されるグループ化処理のフローチャートである。次にそのグループ化処理について、図２４に示すそのフローチャートを参照して詳細に説明する。
【０１０８】
先ず、ステップＳＰ１では、変数ｎｇＲｅｆｔｍｐに、Ｐｈｒａｓｅ［ｐｈＲｅｆ］．ｐＥｎｄの値、変数ｐｈＳｒｃに変数ｐｈＲｅｆの値をそれぞれ代入する。次のステップＳＰ２では、Ｐｈｒａｓｅ［ｐｈｓｒｃ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬだった場合、判定はＮＯとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＰ３に移行する。
【０１０９】
ステップＳＰ３では、変数ｐｈＳｒｃにＰｈｒａｓｅ［ｐｈＲｅｆ］．ｎｅｘｔの値、変数ｎｇＳｒｃにＰｈｒａｓｅ［ｐｈＳｒｃ］．ｐＦｉｒｓｔの値、変数ｎｇＳｒｃｔｍｐにＰｈｒａｓｅ［ｐｈＳｒｃ］．ｐＥｎｄの値、変数ｊｄｇにＴＲＵＥ、をそれぞれ代入する。その代入後に移行するステップＳＰ４では、変数ｊｄｇの値がＴＲＵＥであり、且つ、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。変数ｊｄｇの値がＴＲＵＥでないか、或いはＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値がＮＵＬＬであった場合、判定はＮＯとなってステップＳＰ１６に移行し、図９に示すフレーズデータへのグループ登録処理と同様にしてフレーズデータＰｈｒａｓｅの更新を行った後、上記ステップＳＰ２に戻る。そうでない場合には、つまり変数ｊｄｇの値がＴＲＵＥであり、且つ、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値がＮＵＬＬでない場合には、判定はＹＥＳとなってステップＳＰ５に移行する。
【０１１０】
ステップＳＰ５〜ＳＰ１０では、図２２に示すステップＳＭ７〜ＳＭ１２と同様の処理が行われる。ステップＳＰ１０の処理の実行後に移行するステップＳＰ１１では、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ＩＴｉｍｅの値が、Ｐｈｒａｓｅ［Ｐｈｒａｓｅ［ｐｈＳｒｃ］．ｎｅｘｔ］．ＩＴｉｍｅの値以上か否か判定する。前者が後者以上であった場合、判定はＹＥＳとなり、ステップＳＰ１２でＰｈｒａｓｅ［Ｐｈｒａｓｅ［ｐｈＳｒｃ］．ｎｅｘｔ］．ＩＴｙｐｅとして２を設定した後、ステップＳＰ１３に移行する。そうでない場合には、判定はＮＯとなってそのステップＳＰ１３に移行する。
【０１１１】
ステップＳＰ１３では、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ＩＴｉｍｅの値が、Ｐｈｒａｓｅ［ｐｈＳｒｃ］．ＩＴｉｍｅの値以上か否か判定する。前者が後者以上であった場合、判定はＹＥＳとなり、ステップＳＰ１４でＰｈｒａｓｅ［ｐｈＳｒｃ］．ＩＴｙｐｅとして２を設定し、変数ｐｈＳｒｃに、Ｐｈｒａｓｅ［ｐｈＳｒｃ］．ｎｅｘｔの値を代入する。そうでない場合には、判定はＮＯとなってステップＳＰ１５に移行する。そのステップＳＰ１５では、変数ｎｇＲｅｆｔｍｐにＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ｎｅｘｔの値、変数ｎｇＳｒｃｔｍｐにＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値、をそれぞれ代入する。その代入後は上記ステップＳＰ４に戻る。
＜第５の実施の形態＞
上記第１〜第４の実施の形態では、類似性に着目してフレーズ分割を行っている。これに対し、第５の実施の形態は、分割時とは異なる視点で、分割したフレーズ間の関連性（類似性）を更に解析するようにしたものである。ここでは、リズム、及び転調の２つに着目して関連性の解析を行うようにしている。そのような解析を行い、その結果を図２８に示すようにして提示することにより、楽曲構造をより具体的、且つ容易に理解できるようになる。
【０１１２】
第５の実施の形態における楽曲構造解析装置の構成は、他の実施の形態と同様に、基本的に第１の実施の形態におけるそれと同じである。このことから、第１の実施の形態で付した符号をそのまま用いて説明を行うことにする。
【０１１３】
第５の実施の形態では、上記第４の実施の形態で扱うデータの他に、フレーズ関連性データを更に扱っている。その関連性データは、フレーズ間の関連性の解析結果を管理するために用意したものである。
【０１１４】
図２５は、フレーズ管理用データの構成を説明する図である。図２５（ａ）はフレーズブロックデータ、図２５（ｂ）はフレーズ関連性データのデータ構成をそれぞれ示している。
【０１１５】
図２５（ａ）に示すように、第５の実施の形態では、フレーズブロックデータＰｈＢｌｏｃｋは、第４の実施の形態からデータｐＲｅｌａｔｉｏｎａｌが追加されている。そのデータｐＲｅｌａｔｉｏｎａｌは、関連性の解析を行った最初のフレーズデータＰｈｒａｓｅのインデックス値である。データｐＦｉｒｓｔとしては、対応するフレーズデータＰｈｒａｓｅのインデックス値を格納するようになっている。
【０１１６】
フレーズ関連性データは図２５（ｂ）に示すように、関連性の解析を行った種類を示すデータｉＴｙｐｅ（リズムは１、転調は２）、解析結果である一致性を示すデータｉＲａｔｉｏ、対応する、関連性を解析したフレーズのフレーズブロックデータＰｈＢｌｏｃｋのインデックス値であるデータＲｅｌａｔｉｏｎａｌＢｌｏｃｋ、次の関連性データＰｈＲｅｌａｔｉｏｎのインデックス値であるデータｎｅｘｔ、前の関連性データＰｈＲｅｌａｔｉｏｎのインデックス値であるｐｒｅｖ、の各データから構成される。
【０１１７】
上記リズム、及び転調の関連性の解析は、ぞれぞれ図２６に示すリズム解析処理、図２７に示す転調解析処理を実行することで行われる。それらの解析処理は、例えば図１９に示す構造解析処理内でステップＳＪ２のフレーズ分割処理の実行後に実行するようになっている。本実施の形態では、特に詳細な説明は省略するが、それらのうちの一方のみを選択的に実行するようにしている。以降、それら解析処理について、図２６、及び図２７を参照して詳細に説明する。
【０１１８】
始めに、図２６を参照してリズム解析処理について詳細に説明する。
先ず、ステップＳＱ１では、変数の初期化を行う。その初期化により、各データのなかで着目するものを管理するための変数には、そのデータのなかで先頭に位置するもののインデックス値が代入される。その後に移行するステップＳＱ２では、ＰｈＢｌｏｃｋ［ｐｈｂＲｅｆ］．ｎｅｘｔの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ここで一連の処理を終了する。そうでない場合には、判定はＹＥＳとなってステップＳＱ３に移行する。
【０１１９】
ステップＳＱ３では、変数ｐｈｂＳｒｃに、Ｐｈｒａｓｅ［ｐｈｂＲｅｆ］．ｎｅｘｔの値を代入する。その次に移行するステップＳＱ４では、変数ｐｈｂＳｒｃの値がＮＵＬＬでないか否か判定する。その値がＮＵＬＬであった場合、判定はＮＯとなり、ステップＳＱ１７でＰｈＢｌｏｃｋ［ｐｈｂＲｅｆ］．ｎｅｘｔの値を変数ｐｈｂＲｅｆに代入してから上記ステップＳＱ２に戻る。そうでない場合には、判定はＹＥＳとなってステップＳＱ５に移行する。
【０１２０】
ステップＳＱ５では、Ｐｈｒａｓｅ［ＰｈＢｌｏｃｋ［ｐｈｂＲｅｆ］．ｐＦｉｒｓｔ］．ｐＦｉｒｓｔの値（変数ｐｈｒＲｅｆの値で対応するフレーズブロックデータＰｈＢｌｏｃｋが指定されるフレーズの先頭位置に存在する時系列データＮｏｔｅＧｒｏｕｐのインデックス値）を変数ｎｇＲｅｆに、Ｐｈｒａｓｅ［ＰｈＢｌｏｃｋ［ｐｈｂＳｒｃ］．ｐＦｉｒｓｔ］．ｐＦｉｒｓｔの値を変数ｎｇＳｒｃに、それぞれ代入する。続くステップＳＱ６では、変数ｎｇＲｅｆの値を変数ｎｇＲｅｆｔｍｐに、変数ｎｇＳｒｃの値を変数ｎｇＳｒｃｔｍｐに、それぞれ代入し、変数ｉＯｒｇＣｎｔ、及びｉＨｉｔＣｎｔにそれぞれ０を代入する。その後は、ステップＳＱ７で変数ｉＯｒｇＣｎｔの値をインクリメントし、変数ｊｄｇにＴＲＵＥを代入してからステップＳＱ８に移行する。
【０１２１】
ステップＳＱ８では、変数ｊｄｇの値がＴＲＵＥであり、且つＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ＩＴＩＭＥの値からＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆ］．ＩＴｉｍｅの値を引いた値に対し、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ＩＴｉｍｅの値からＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃ］．ＩＴｉｍｅの値を引いた値を減算して得られる値の絶対値が定数ＳｔａｒｔＴｉｃｋＲａｎｇｅ未満であれば変数ｊｄｇにＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。続くステップＳＱ９では、変数ｊｄｇの値がＴＲＵＥであり、且つ変数ｎｇＲｅｆｔｍｐ、ｎｇＳｒｃｔｍｐの各値で指定される時系列データＮｏｔｅＧｒｏｕｐで示されるゲートタイムの比を１から引いた値の絶対値が定数ＧａｔｅＴｉｍｅＲａｔｉｏ未満であれば変数ｊｄｇにＴＲＵＥを代入する。そうでなければＦＡＬＳＥを代入する。その後はステップＳＱ１０に移行する。
【０１２２】
ステップＳＱ１０では、変数ｊｄｇの値がＴＲＵＥか否か判定する。その値がＴＲＵＥであった場合、判定はＹＥＳとなり、ステップＳＱ１１で変数ｉＨｉｔＣｎｔの値をインクリメントした後、ステップＳＱ１２に移行する。そうでない場合には、判定はＮＯとなってそのステップＳＱ１２に移行する。
【０１２３】
ステップＳＱ１２では、Ｐｈｒａｓｅ［ＰｈＢｌｏｃｋ［ｐｈｂＲｅｆ］．ｐＦｉｒｓｔ］．ｐＥｎｄの値が変数ｎｇＲｅｆｔｍｐの値と等しくなく、且つＰｈｒａｓｅ［ＰｈＢｌｏｃｋ［ｐｈｂＳｒｃ］．ｐＦｉｒｓｔ］．ｐＥｎｄの値が変数ｎｇＳｒｃｔｍｐの値と等しいか否か判定する。それらが共に等しくない場合、判定はＹＥＳとなり、ステップＳＱ１３でＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆｔｍｐ］．ｎｅｘｔの値を変数ｎｇＲｅｆｔｍｐに、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃｔｍｐ］．ｎｅｘｔの値を変数ｎｇＳｒｃｔｍｐに、それぞれ代入した後、上記ステップＳＱ７に戻る。それにより、フレーズ間での対比を継続して行う。そうでない場合には、つまり少なくとも何れか一方が等しい場合には、判定はＮＯとなってステップＳＱ１４に移行する。
【０１２４】
ステップＳＱ１４では、変数ｐｈｒＲに、フレーズ関連性データＰｈＢｌｏｃｋが格納されていないエリアのインデックス値を代入し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．ｉＴｙｐｅとして１を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．ＲｅｌａｔｉｏｎａｌＢｌｏｃｋとして変数ｐｈｂＳｒｃの値を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．Ｒａｔｉｏとして、変数ｉＨｉｔＣｎｔの値を変数ｉＯｒｇＣｎｔの値で割った値に１００を掛けて得られる値を設定する。その後はステップＳＱ１５に移行する。
【０１２５】
ステップＳＱ１５では、変数ｐｈｒＳに、フレーズ関連性データＰｈＢｌｏｃｋが格納されていないエリアのインデックス値を代入し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．ｉＴｙｐｅとして１を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．ＲｅｌａｔｉｏｎａｌＢｌｏｃｋとして変数ｐｈｂＲｅｆの値を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．Ｒａｔｉｏとして、変数ｉＨｉｔＣｎｔの値を変数ｉＯｒｇＣｎｔの値で割った値に１００を掛けて得られる値を設定する。その後はステップＳＱ１６に移行して、ＰｈＢｌｏｃｋ［ｐｈｂＳｒｃ］．ｎｅｘｔの値を変数ｐｈｂＳｒｃに代入する。上記ステップＳＱ４にはその後に移行する。
【０１２６】
次に、図２７を参照して転調解析処理について詳細に説明する。
図２７では、図２６に示すリズム解析処理と処理内容が同じ、或いは基本的に同じものには同一の符号を付してある。ここでは、図２６から異なる部分に着目して説明することとする。
【０１２７】
図２７の転調解析処理では、ステップＳＱ１０の判定がＹＥＳとなるとステップＳＲ１に移行する。そのステップＳＲ１では、ＮｏｔｅＧｒｏｕｐ［ｎｇＲｅｆ］．ＮｏｔｅＥｖの値を変数ＲｅｆＮｏｔｅｔｍｐに代入し、ＮｏｔｅＧｒｏｕｐ［ｎｇＳｒｃ］．ＮｏｔｅＥｖの値を変数ＳｒｃＮｏｔｅｔｍｐに代入する。次のステップＳＲ２では、変数ｎｇＲｅｆの値で指定される時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが無いか（図中「Ｎｏｔｅ［ＲｅｆＮｏｔｅｔｍｐ］≠ＮＵＬＬ」と表記）、或いは変数ｎｇＳｒｃの値で指定される時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが無いか（図中「Ｎｏｔｅ［ＳｒｃＮｏｔｅｔｍｐ］≠ＮＵＬＬ」と表記）が無いか否か判定する。それらのうちの少なくとも一方の時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが存在しなかった場合、判定はＮＯとなり、ステップＳＱ１２に移行する。そうでない場合には、つまりそれの両方に他のデータＮｏｔｅＥｖが存在している場合には、判定はＹＥＳとなってステップＳＲ３に移行する。
【０１２８】
ステップＳＲ３では、Ｎｏｔｅ［ＲｅｆＮｏｔｅｔｍｐ］．ｐｉｔｃｈの値からＮｏｔｅ［ＳｒｃＮｏｔｅｔｍｐ］．ｐｉｔｃｈの値を引いた値を変数ｉＤｉｆに代入し、配列変数ｉＨｉｔＣｎｔの１２から変数ｉＤｉｆの値を引いた値で指定される要素ｉＨｉｔＣｎｔ［１２−ｉＤｉｆ］の値をインクリメントする。続くステップＳＲ４では、変数ｎｇＲｅｆの値で指定される時系列データＮｏｔｅＧｒｏｕｐに他のデータＮｏｔｅＥｖが存在すればＮｏｔｅ［ＲｅｆＮｏｔｅｔｍｐ］．ｎｅｘｔの値を変数ＲｅｆＮｏｔｅｔｍｐ、同様にＮｏｔｅ［ＳｒｃＮｏｔｅｔｍｐ］．ｎｅｘｔの値を変数ＳｒｃＮｏｔｅｔｍｐにそれぞれ代入する。その代入後は上記ステップＳＲ２に戻る。
【０１２９】
転調解析処理では、ステップＳＱ１２の判定がＮＯとなるとステップＳＲ５に移行し、配列変数ｉＨｉｔｍａｘの要素のなかで値が最も大きい要素を指定する値を変数ｉＨｉｔＭａｘに代入する。次のステップＳＲ６では、変数ｐｈｒＲに、フレーズ関連性データＰｈＢｌｏｃｋが格納されていないエリアのインデックス値を代入し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．ｉＴｙｐｅとして２を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．ＲｅｌａｔｉｏｎａｌＢｌｏｃｋとして変数ｐｈｂＳｒｃの値を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＲ］．Ｒａｔｉｏとして、変数ｉＨｉｔＣｎｔの値を変数ｉＯｒｇＣｎｔの値で割った値に１００を掛けて得られる値を設定する。その後はステップＳＲ７に移行する。
【０１３０】
ステップＳＲ７では、変数ｐｈｒＳに、フレーズ関連性データＰｈＢｌｏｃｋが格納されていないエリアのインデックス値を代入し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．ｉＴｙｐｅとして２を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．ＲｅｌａｔｉｏｎａｌＢｌｏｃｋとして変数ｐｈｂＲｅｆの値を設定し、ＰｈＲｅｌａｔｉｏｎ［ｐｈｒＳ］．Ｒａｔｉｏとして、変数ｉＨｉｔＣｎｔの値を変数ｉＯｒｇＣｎｔの値で割った値に１００を掛けて得られる値を設定する。その後はステップＳＱ１６に移行する。
【０１３１】
なお、本実施の形態では、関連性としてリズム、及び転調に着目した解析を行うようにしているが、それら以外の関連性（類似性）に着目した解析を行うようにしても良い。着目する関連性の異なる複数の解析を一度に行えるようにしても良い。また、特許文献１に記載された技術での構造解析を併せて行い、その結果を反映させた形で構造解析を行うようにしても良い。
【０１３２】
上述したような楽曲構造解析装置を実現させるようなプログラムは、ＣＤ−ＲＯＭ、ＤＶＤ、或いは着脱自在なフラッシュメモリ等の記録媒体に記録させて配布しても良い。公衆網等の通信ネットワークを介して、そのプログラムの一部、若しくは全部を配信するようにしても良い。そのようにした場合には、ユーザーはプログラムを取得してデータ処理装置にロードすることにより、その装置に本発明を適用させることができる。このことから、記録媒体は、プログラムを配信する装置がアクセスできるものであっても良い。
【図面の簡単な説明】
【０１３３】
【図１】第１の実施の形態による楽曲構造解析装置の構成を説明する図である。
【図２】楽曲データの構成を説明する図である。
【図３】フレーズデータの構成を説明する図である。
【図４】構造解析処理のフローチャートである。
【図５】フレーズ分割処理のフローチャートである。
【図６】先端位置検索処理のフローチャートである。
【図７】フレーズデータの登録処理のフローチャートである。
【図８】グループ化処理のフローチャートである。
【図９】フレーズデータへのグループ登録処理のフローチャートである。
【図１０】楽曲の分割方法を説明する図である。
【図１１】グループ化処理のフローチャートである（第２の実施の形態：抜粋）。
【図１２】フレーズ分割処理のフローチャートである（第３の実施の形態）。
【図１３】端数処理のフローチャートである。
【図１４】楽曲の構造解析結果の表示例を説明する図である（その１）。
【図１５】楽曲データの構成を説明する図である（第４の実施の形態）。
【図１６】時系列データの構成を説明する図である。
【図１７】ノートデータの構成を説明する図である。
【図１８】フレーズ管理用データの構成を説明する図である。
【図１９】構造解析処理のフローチャートである（第４の実施の形態）。
【図２０】時系列データの生成処理のフローチャートである。
【図２１】フレーズ分割処理のフローチャートである（第４の実施の形態）。
【図２２】先端位置検索処理のフローチャートである（第４の実施の形態）。
【図２３】フレーズデータ登録処理のフローチャートである（第４の実施の形態）。
【図２４】グループ化処理のフローチャートである（第４の実施の形態）。
【図２５】フレーズ管理用データの構成を説明する図である（第５の実施の形態）。
【図２６】リズム解析処理のフローチャートである（第５の実施の形態）。
【図２７】転調解析処理のフローチャートである（第５の実施の形態）。
【図２８】楽曲の構造解析結果の表示例を説明する図である（その２）。
【符号の説明】
【０１３４】
１０１    ＣＰＵ
１０２    ＲＡＭ
１０３    ＲＯＭ
１０４    入力装置
１０５    表示装置
１０６    インターフェース（Ｉ／Ｆ）
【図１】
2006085090.tif 000003
【図２】
2006085090.tif 000004
【図３】
2006085090.tif 000005
【図４】
2006085090.tif 000006
【図５】
2006085090.tif 000007
【図６】
2006085090.tif 000008
【図７】
2006085090.tif 000009
【図８】
2006085090.tif 000010
【図９】
2006085090.tif 000011
【図１０】
2006085090.tif 000012
【図１１】
2006085090.tif 000013
【図１２】
2006085090.tif 000014
【図１３】
2006085090.tif 000015
【図１４】
2006085090.tif 000016
【図１５】
2006085090.tif 000017
【図１６】
2006085090.tif 000018
【図１７】
2006085090.tif 000019
【図１８】
2006085090.tif 000020
【図１９】
2006085090.tif 000021
【図２０】
2006085090.tif 000022
【図２１】
2006085090.tif 000023
【図２２】
2006085090.tif 000024
【図２３】
2006085090.tif 000025
【図２４】
2006085090.tif 000026
【図２５】
2006085090.tif 000027
【図２６】
2006085090.tif 000028
【図２７】
2006085090.tif 000029
【図２８】
2006085090.tif 000030