« 2008年4月 | トップページ | 2008年6月 »

MikuMikuVoice

音声ファイル(WAV)を入力してVSQファイルを出力し、初音ミクに歌わせるツールが現れました。その名はMikuMikuVoice。かの MikuMikuDance の作者である樋口さんの作品です。
http://www.geocities.jp/higuchuu4/index.htm

 歌詞(Lyric)はどう入力するかというと、時間範囲を指定して発音を手入力ですが、その指定時間範囲をループ再生させて確認できます。
 歌詞部分をどうするかというのは、WAV入力によるVSQ生成にとって大きな課題だったのですが、自動認識などで開発工数を膨らまさず、かつユーザーが歌詞部分を入力しやすいように、うまく処理していますね。

 既に「自分で歌って比較してみた」という方がおられましたので、紹介します。

VEL(ベロシティ)は固定値ですが、PIT(音高)とDYN(音量)は元音声をちゃんと反映させてあります。なおかつ note までちゃんと反映させているのが秀逸です。
これは単なるボイスチェンジャではない何かを感じます。これだけで何かうまい応用ができないものでしょうか。

| | コメント (0) | トラックバック (0)

ぼかんないんです><&ぼかりす

 「ぼかんないんです><」によって作成されたyuukiss氏の新作がアップロードされていたので、ご紹介します。


 音声の美しさもさることながら、Vocaloid Editor 上のPITとDYN の曲線の美しさに魅入ってしまいました。

 さて、昨日は神戸の学会での Vocalistener の発表のレポートが2ちゃんねるにレポートされていました。技術的要素は ①目標歌唱に近づけるため、合成歌唱の音高(PIT)パラメーター/音量(DYN)パラメーターを反復計算する事と、②目標歌唱と歌詞の時間的対応付けを自動化する事、及び③歌唱力を補正して歌をうまく聞こえるよう補正する事、以上3点です。

 yuukiss 氏がおこなったのは、①合成歌唱の音高パラメーター(PIT)/音量(DYN)パラメーター反復計算する事の代わりに、目標歌唱の波形を参照しながら手動でオートメーション描画した事と推定されます。詳しくは浜崎あゆみ「Dearest」を入手して波形を調査してみたく思います。波形調査にあたっては、zhuo さんの Ripples を使わせていただくと思います。便利な解析ツールを提供いただいた zhuo さんに感謝いたします。
 余談ですが、現在は浜崎あゆみ「Dearest」は在庫切れ欠品だそうで、やむを得ず Amazon で中古品を手配しているところです。

| | コメント (0) | トラックバック (0)

特開2002-221978の帰趨#3

 

特開2002-221978「ボーカルデータ生成装置、ボーカルデータ生成方法および歌唱音合成装置」とは、初音ミクに実装されていると思われる発明で、母音のタイミングを音符のタイミングと一致させる為に、子音を先行して発音させるものです。

【課題】 音節を構成する音素のうち、子音に対向する音素を音符の発生タイミングにあわせて発声することにより、伴奏に合わせたバーチャルシンガによる自然な歌唱を実現する。
【解 決手段】 歌詞に対応した音節毎の発音タイミングデータを含むボーカルデータを予め記憶する。再生処理を始めると、音符「ド」に対応した音節「さ」を発声させると き、子音「s」の発声動作を音符の発音タイミングよりも前に始め、母音「a」の発音タイミングを音符「ド」の発音タイミングに合わせる。これにより、伴奏 に遅れることなく、バーチャルシンガによる自然な歌唱を可能にする。

当該特許出願の、最初の拒絶理由通知(17条の2第1項1号)にて引用された発明 特開平10-319993 「データ編集装置」 の権利化後である特許3518253 「データ編集装置」 の請求項1を見てみました。特許発明の技術的範囲の判断は、原則として請求範囲が基準となるためです。(特許法70条1項) 括弧部分は請求項の理解のために付記しました。

【請求項1】

(公知部分1) 再生テンポに非依存のデュレーションデータにより発生時間が規定された複数の音素データから構成される音節データを含む音声データと

(公知部分2) 該音声データの発音タイミングを規定する再生テンポに依存したタイミングデータとを含むソングデータにおける

(公知部分3) 前記音節データを編集することができるデータ編集装置であって、

(特許要件1) 前記音節データを構成する前記複数の音素データのうちの1つを指定する音素指定手段と、

(特許要件2)
 前記音素指定手段により指定される音素データに対応するデュレーションデータを前記再生テンポの指定とは独立して指定される発生時間に変更する変更手段と

 を有するデータ編集装置。

特開平10-319993 の権利化後である特許3518253 「データ編集装置」 のデータ編集装置とは、Vocaloid Editor の編集機能などを指すと思われます。

 これを、特開2002-221978「ボーカルデータ生成装置、ボーカルデータ生成方法および歌唱音合成装置」の請求項1と対比します。

【請求項1】
(公知部分1) メロディおよび歌詞に対応するボーカルデータを生成するボーカルデータ生成装置であって、

(特許要件1) 歌詞の音節を前記メロディに対応する音符に割り当てる歌詞割当手段と、

(特許要件2) 前記音節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミングを前記音符に対応する発音タイミングに合わせるべく各音節に対応する発音タイミングデータを生成する発音タイミングデータ生成手段と、

(特許要件3) 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高データをボーカルデータとして生成し、このボーカルデータを出力するデータ出力手段と、

 を備えたことを特徴とするボーカルデータ生成装置。

特開2002-221978 のボーカルデータ生成装置とは、Vocaloid Editor の音声出力機能を指すと思われます。最も大きな相違点は、引用発明は音素データの指定手段を有するのに対して、当該発明は音素データの指定手段が無い事です。
 出願人は、最初の拒絶理由通知に対する意見書で音素データの指定無しに発音タイミングを自動調整できることを主張しています。しかし、先願の特許要件を削除したならば、それは上位概念の発明となるため、拒絶査定(特許法49条)を受ける理由となると思います。
 出願人のヤマハ(株)は、Vocaloid の発声タイミングの自動調整機構は、特許3518253 「データ編集装置」 ではカバーされていないことに気づいたのだと思います。そして、特開2002-221978 を審査請求して特許権取得を狙ったが、特許3518253 「データ編集装置」 の権利化前である 特開平10-319993 「データ編集装置」で極めて近い発明が公知化されていた為、相違点は当業者に容易に想到できるとして審査官に拒絶査定を受けたのだと推定します。


 さて、今回の件で、特開平10-319993 「データ編集装置」 及び権利化後の特許3518253 「データ編集装置」 を見てみました。

H10319993_fig4
 これを Vocaloid1 Editor のPhonome編集画面と対比してみてください。酷似しているので驚いてしまいました。

 図4      - Phonome編集画面
 ノート     → (対応なし)
 発音時間   ⇔ POSITION
 歌詞      ⇔ LYRICS
 音素列データ ⇔ PHONETIC SYMBOLS
 呼気      → (対応なし)
 (対応なし)  ← PROTECT

Phenome_edit

段落0050は、ブレス音の実装を記載しています。Vocaloid2 の実装では、ブレスは音素として扱われていますが、当該発明では音素データの属性として扱われています。

【0050】呼気データ65は、息継ぎを表現することを示すデータである。音素データPDの後に呼気データ65が位置すると、その音素データPDを発音した後、息継ぎ表現を行うのため発音を無音状態に変化させることを示す。呼気データ65は、音素列データ55の最後に位置する場合に限らず、音素データPDと他の音素データPDの間に位置してもよい。

段落0052は、ベロシティ(VEL)の実装を記載しています。50音の音素ごとに子音の長さを調整するのではなく、更に細かな音素に分解し、その発音長(デュレーション)を変更可能としてます。

【0052】音節編集機能とは、該各音素のデュレーションを編集することができる機能である。例えば、音素「kha」のデュレーションを4×7.5msから、3×7.5ms又は5×7.5msに変更することができる。この機能を使えば、デュレーションを自由に設定することができるため、例えば音節「か」を発音する場合にも、多様な「か」の発音を行うことができる。

段落0053は、VOCALOIDには全く実装されていない機能について言及しています。

【0053】また、音節編集機能は、音節を構成する音素列データに新たな音素を付け加えることができる。例えば、音素列「CL+kha+aj」に新たな音素を付け加えることにより、鼻にかかったような「か」の発音を実現することも可能になる。さらに、音素を付け加える代わりに、音節を付け加えるようにしてもよい。

 上記のことを総合すると、特開平10-319993 「データ編集装置」 は、VOCALOID のプロトタイプを元に特許出願したものと推定します。VOCALOIDの編集ウインドウと酷似した画面が掲載されており、VOCALOIDに搭載された機能の多くが記載されており、かつVOCALOIDの技術発表(2003年)以前だからです。
 この推定が正しいとすると、特開平10-319993 「データ編集装置」の出願日の1997年5月22日には、既にVOCALOIDプロトタイプが開発済みであったことになります。

| | コメント (0) | トラックバック (0)

特開2002-221978の帰趨#2

特開2002-221978「ボーカルデータ生成装置、ボーカルデータ生成方法および歌唱音合成装置」とは、初音ミクに実装されていると思われる発明で、母音のタイミングを音符のタイミングと一致させる為に、子音を先行して発音させるものです。

【課題】 音節を構成する音素のうち、子音に対向する音素を音符の発生タイミングにあわせて発声することにより、伴奏に合わせたバーチャルシンガによる自然な歌唱を実現する。
【解 決手段】 歌詞に対応した音節毎の発音タイミングデータを含むボーカルデータを予め記憶する。再生処理を始めると、音符「ド」に対応した音節「さ」を発声させると き、子音「s」の発声動作を音符の発音タイミングよりも前に始め、母音「a」の発音タイミングを音符「ド」の発音タイミングに合わせる。これにより、伴奏 に遅れることなく、バーチャルシンガによる自然な歌唱を可能にする。

特開2002-221978が拒絶査定を受けたので、ヤマハ株式会社は拒絶査定不服審判(特121条)を請求し、同時に手続補正書を提出しました。最初の拒絶理由通知の「引用文献1のものはノートオン/オフのタイミングを直接かえて、このタイミングを実現しているが、これを、ノートオン/オフのタイミングは変えずに、音声波形の読み出し時期を制御することにより実現することは当業者が容易に発明をすることができたものである。」の意見に真っ向から反論しています。


【書類名】      手続補正書(方式)
【提出日】      平成17年 1月17日
【あて先】      特許庁長官 殿
【事件の表示】
  【審判番号】   不服2004-25743
  【出願番号】   特願2001- 19141
【補正をする者】
  【識別番号】   000004075
  【氏名又は名称】 ヤマハ株式会社
【代理人】
  【識別番号】   100098084
  【弁理士】
  【氏名又は名称】 川▲崎▼ 研二
  【電話番号】   03-3242-5481
【発送番号】     415026
【手続補正1】
 【補正対象書類名】 審判請求書
 【補正対象項目名】 請求の理由
 【補正方法】    変更
 【補正の内容】
  【請求の理由】
  【手続の経緯】
   出願            平成13年1月26日
   拒絶理由の通知(発送日)  平成16年6月8日
   意見書(提出日)      平成16年8月6日
   手続補正書(提出日)    平成16年8月6日
   拒絶査定(起案日)     平成16年11月8日
   同謄本送達(送達日)    平成16年11月16日
   手続補正書(提出日)    平成17年1月17日

  【拒絶査定の要点】
(a)原査定の拒絶理由は、本願の請求項1~8に係る発明は、特開平10-31999
3号公報(以下、引用例という)に記載された発明に基づいて、その出願前にその発明の
技術の分野における通常の知識を有する者が容易に発明をすることができたものであるか
ら、特許法第29条第2項の規定により特許を受けることができない、というものである

(b)その理由は、要するに、引用例には、音声波形を通常のノートオンタイミングで読
み出すと、子音の発音時間分だけ聴取者には発音が遅れたように聞こえる課題を解決する
ため、ノートオンのタイミングが母音の発音開始点となるように音声素片の読み出しタイ
ミングを調整することが記載されているため、本願発明は、この引用例に記載された発明
に基づき容易に発明することができたものである、というものである。
  【本願発明が特許されるべき理由】
(a)本願発明の説明
 請求項1に係る発明は、「メロディおよび歌詞に対応するボーカルデータを生成するボ
ーカルデータ生成装置であって、歌詞の音節のデータ数と前記メロディに対応する音符の
データ数とを合わせて、該歌詞の音節を該メロディに対応する音符に割り当てる歌詞割当
手段と、前記音節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミ
ングが前記音符に対応する発音タイミングに合うように各音節の発音タイミングを指示す
る発音タイミングデータを生成する発音タイミングデータ生成手段と、前記音節の音素列
データ、前記発音タイミングデータおよび前記音節に対応した音高データをボーカルデー

タとして生成し、このボーカルデータを出力するデータ出力手段と、を備えたことを特徴
とするボーカルデータ生成装置」を要旨とするものである。
 かかる発明によれば、歌詞の音節のデータ数とメロディに対応する音符のデータ数とを
合わせて、該歌詞の音節を該メロディに対応する音符に割り当て、歌詞の音節を音素に分
け、母音の音素の発音タイミングが音符に対応する発音タイミングに合うように各音節の
発音タイミングを指示する発音タイミングデータを生成するので、操作者の手を全く煩わ
せることなく、歌詞に含まれる音節のうち子音および母音からなる音節のみを対象とし、
音符のタイミングより遅れて聞こえることのないよう自動的に音節の発音タイミングを調
整することができる。
 請求項2は、この請求項1におけるボーカルデータの出力態様に関し、「ボーカルデー
タをシステムエクスクルーシブメッセージに含ませて出力する」なる技術的限定を加えた
ものである。
 請求項3~6は、請求項1または2にさらなる技術的限定を加えて従属項、請求項7お
よび8は請求項1および2を各々方法のカテゴリに書き換えた請求項である。
(b)補正の根拠の明示
 同時に提出する手続補正書により、請求項1、2、7および8における歌詞割当手段ま
たは歌詞割当工程は、「歌詞の音節のデータ数と前記メロディに対応する音符のデータ数
とを合わせて、該歌詞の音節を該メロディに対応する音符に割り当てる」ものであること
を明らかにする補正を行った。この補正は、本願の出願当初の明細書における段落004
2の記載を根拠とするものである。
(c)引用発明の説明
 引用例の段落0060~0065には、音節毎に発音タイミングを早める程度を示すク
ロック数を定めた変換テーブルを記憶し、各音節の音声データの発生タイミングをその変
換テーブルに定められたクロック数だけ早める旨が開示されている。また、引用例の段落
0059および0060には、音節が音として聞こえるタイミングが子音のデュレーショ
ンにより遅れる旨が開示されている。また、引用例の段落0063には、子音の音素を含
まない音節については、発音タイミングを早める程度を示すクロック数を変換テーブルに
おいて定める必要がない旨が開示されている。
(d)本願発明と引用発明との対比
 引用発明は、子音のデュレーションにより聴取者には発音が遅れたように聞こえる課題
を解決するため、音節の発音タイミングを早めるものである点において、請求項1に係る
発明と共通の特徴を有する。

 しかしながら、請求項1に係る発明と引用発明との間には、次の相違点がある。すなわ
ち、請求項1に係る発明は、「音節を音素に分け、各音節を構成する音素のうち、母音の
音素の発音タイミングが前記音符に対応する発音タイミングに合うように各音節の発音タ
イミングを指示する発音タイミングデータを生成する」
に当たり、「歌詞の音節のデータ
数と前記メロディに対応する音符のデータ数とを合わせて、該歌詞の音節を該メロディに
対応する音符に割り当てる」という技術的特徴を有するのに対し、引用発明はこの技術的
特徴を有しない。
 音節には、母音のみからなる音節と、子音および母音のみからなる音節とがあるが、請
求項1に係る発明によれば、「歌詞の音節のデータ数と前記メロディに対応する音符のデ
ータ数とを合わせて、該歌詞の音節を該メロディに対応する音符に割り当てる」ため、各
音符には1つずつ音節が割り当てられ、それらのうち子音および母音からなる各音節につ
いては、「母音の音素の発音タイミングが前記音符に対応する発音タイミングに合うよう
に各音節の発音タイミングを指示する発音タイミングデータを生成する」ことができる。
このように請求項1に係る発明によれば、歌詞の中に含まれる音節のうち子音および母音
からなる音節のみを自動的に選択して調整対象とし、音符より遅れて聞こえることのない
ようにその音節の発音タイミングを調整することができる、という引用発明からは得られ
ない格別な効果が得られる。
このような特徴は、引用例には開示されておらず、示唆すら
されていない。

 よって、請求項1に係る発明は、引用発明に基づき容易に発明することができたもので
はなく、特許要件を具備すると確信する次第である。
 他の請求項に係る発明は、請求項1に係る発明にさらなる技術的限定を加えたもの、あ
るいは請求項1に係る発明のカテゴリのみを変更したものである。
 よって、これらの請求項に係る発明も、請求項1と同様の理由により、特許要件を具備
すると確信する次第である。
  【むすび】
 以上のように、本願発明は引用例に記載された発明とは全く別異であり、引用例から容
易には想到し得ないものであるから特許要件を具備するものと確信致します。よって本願
に対し、特許査定を賜りますようお願いする次第です。

これに対しての前置報告書は以下のものです。

                前置報告書

 審判番号         不服2004-25743
 特許出願の番号      特願2001-019141
 特許庁審査官       渡邊 聡         8622 5D00
 作成日          平成17年 2月23日

 この審判請求に係る出願については、下記の通り報告する。

                 記
 平成17年1月17日付け手続補正書にて新たに付加された構成(歌声生成時
に音符数と音節数とを対応させてメロディ付き音声を出力する点)は下記の周知
文献に記載されている。

本願出願前周知の技術事項を示す文献
特開2000-105595号公報

前置審査で、審査官は新たな先行技術として特開2000-105595「歌唱装置及び記録媒体」を指摘しました。出願人は日本ビクター株式会社です。この先行技術の要約を見てみます。

【課題】 任意のテキストファイルを自動的にメロディ にのせて歌にしてしまう歌唱装置がなかった。
【解決手段】 供給されるテキストデータはテキスト解析部4によってその音節データに変換され、供給されるテキストデータと共にメロディ 生成部6に出力される。また、音楽生成用SMF2aもメロディ 生成部6に出力される。そして、音節データは音楽生成用SMF2aのメロディ ーに割り当てられてシーケンサ部8に出力され、ソフトシンセ12によって、音節データを音声に変換して音程を変化させながらサウンド出力部14から出力する。

 VOCALOIDを先取りしたような発明を日本ビクターが出願していたものだと感心してしまいました。しかし、日本ビクターは、この発明が単発だったらしくてあとが続いていません。

 さて、拒絶査定不服審判は請求棄却審決となりましたが、その理由を見てみます。まずは引用発明との一致点と相違点を認定し、相違点について当業者が容易に想到することの論理を構築しております。このあたりは審査基準を厳格に守っていますね。

(一致点)
 「メロディおよび歌詞に対応するボーカルデータを生成するボーカルデータ生成装置であって、
 歌詞の音節のデータと前記メロディに対応する音符のデータとを合わせて、該歌詞の音節を該メロディに対応する音符に割り当てる歌詞割当手段と、
 前記音節を音素に分け、音節を構成する音素のうち、母音の音素の発音タイミングが前記音符に対応する発音タイミングに合うように音節の発音タイミングを指示する発音タイミングデータを生成する発音タイミングデータ生成手段と、
 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高データをボーカルデータとして生成し、このボーカルデータを出力するデータ出力手段と、
を備えたボーカルデータ生成装置。」
である点で一致し、次の各点で相違する。

(相違点1)
 本願補正発明は、歌詞の音節のデータ数とメロディに対応する音符のデータ数とを合わせて、歌詞の音節をメロディに対応する音符に割り当てているのに対し、引用例に記載された発明は、歌詞の音節のデータとメロディに対応する音符のデータとを合わせて、歌詞の音節をメロディに対応する音符に割り当てるものではあるが、歌詞の音節のデータ数とメロディに対応する音符のデータ数までを合わせるとは明記しない点。

(相違点2)
 本願補正発明は、各音節を構成する音素のうち、母音の音素の発音タイミングが音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音タイミングデータを生成しているのに対して、引用例1に記載された発明は、音符の発生タイミングに対して発音の遅れを感じた歌詞(例えば、「か」)についてのみ音節の発生タイミングを指示して発音タイミングデータを生成している点。

(4)判断
(相違点1について)
 上記相違点1について判断するに、(i)通常、メロディを構成する音符の総数と歌詞を構成する音節の総数とは、ほぼ同数とされていることは、歌を愛好する人なら誰でも経験していることである。
(ii) また、メロディを構成する音符の総数と歌詞を構成する音節の総数とを、ほぼ同じ数とし、メロディが奏でられている間中、歌詞を歌唱することは、例えば、特開2000-105595号公報(特に、段落【0039】~【0041】の記載を参照。)にその旨の記載があるように当業者のみならず歌を愛好する人には周知自明な技術常識である。
 以上のことに鑑みると、引用例1に記載された発明に上記周知技術常識を適用して、本願発明の如く構成することは、当業者が適宜なし得ることである。

(相違点2について)
 上記相違点2について判断するに、(i)引用例1に記載されているように(前掲(ア)~(ウ)参照。)、音節が母音と子音からなる場合、母音の発声タイミングを音符の発生タイミングに合わせると音符が示す音の発生から遅れて、音節の音が聞こえる現象は、当分野の当業者の間に広く認識されている音現象であり、しかもこの問題を解消するためには音符の発生タイミングよりも子音の発声タイミングを少し前にずらせば解決すること(このことは人間が歌を歌うとき無意識に行っていることは、本願補正発明の明細書の段落【0004】における記載でも指摘されている。)も当業者の間に広く知られている自明な技術事項である。(ii)そして、引用例1に記載された発明は、音節及び音声データ編集時の操作性を高めるために、母音と子音とからなる音節すべてに対して等しく母音の発声タイミングを変更する構成を採用せず、敢えて、音符の示す音の発生から遅れを感じた歌詞のみに対して母音の発声タイミングを変更する構成を採用しているのであるから、音印象の如何にかかわらず一律に発声タイミングの変更を行うようにすることは、当業者が適宜なし得ることである。そして、その奏する効果の程も当業者の当初の予測の範囲を超えるものではない。

(5)むすび
 以上のとおり、本願補正発明は、引用例1に記載された発明及び周知技術に基づいて当業者が容易に発明をすることができたものであるから、特許法第29条第2項の規定により特許出願の際、独立して特許を受けることができるものではなく、特許法第17条の2第5項で準用する同法126条第5項の規定に違反するものであるから、平成17年1月17日付けの手続補正は、特許法第159条第1項で準用する同法第53条第1項の規定により却下すべきものである。

自分は、特開2000-105595「歌唱装置及び記録媒体」の図面に驚いてしまいました。まるで「初音ミク」の予言のように感じてしまいます。


20080514232703141204_2
20080514232703255814

 ついでに、最初の拒絶理由通知に記載された特開平10-319993 「データ編集装置」 を調べてみました。この特許の出願人はヤマハ(株)じゃないですか!しかも権利化されています。だったら、特開2002-221978 の権利化に拘らなくてもよかったのではと思います。

| | コメント (2) | トラックバック (0)

特開2002-221978の帰趨

特開2002-221978の帰趨について hidonさんからご質問を受けましたので、調査してみました。データベースは特許電子図書館の経過情報検索です。

特開2002-221978「ボーカルデータ生成装置、ボーカルデータ生成方法および歌唱音合成装置」とは、初音ミクに実装されていると思われる発明で、母音のタイミングを音符のタイミングと一致させる為に、子音を先行して発音させるものです。

【課題】 音節を構成する音素のうち、子音に対向する音素を音符の発生タイミングにあわせて発声することにより、伴奏に合わせたバーチャルシンガによる自然な歌唱を実現する。
【解 決手段】 歌詞に対応した音節毎の発音タイミングデータを含むボーカルデータを予め記憶する。再生処理を始めると、音符「ド」に対応した音節「さ」を発声させると き、子音「s」の発声動作を音符の発音タイミングよりも前に始め、母音「a」の発音タイミングを音符「ド」の発音タイミングに合わせる。これにより、伴奏 に遅れることなく、バーチャルシンガによる自然な歌唱を可能にする。

表1、特開2002-221978の経過情報

                                                                                                                                                                
出願記事特許 2001-019141 (平13.1.26) 出願種別(通常)
公開記事2002-221978 (平14.8.9)
発明の名称ボーカルデータ生成装置およびボーカルデータ生成方法
出願人ヤマハ株式会社 <YAMAHA CORPORATION>
発明・考案・創作者劔持 秀紀
公開・公表IPC
国際分類 第7版
   G10L 13/00         
国際分類 第4版
   G10L  3/00        J
出願細項目記事査定種別(拒絶査定)
審判記事登録記録査定不服審判 2004-025743 請求日(平16.12.16) 審判(判定含む) 請求不成立 最終処分日(平19.7.26)

この特許出願は、拒絶査定(特49条)を受けたのち、ヤマハ(株)は平成16年12月16日に拒絶査定不服審判(特121条)を請求しましたが、平成19年7月26日に請求棄却審決を受け、拒絶が確定したようです。よって、この特許出願は不成立のまま終わりました。

 最初の拒絶理由通知書は以下のものです。特開平10-319993号公報を理由に進歩性欠如(29条2項)で拒絶しています。

              拒絶理由通知書

 特許出願の番号      特願2001-019141
 起案日          平成16年 5月31日
 特許庁審査官       渡邊 聡         8622 5C00
 特許出願人代理人     川▲崎▼ 研二 様
 適用条文         第29条第2項


 この出願は、次の理由によって拒絶をすべきものである。これについて意見が
あれば、この通知書の発送の日から60日以内に意見書を提出して下さい。

                理 由

 この出願の下記の請求項に係る発明は、その出願前日本国内又は外国において
頒布された下記の刊行物に記載された発明に基いて、その出願前にその発明の属
する技術の分野における通常の知識を有する者が容易に発明をすることができた
ものであるから、特許法第29条第2項の規定により特許を受けることができな
い。

     記   (引用文献等については引用文献等一覧参照)
(請求項1乃至10について)
 下記の引用文献1には楽音合成装置において、ボーカル信号を合成するときの
タイミングについて、ボーカルの子音については人が聞き取りにくく、発音タイ
ミングは母音の発音開始時点に調整した方がよいことが記載されている。
 引用文献1のものはノートオン/オフのタイミングを直接かえて、このタイミ
ングを実現している
が、これを、ノートオン/オフのタイミングは変えずに、
声波形の読み出し時期を制御することにより実現すること
は当業者が容易に発明
をすることができたものである。
 上記以外の構成は、楽音発生装置の技術分野において周知の技術事項である。

 この拒絶理由通知書中で指摘した請求項以外の請求項に係る発明については、
現時点では、拒絶の理由を発見しない。拒絶の理由が新たに発見された場合には
拒絶の理由が通知される。

           引 用 文 献 等 一 覧
1.特開平10-319993号公報
------------------------------------
           先行技術文献調査結果の記録            
                                                                        
・調査した分野  IPC第7版  G10L13/00
                        DB名   
・先行技術文献                             
                                    
 この先行技術文献調査結果の記録は、拒絶理由を構成するものではない。

 これに対する2004年8月6日付けの意見書は以下のものです。先行技術文献が1件だけということは、審査官が相当の自信をもって拒絶理由通知を打ってきていると思われます。よって、出願人側は、本腰を入れて掛からないと特許を受けることはできません。
 しかし、出願人の代理人による意見書はなんだかベクトルがぶれている感じがします。当該発明の優位性を「音素の選択が不要である」ことならば、その点を重点的に述べて有利な効果を主張し、かつ補正により主張した点が明確になるようにすべきですが、そのような対処はなされていません。

【書類名】      意見書
【提出日】      平成16年 8月 6日
【あて先】      特許庁審査官 渡邊 聡 殿
【事件の表示】
  【出願番号】   特願2001- 19141
【特許出願人】
  【識別番号】   000004075
  【氏名又は名称】 ヤマハ株式会社
【代理人】
  【識別番号】   100098084
  【弁理士】
  【氏名又は名称】 川▲崎▼ 研二
  【電話番号】   03-3242-5481
【発送番号】     202468
【意見の内容】
(1)審査官殿は、本願の請求項1~10に係る発明は、その出願前に日本国内又は外国
において頒布された特開平10-319993号公報(以下、引例という)に記載された
発明に基づいて当業者が容易に発明することができたものであるから、特許法第29条第
2項の規定により特許を受けることができない、とのご認定である。
 しかしながら、本出願人は、この認定には承服できず、別紙手続補正書により本願発明
の要旨を明確にするとともに、以下に意見を申し述べる。
(2)本願の請求項1に係る発明は、別紙手続補正書により明らかにしたように「前記音
節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミングが前記音符
に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音タイミン
グデータを生成する」ものである。なお、この補正は、本願の出願当初の明細書の段落0
045、0053の記載および図面の図9を根拠としている。
 引例の段落0060~0065の記載によると、引例のものは、音節毎に発音タイミン
グを早める程度を示すクロック数を定めた変換テーブルを記憶し、子音の音素を含む音声
データの発生タイミングをその子音に対応したクロック数だけ早めるものである。しかも
引例によると、この子音に対応したクロック数だけ早める処理は、操作者が発音の遅れ
た歌詞(例えば「か」)を指定することにより行われる(段落0065)

 しかしながら、本願の請求項1に係る発明は、このように、操作者からの指示に従い、
変換テーブルを利用して、音声データの発生タイミングを早めるものではない。本願の請
求項1に係る発明の特徴は、「母音の音素の発音タイミングが音符に対応する発音タイミ
ングに合うように各音節の発音タイミングを指示する発音タイミングデータを生成する」
点にある。

 かかる発明によれば、音節が子音と母音からなる場合であっても、母音の発音タイミン
グが音符の発音タイミングに合ったボーカルデータが自動的に作成されるため、操作者の
手を全く煩わせることなく各音節の母音の発音タイミングが音符のタイミングとが整合し
たボーカルデータが得られる。

 このような技術的特徴は、引例には開示されておらず、示唆もされていない。他の独立
請求項2、7、8も同様である。
(3)結論
 従って、本願発明は特許要件を具備するものと確信致します。よって本願に対し、特許
査定を賜りますようお願いする次第です。

2004年8月6日付けの手続補正書は以下のものです。

【書類名】      手続補正書
【提出日】      平成16年 8月 6日
【あて先】      特許庁長官 殿
【事件の表示】
  【出願番号】   特願2001- 19141
【補正をする者】
  【識別番号】   000004075
  【氏名又は名称】 ヤマハ株式会社
【代理人】
  【識別番号】   100098084
  【弁理士】
  【氏名又は名称】 川▲崎▼ 研二
  【電話番号】   03-3242-5481
【発送番号】     202468
【手続補正1】
 【補正対象書類名】 明細書
 【補正対象項目名】 発明の名称
 【補正方法】    変更
 【補正の内容】
  【発明の名称】ボーカルデータ生成装置およびボーカルデータ生成方

【手続補正2】
 【補正対象書類名】 明細書
 【補正対象項目名】 特許請求の範囲
 【補正方法】    変更
 【補正の内容】
【特許請求の範囲】
  【請求項1】 メロディおよび歌詞に対応するボーカルデータを生成するボーカルデ
ータ生成装置であって、
 歌詞の音節を前記メロディに対応する音符に割り当てる歌詞割当手段と、
 前記音節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミング
前記音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音
タイミングデータを生成する発音タイミングデータ生成手段と、
 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高デ
ータをボーカルデータとして生成し、このボーカルデータを出力するデータ出力手段と、
を備えた
 ことを特徴とするボーカルデータ生成装置。
  【請求項2】 メロディおよび歌詞に対応するボーカルデータを生成するボーカルデ
ータ生成装置であって、
 歌詞の音節を前記メロディに対応する音符に割り当てる歌詞割当手段と、
 前記音節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミング
前記音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音
タイミングデータを生成する発音タイミングデータ生成手段と、
 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高デ
ータをボーカルデータとして生成し、このボーカルデータをシステムエクスクルーシブメ
ッセージに含ませて出力するデータ出力手段と、を備えた
 ことを特徴とするボーカルデータ生成装置。
  【請求項3】 請求項1または2記載のボーカルデータ生成装置において、前記デー
タ出力手段は、前記ボーカルデータをコーラス毎に分けて出力することを特徴とするボー
カルデータ生成装置。
  【請求項4】 請求項1または2記載のボーカルデータ生成装置において、前記デー
タ出力手段は、前記ボーカルデータをフレーズ毎に分けて出力することを特徴とするボー
カルデータ生成装置。
  【請求項5】 請求項1または2記載のボーカルデータ生成装置において、前記デー
タ出力手段は、前記ボーカルデータを各息継ぎ区間毎に分けて出力することを特徴とする
ボーカルデータ生成装置。
  【請求項6】 請求項1または2記載のボーカルデータ生成装置において、前記デー
タ出力手段は、前記ボーカルデータを小節毎に出力することを特徴とするボーカルデータ
生成装置。
  【請求項7】 メロディおよび歌詞に対応するボーカルデータを生成するボーカルデ
ータ生成方法であって、
 歌詞の音節を前記メロディに対応する音符に割り当てる歌詞割当工程と、
 前記音節を音素に分け、各音声を構成する音素のうち、母音の音素の発音タイミング
前記音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音
タイミングデータを生成する発音タイミングデータ生成工程と、
 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高デ
ータをボーカルデータとして生成し、このボーカルデータを出力するデータ出力工程と、
を備えた
 ことを特徴とするボーカルデータ生成方法。
  【請求項8】 メロディおよび歌詞に対応するボーカルデータを生成するボーカルデ
ータ生成方法であって、
 歌詞の音節を前記メロディに対応する音符に割り当てる歌詞割当工程と、
 前記音節を音素に分け、各音声を構成する音素のうち、母音の音素の発音タイミング
前記音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音
タイミングデータを生成する発音タイミングデータ生成工程と、
 前記音節の音素列データ、前記発音タイミングデータおよび前記音節に対応した音高デ
ータをボーカルデータとして生成し、このボーカルデータをシステムエクスクルーシブメ
ッセージに含ませて出力するデータ出力工程と、を備えた
 ことを特徴とするボーカルデータ生成方法。

【手続補正3】
 【補正対象書類名】 明細書
 【補正対象項目名】 0001
 【補正方法】    変更
 【補正の内容】
   【0001】
  【発明の属する技術分野】
 本発明は、例えばパソコンによるコンピュータ・ミュージックに用いて好適なボーカル
データ生成装置およびボーカルデータ生成方法に関する。

【手続補正4】
 【補正対象書類名】 明細書
 【補正対象項目名】 0010
 【補正方法】    変更
 【補正の内容】
  【0010】
 本発明は、以上の問題に鑑みてなされたものであり、伴奏に合わせたバーチャルシンガ
による自然な歌唱を実現することのできるボーカルデータを生成するボーカルデータ生成
装置およびボーカルデータ生成方法を提供することを目的としている。

【手続補正5】
 【補正対象書類名】 明細書
 【補正対象項目名】 0011
 【補正方法】    変更
 【補正の内容】
   【0011】
  【課題を解決するための手段】
 上記目的を達成するために、この発明は、歌詞の音節をメロディに対応する音符に割り
当て、音節を音素に分け、各音節を構成する音素のうち、母音の音素の発音タイミングが
音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する発音タイ
ミングデータを生成し、音節の音素列データ、発音タイミングデータおよび音節に対応し
た音高データをボーカルデータとして生成するボーカルデータ生成装置およびボーカルデ
ータ生成方法を提供する。

 出願人が意見書で反論し、手続補正書で引用文献との差異を出そうとしたにも係わらず、審査官による拒絶査定を受けました。
 審査官は、進歩性(29条2項)を否定し得る論理として、「音素を選択せずに全てに処理を適用することは当業者にとって自明である」という点を指摘しており、当該拒絶査定は妥当とおもいます。

              拒絶査定


 特許出願の番号      特願2001-019141
 起案日          平成16年11月 8日
 特許庁審査官       渡邊 聡         8622 5D00
 発明の名称        ボーカルデータ生成装置およびボーカルデータ生
              成方法
 特許出願人        ヤマハ株式会社
 代理人          川▲崎▼ 研二


 この出願については、平成16年 5月31日付け拒絶理由通知書に記載した
理由によって、拒絶をすべきものである。
 なお、意見書並びに手続補正書の内容を検討したが、拒絶理由を覆すに足りる
根拠が見いだせない。

備考
 出願人は意見書にて下記のとおり主張している。
    記
 引例の段落0060~0065の記載によると、引例のものは、音節毎に発音
タイミングを早める程度を示すクロック数を定めた変換テーブルを記憶し、子音
の音素を含む音声データの発生タイミングをその子音に対応したクロック数だけ
早めるものである。しかも、引例によると、この子音に対応したクロック数だけ
早める処理は、操作者が発音の遅れた歌詞(例えば「か」)を指定することによ
り行われる(段落0065)。
 しかしながら、本願の請求項1に係る発明は、このように、操作者からの指示
に従い、変換テーブルを利用して、音声データの発生タイミングを早めるもので
はない。本願の請求項1に係る発明の特徴は、「母音の音素の発音タイミングが
音符に対応する発音タイミングに合うように各音節の発音タイミングを指示する
発音タイミングデータを生成する」点にある。
 かかる発明によれば、音節が子音と母音からなる場合であっても、母音の発音
タイミングが音符の発音タイミングに合ったボーカルデータが自動的に作成され
るため、操作者の手を全く煩わせることなく各音節の母音の発音タイミングが音
符のタイミングとが整合したボーカルデータが得られる。
 出願人の主張する、操作者が発音遅れの歌詞を指定する必要性については、引
用文献のものにおいて、
単にすべての歌詞を指定すれば本願発明のものと同じと
なることは自明のこと
であり、引用文献1のものは操作者の自由度を高めるため
に、あえて、遅れを感じた歌詞のみ指定できるようになっているのであるから、
あらかじめこのような機能を設けずにすべての歌詞について、一律に、発音タイ
ミングの変更を行うようにすることは当業者が適宜なしえたこと
である。
 そして、引用文献1にの【0059】、【0060】の記載を見れば、その技
術思想は、結局本願発明と同じ、音声波形を通常のノートオンタイミングで読み
出すと、子音の発音時間分だけ聴取者には発音が遅れたように聞こえる課題を解
決するため、ノートオンのタイミングが母音の発音開始時点となるように音声素
片の読み出しタイミングを調整することが記載されているから、本願発明は上記
拒絶理由通知書に記載された発明に基づき当業者が容易に発明をすることができ
たという拒絶の理由は解消していない。
                                 以上
続きは明日にでも記載します。

| | コメント (1) | トラックバック (0)

MIKU_TALK 0.2.1 ソース(VSQ生成部)

 MIKU_TALK 0.2.1 のVSQ生成部ソースを公開します。サーバ上のCGIスクリプトとして動作しますが、ローカルPC上で動くように変更するのは、それほど難しくはないと思います。説明なくとも理解できるよう、できるだけ沢山のコメントを入れました。これを参考に更に良いものが世の中に生み出されればと思います。

#!/usr/local/bin/perl
BEGIN { unshift(@INC, "/cgi-bin/lib"); }
########################################################################
#
#    Filename : miku_talk021.cgi @infoseek
#    Charcode : UTF-8
#
#    Released on 26/Apr/2008, Programmed by A.Izumi
#
#
use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use Jcode;
use MIDI;        # MIDI-Perl のインストールを要する。(非標準モジュール)
#
#    プロバイダ固有部分:ワークファイルの相対書込み先
#
my $myWorkFolderPath = "work";

#
#    プロバイダ固有部分:URL
my $myUrl = "work";
my $myAdv = "";

$CGI::POST_MAX = 1024*1024*100;

#
#    ワークファイル書込みフォルダを作成しておく。
mkdir($myWorkFolderPath, 0777);

my $q = new CGI;
my $mySessionId = GetSessionId($q->remote_host);

my $myPostedString = $q->param("myText1");
my $myDebugMode    = $q->param("debug");

if( !defined($myDebugMode) ) {
  $myDebugMode = 0;
}
# 改行記号が \x0d の場合に \x0d\x0a に正規化する。
$myPostedString =~ s/\x0d\x0a/\x0d/g;
$myPostedString =~ s/\x0d/\x0d\x0a/g;
$myPostedString =~ s/%([0-9a-f][0-9a-f])/pack("C",hex($1))/egi;
$myPostedString = Jcode->new($myPostedString)->utf8;

#
#    入力された形態素のチェック
#
  my $maErrorLine = checkMa($myPostedString,$mySessionId);
  if( $maErrorLine > 0 ) {
    print $q->header(-type=>'text/html; charset=UTF-8');
    print $q->start_html(-lang=>'ja',
                     -charset  => 'UTF-8',
                     -encoding => 'UTF-8',
                     -title    => 'MIKU_TALK Ver. 0.2.0');
    print $myAdv, "\n";
    print $q->br;
    print $q->h1('MIKU_TALK はエラーを検出しました。'),
          $q->hr;
    print "MIKU_TALK は、".$maErrorLine."行目の形態素を読み取れません。\n";
    print $q->br;
    exit();
  }
  if( $myDebugMode != 0 ) {
    print $q->header(-type=>'text/html; charset=UTF-8');
    print $q->start_html(-lang=>'ja',
                     -charset  => 'UTF-8',
                     -encoding => 'UTF-8',
                     -title    => 'MIKU_TALK Ver. 0.2.0');
    print $myAdv, "\n";
    print $q->h1('MIKU_TALK がVSQファイルを生成しました。'),
          $q->hr,
          $q->br;
  }
  my $lockdir = "miku_lock";
  my $retry = 20;                            # リトライ回数セット
  while (!mkdir($lockdir, 0755)) {           # ロック作成。出来なければ待つ
    if (--$retry <= 0) {
       last;
    } # 20秒間ダメならあきらめて強行
    sleep(1);                              # 1秒待つ
  }
  my $myDebugPath = "./". $myWorkFolderPath. "/". $mySessionId. ".txt";
  my $myVsqPath = "./". $myWorkFolderPath. "/". $mySessionId. ".vsq";
  my $myVsqUrl  = $myUrl. "/". $mySessionId. ".vsq";

  WriteMA("ma000.txt",$myPostedString);
  $myPostedString = Hankaku2Zenkaku($myPostedString);
  WriteMA("ma001.txt",$myPostedString);
  $myPostedString = JoinTyouonKigou($myPostedString);
  WriteMA("ma002.txt",$myPostedString);
  $myPostedString = AddPhonetic($myPostedString);
  WriteMA("ma003.txt",$myPostedString);
  $myPostedString = AddSeparator($myPostedString);
  WriteMA("ma004.txt",$myPostedString);

  $myPostedString = ParseSentence($myPostedString);
  WriteMA("ma005.txt",$myPostedString);
  mecab2VsqGenerate( $myPostedString, $myVsqPath );

  my @myStatVsq = ();
  @myStatVsq = stat $myVsqPath;
  rmdir($lockdir);                           # ロックの削除

#
#    正常にVSQ生成できた。
#
  if( $myDebugMode != 0 ) {
#
#    デバッグモードでは、ダウンロードリンクを表示する。
#
    my $myVsqCgi = "miku_talk_dl021.cgi";
    $myVsqCgi   .= "?download_name=". $mySessionId. ".vsq";
    $myVsqCgi   .= "&source_path="  . $myVsqPath;
    $myVsqCgi   .= "&debug="        . $myDebugMode;
    print $q->a({href=> $myVsqCgi }, "VSQファイルのダウンロード");
    print $q->br;
    print "↑ ここをクリックしてください。";
    print $q->br;
    print $q->end_html;

  } else {
#
#    正常にVSQ生成できたなら、ダウンロードする。
#
    print $q->header(
        -content_type        => "audio/midi",
        -content_disposition => "attachment;filename=". $mySessionId. ".vsq"
      );
    my $contents;
    my @srcStat = stat $myVsqPath;

    open(hFile,"< ".$myVsqPath);
    binmode hFile;
    read hFile,$contents, $srcStat[7] + 1024;
    print $contents;
    close(hFile);
#
#    元ファイルは消す。
#
    unlink $myVsqPath;
  }
  exit;
########################################################################
#
#   サブルーチン名:WriteMA
#
#   第1引数:出力するファイルパス
#   第2引数:出力データ
#
sub WriteMA {
  open hFile,">".$_[0];
  my @myWords = split(/\n/, $_[1]);
  my $i=0;
  for($i=0; $i<@myWords-1; $i++) {
    print hFile $myWords[$i]."\n";
  }
  close hFile;
  return $_[1];
}
########################################################################
#
#   サブルーチン名:Hankaku2Zenkaku
#
#   形態素解析の読みが半角カナならば全角カナに変換する。
#
#    Mecab拡張形式入力
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#
sub Hankaku2Zenkaku {
  my @myWords = split(/\n/, $_[0]);

  my $i=0;
  for($i=0; $i<@myWords; $i++) {
    #
    # 現在着目している単語
    #
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;
    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];

    if( !defined($thisWord19) || length($thisWord19)==0 ) {
      $myWords[$i] = sprintf("%s\x0d\n",$thisWord);
    } else {
      my( $hinsi, $yomi ) = (split( /,/, $thisWord19 ))[0,8];
#
#   Mecab対策・・・カタカナ記載は読みを出力しない場合があるので、
#  $midasi をそのまま読みとする。
#
      if( $hinsi eq "名詞" && $yomi eq "" ) {
        $yomi = $midasi;
      }
      my $yomi_sj = Jcode->new($yomi,'utf8')->sjis;
      $yomi = Jcode->new($yomi_sj,'sjis')->h2z->utf8;
      $myWords[$i] = sprintf("%s\t%s,,,,,,,,%s\x0d\n", $midasi, $hinsi, $yomi );
    }
  }
  my $result = "";
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    $result .= $thisWord;
  }
  return $result;
}
########################################################################
#
#   サブルーチン名:JoinTyouonKigou
#
#    単独の長音記号を直前の語に付けて、発音を確定させる。
#
#    Mecab拡張形式入力
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#
sub JoinTyouonKigou {
  my @myWords = split(/\n/, $_[0]);

  my $i=0;
  for($i=0; $i<@myWords-1; $i++) {
#
# 現在着目している単語の各要素を切り出す。
#
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;
    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];

    if( !defined($thisWord19) || length($thisWord19)==0 ) {
      $myWords[$i] = sprintf("%s\x0d\n",$thisWord);
    } else {
      my( $hinsi, $yomi ) = (split( /,/, $thisWord19 ))[0,8];

#
# 次に着目する単語が長音記号ならば、見出しと読みに追加してゆく。
#
      my $j=0;
      for($j=$i+1; $j<@myWords; $j++) {
        my $nextWord = $myWords[$j];
        chomp($nextWord);
        $nextWord =~ s/\x0d//g;
        my( $nextMidasi, $nextWord19 ) = (split( /\t/, $nextWord ))[0,1];
        if( length($nextWord19)!=0 ) {
          my( $nextHinsi, $nextYomi ) = (split( /,/, $nextWord19 ))[0,8];

          if( $nextMidasi eq "ー" || $nextMidasi eq "-" ) {
            $midasi .= $nextMidasi;
            $yomi   .= $nextMidasi;
            $myWords[$j] = "";
          } else {
            last;
          }
        }
      }
      $myWords[$i] = sprintf("%s\t%s,,,,,,,,%s\x0d\n", $midasi, $hinsi, $yomi );
    }
  }
  my $result = "";
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    if( length($thisWord) != 0 ) {
      $result .= $thisWord;
    }
  }
  return $result;
}
########################################################################
#
#   サブルーチン名:AddPhonetic
#
#    機能:発音を付加する。
#
#    Mecab拡張形式入力
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#
#
#    Mecab拡張形式出力
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
# ● 9,ミク発音と歌詞      :$lyricPhonetics
# ●10,発音数          :$phoneticCount
#
#
sub AddPhonetic {
  my @myWords = split(/\n/, $_[0]);
my %phonetic = (
"あ"=>"a",  "い"=>"i",   "う"=>"M",    "え"=>"e",    "お"=>"o",
"ぁ"=>"a",  "ぃ"=>"i",   "ぅ"=>"M",    "ぇ"=>"e",    "ぉ"=>"o",
"か"=>"k a","き"=>"k' i","く"=>"k M",  "け"=>"k e",  "こ"=>"k o",
"さ"=>"s a","し"=>"S i", "す"=>"s M",  "せ"=>"s e",  "そ"=>"s o",
"た"=>"t a","ち"=>"tS i","つ"=>"ts M", "て"=>"t e",  "と"=>"t o",
"な"=>"n a","に"=>"J i", "ぬ"=>"n M",  "ね"=>"n e",  "の"=>"n o",
"は"=>"h a","ひ"=>"C i", "ふ"=>"p\\ M","へ"=>"h e",  "ほ"=>"h o",
"ま"=>"m a","み"=>"m' i","む"=>"m M",  "め"=>"m e",  "も"=>"m o",
"や"=>"j a",             "ゆ"=>"j M",  "いぇ"=>"j e","よ"=>"j o",
"ら"=>"4 a","り"=>"4' i","る"=>"4 M",  "れ"=>"4 e",  "ろ"=>"4 o",
"わ"=>"w a","ゐ"=>"w i",
#        "ゑ"=>"w e",
"を"=>"o","うぃ"=>"w i",             "うぇ"=>"w e",
"ん"=>"n",
#"んが"=>"N a",   "んぎ"=>"N i",   "んぐ"=>"N M",   "んげ"=>"N e",   "んご"=>"N o",
#"んにゃ"=>"N' a","んにぃ"=>"N' i","んにゅ"=>"N' M","んにぇ"=>"N' e","んにょ"=>"N' o",

"が"=>"g a",   "ぎ"=>"g' i",  "ぐ"=>"g M",   "げ"=>"g e",   "ご"=>"g o",
"ざ"=>"dz a",  "じ"=>"dZ i",  "ず"=>"dz M",  "ぜ"=>"dz e",  "ぞ"=>"dz o",
"だ"=>"d a",   "ぢ"=>"dZ i",  "づ"=>"dz M",  "で"=>"d e",   "ど"=>"d o",
"ば"=>"b a",   "び"=>"b' i",  "ぶ"=>"b M",   "べ"=>"b e",   "ぼ"=>"b o",
"ぱ"=>"p a",   "ぴ"=>"p' i",  "ぷ"=>"p M",   "ぺ"=>"p e",   "ぽ"=>"p o",
"きゃ"=>"k' a","きぃ"=>"k' i","きゅ"=>"k' M","きぇ"=>"k' e","きょ"=>"k' o",
"しゃ"=>"S a", "しぃ"=>"S i", "しゅ"=>"S M", "しぇ"=>"S e", "しょ"=>"S o",
"ちゃ"=>"tS a","ちぃ"=>"tS i","ちゅ"=>"tS M","ちぇ"=>"tS e","ちょ"=>"tS o",
"にゃ"=>"J a", "にぃ"=>"J i", "にゅ"=>"J M", "にぇ"=>"J e", "にょ"=>"J o",
"ひゃ"=>"C a", "ひぃ"=>"C i", "ひゅ"=>"C M", "ひぇ"=>"C e", "ひょ"=>"C o",

"ふゃ"=>"p\\' a","ふぃ"=>"p\\' i","ふゅ"=>"p\\' M","ふぇ"=>"p\\' e","ふょ"=>"p\\' o",
"みゃ"=>"m' a","みぃ"=>"m' i","みゅ"=>"m' M","みぇ"=>"m' e","みょ"=>"m' o",
"りゃ"=>"4' a","りぃ"=>"4' i","りゅ"=>"4' M","りぇ"=>"4' e","りょ"=>"4' o",
"ぎゃ"=>"g' a","ぎぃ"=>"g' i","ぎゅ"=>"g' M","ぎぇ"=>"g' e","ぎょ"=>"g' o",
"じゃ"=>"Z a", "じぃ"=>"Z i", "じゅ"=>"Z M", "じぇ"=>"Z e", "じょ"=>"Z o",
"じゃ"=>"dZ a","じぃ"=>"dZ i","じゅ"=>"dZ M","じぇ"=>"dZ e","じょ"=>"dZ o",
"ぢゃ"=>"dZ a","ぢぃ"=>"dZ i","ぢゅ"=>"dZ M","ぢぇ"=>"dZ e","ぢょ"=>"dZ o",
"びゃ"=>"b' a","びぃ"=>"b' i","びゅ"=>"b' M","びぇ"=>"b' e","びょ"=>"b' o",
"ぴゃ"=>"p' a","ぴぃ"=>"p' i","ぴゅ"=>"p' M","ぴぇ"=>"p' e","ぴょ"=>"p' o",
"ふぁ"=>"p\\ a","ふぃ"=>"p\\ i","ふぅ"=>"p\\ M","ふぇ"=>"p\\ e","ふぉ"=>"p\\ o",
"てゃ"=>"t' a","てぃ"=>"t' i","てゅ"=>"t' M","てぇ"=>"t' e","てょ"=>"t' o",
"でゃ"=>"d' a","でぃ"=>"d' i","でゅ"=>"d' M","でぇ"=>"d' e","でょ"=>"d' o",
"ぁ"=>"h\\ a", "ぃ"=>"h\\ i",  "ぅ"=>"h\\ M","ぇ"=>"h\\ e", "ぉ"=>"h\\ o",
"っ"=>"tS  ",
"すぃ"=>"s i", "ずぃ"=>"dz i", "とぅ"=>"t M","どぅ"=>"d M",

"ア"=>"a",  "イ"=>"i",   "ウ"=>"M",    "エ"=>"e",    "オ"=>"o",
"カ"=>"k a","キ"=>"k' i","ク"=>"k M",  "ケ"=>"k e",  "コ"=>"k o",
"サ"=>"s a","シ"=>"S i", "ス"=>"s M",  "セ"=>"s e",  "ソ"=>"s o",
"タ"=>"t a","チ"=>"tS i","ツ"=>"ts M", "テ"=>"t e",  "ト"=>"t o",
"ナ"=>"n a","ニ"=>"J i", "ヌ"=>"n M",  "ネ"=>"n e",  "ノ"=>"n o",
"ハ"=>"h a","ヒ"=>"C i", "フ"=>"p\\ M","ヘ"=>"h e",  "ホ"=>"h o",
"マ"=>"m a","ミ"=>"m' i","ム"=>"m M",  "メ"=>"m e",  "モ"=>"m o",
"ヤ"=>"j a",             "ユ"=>"j M",  "イェ"=>"j e","ヨ"=>"j o",
"ラ"=>"4 a","リ"=>"4' i","ル"=>"4 M",  "レ"=>"4 e",  "ロ"=>"4 o",
"ワ"=>"w a","ヰ"=>"w i",
#        "ヱ"=>"w e",
"ヲ"=>"o",  "ウィ"=>"w i",             "ウェ"=>"w e",
"ン"    =>"n",
#"ンガ"  =>"N a", "ンギ"=>"N i",   "ング"=>"N M",   "ンゲ"=>"N e",   "ンゴ"=>"N o",
#"ンニャ"=>"N' a","ンニィ"=>"N' i","ンニュ"=>"N' M","ンニェ"=>"N' e","ンニョ"=>"N' o",
"ガ"=>"g a",   "ギ"=>"g' i",  "グ"=>"g M",   "ゲ"=>"g e",   "ゴ"=>"g o",
"ザ"=>"dz a",  "ジ"=>"dZ i",  "ズ"=>"dz M",  "ゼ"=>"dz e",  "ゾ"=>"dz o",
"ダ"=>"d a",   "ヂ"=>"dZ i",  "ヅ"=>"dz M",  "デ"=>"d e",   "ド"=>"d o",
"バ"=>"b a",   "ビ"=>"b' i",  "ブ"=>"b M",   "ベ"=>"b e",   "ボ"=>"b o",
"パ"=>"p a",   "ピ"=>"p' i",  "プ"=>"p M",   "ペ"=>"p e",   "ポ"=>"p o",
#                             "ヴ"=>""p M",
"キャ"=>"k' a","キィ"=>"k' i","キュ"=>"k' M","キェ"=>"k' e","キョ"=>"k' o",
"シャ"=>"S a", "シィ"=>"S i", "シュ"=>"S M", "シェ"=>"S e", "ショ"=>"S o",
"チャ"=>"tS a","チィ"=>"tS i","チュ"=>"tS M","チェ"=>"tS e","チョ"=>"tS o",
"ニャ"=>"J a", "ニィ"=>"J i", "ニュ"=>"J M", "ニェ"=>"J e", "ニョ"=>"J o",
"ヒャ"=>"C a", "ヒィ"=>"C i", "ヒュ"=>"C M", "ヒェ"=>"C e", "ヒョ"=>"C o",

"フャ"=>"p\\' a","フィ"=>"p\\' i","フュ"=>"p\\' M","フェ"=>"p\\' e","フョ"=>"p\\' o",
"ミャ"=>"m' a",  "ミィ"=>"m' i",  "ミュ"=>"m' M",  "ミェ"=>"m' e",  "ミョ"=>"m' o",
"リャ"=>"4' a",  "リィ"=>"4' i",  "リュ"=>"4' M",  "リェ"=>"4' e",  "リョ"=>"4' o",
"ギャ"=>"g' a","ギィ"=>"g' i","ギュ"=>"g' M","ギェ"=>"g' e","ギョ"=>"g' o",
"ジャ"=>"Z a", "ジィ"=>"Z i", "ジュ"=>"Z M", "ジェ"=>"Z e", "ジョ"=>"Z o",
"ジャ"=>"dZ a","ジィ"=>"dZ i","ジュ"=>"dZ M","ジェ"=>"dZ e","ジョ"=>"dZ o",
"ヂャ"=>"dZ a","ヂィ"=>"dZ i","ヂュ"=>"dZ M","ビェ"=>"dZ e","ビョ"=>"dZ o",
"ビャ"=>"b' a","ビィ"=>"b' i","ビュ"=>"b' M","ビェ"=>"b' e","ビョ"=>"b' o",
"ピャ"=>"p' a","ピィ"=>"p' i","ピュ"=>"p' M","ピェ"=>"p' e","ピョ"=>"p' o",
"ファ"=>"p\\ a","フィ"=>"p\\ i","フゥ"=>"p\\ M","フェ"=>"p\\ e","フォ"=>"p\\ o",
"テャ"=>"t' a", "ティ"=>"t' i", "テゥ"=>"t' M", "テェ"=>"t' e", "テォ"=>"t' o",
"デャ"=>"d' a", "ディ"=>"d' i", "デゥ"=>"d' M","デェ"=>"d' e",  "デォ"=>"d' o",
"ァ"=>"h\\ a", "ィ"=>"h\\ i",   "ゥ"=>"h\\ M", "ェ"=>"h\\ e",   "ォ"=>"h\\ o",
"ッ"=>"tS  ",
"スィ"=>"s i", "ズィ"=>"dz i", "トゥ"=>"t M","ドゥ"=>"d M",

","=>"br1","、"=>"br1", "。"=>"br2","!"=>"br2","?"=>"br2",
"("=>"br4","『"=>"br4","「"=>"br4"
);
  my $i=0;
  for($i=0; $i<@myWords; $i++) {
    #
    # 現在着目している単語
    #
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;
    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];

    if( !defined($thisWord19) || length($thisWord19)==0 ) {
      $myWords[$i] = sprintf("%s\x0d\n",$thisWord);
    } else {
      my( $hinsi, $yomi ) = (split( /,/, $thisWord19 ))[0,8];
      my $lyricPhonetics = "";    # 歌詞と発音の構造体
      my $phoneticCount = 0;
#
# 読みに対応したミクの歌詞と発音記号の構造体を得る
#
      my $idxYomi;
      for($idxYomi=0; $idxYomi<(length($yomi)-1);) {
#
# UTF8 の3文字(9bytes)→2文字→1文字の優先順で
# カタカナとミクの発音テーブルから、発音記号を取得する。
#
        my $myLyric = "";
        my $myPhonetic = "";
        my $myLyricLen = 0;
        for($myLyricLen=9; $myLyricLen>=3; $myLyricLen-=3) {
          $myLyric = substr($yomi,$idxYomi,$myLyricLen);
          if( exists($phonetic{$myLyric}) ) {
            $myPhonetic = $phonetic{$myLyric};
            $phoneticCount++;
            last;
          } elsif( $myLyricLen<=3 ) {
            $myPhonetic = "";
            last;
          }
        }
        $idxYomi += $myLyricLen;
#
# 発音の直後が長音記号「ー」「-」のときは歌詞に長音記号を付加する。
#
        if( $myPhonetic ne "" ) {
          for(;;) {
            my $myLyric_appendix = substr($yomi,$idxYomi,3);
            if( $myLyric_appendix ne "ー" && $myLyric_appendix ne "-" ) {
              last;
            }
            $phoneticCount++;
            $myLyric .= $myLyric_appendix;
            $idxYomi += 3;
          }
          $lyricPhonetics .= $myLyric.":".$myPhonetic.";";
        } else {
          $lyricPhonetics .= ":;";
        }
      }
      $myWords[$i] = sprintf("%s\t%s,,,,,,,,%s,%s,%d\x0d\n",
        $midasi, $hinsi, $yomi, $lyricPhonetics, $phoneticCount );
    }
  }
  my $result = "";
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    $result .= $thisWord;
  }
  return $result;
}
########################################################################
#
#   サブルーチン名:AddSeparator
#
#    区切りを入れる。
#
#    発音区切 "W575", 息継区切 "BR", 文末区切 "EOS"
#    区切りの場合にはタブ等は無く、そのまま改行記号が入る。
#
sub AddSeparator {
  my @myWords = split(/\n/, $_[0]);
  my $phoneticCountFromW575 = 0;
  my $myHinsiLast = "";

  my $i=0;
  for($i=0; $i<@myWords; $i++) {
#   
# 現在着目している単語の各要素を切り出す。
#   
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;
    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];
    if( !defined($thisWord19) || length($thisWord19) == 0 ) {
#
#     区切りそのものだった場合は次の語の判断に入る
#
      $myHinsiLast = "";
      $phoneticCountFromW575 = 0;
      next;
    }
    if( $i == @myWords - 1) {
#
# 終端の単語は常に文末とする。
#
      $myWords[$i] = sprintf("%s\x0d\n%s\x0d\n", $thisWord, "EOS" );
      next;
    }
    my( $hinsi, $yomi, $lyricphonetics, $phoneticCount )
      = (split( /,/, $thisWord19 ))[0,8,9,10];
    $phoneticCountFromW575 += $phoneticCount;

    my $nextWord = $myWords[$i+1];
    chomp($nextWord);
    $nextWord =~ s/\x0d//g;
    my( $nextMidasi, $nextWord19 ) = (split( /\t/, $nextWord ))[0,1];

    if( (!defined($nextWord19) || length($nextWord19) == 0)
    &&    $nextMidasi eq "EOS" ) {
#    
#       既にMecabが文末 "EOS" を判定したら、新たな判定は不要。
#    
      next;
    }
    my( $nextHinsi ) = (split( /,/, $nextWord19 ))[0];

    my $mySeparator = "";
    if( $midasi eq "。" ||  $midasi eq "!" ||  $midasi eq "?" ) {
      $mySeparator = "EOS";
    } elsif( 0 <= index($lyricphonetics,"br") ) {
      $mySeparator = "BR";
    }
    if( length($mySeparator) == 0 ) {
      if( $phoneticCountFromW575 < 5 ) {
#
# 何もしない。
#
        ;
      } elsif( 5 <= $phoneticCountFromW575 && $phoneticCountFromW575 <= 7 ) {
#
# 5音節~7音節を発音し、かつ文節の頭となる単語だったら、そこで区切って発音する。
#
        if(($hinsi ne "名詞"     && $hinsi ne "形容詞" && $hinsi ne "形容動詞"
        &&  $hinsi ne "接頭詞"   && $hinsi ne "感動詞" && $hinsi ne "接頭辞"
        &&  $hinsi ne "副詞" )
        && ($nextHinsi eq "名詞"     || $nextHinsi eq "形容詞" || $nextHinsi eq "形容動詞"
        ||  $nextHinsi eq "接頭詞"   || $nextHinsi eq "感動詞" || $nextHinsi eq "接頭辞"
        ||  $nextHinsi eq "副詞" ) ) {
          $mySeparator = "W575";
        }
      } else {
#
# 発音があまりに長く8音節以上継続する場合には、次が名詞等(動詞を含む)ならば区切る。
#
        if(($nextHinsi eq "名詞"   || $nextHinsi eq "形容詞" ||  $nextHinsi eq "形容動詞"
        ||  $nextHinsi eq "接頭詞" || $nextHinsi eq "感動詞" ||  $nextHinsi eq "接頭辞"
        ||  $nextHinsi eq "副詞"   || $nextHinsi eq "動詞" ) ) {
          $mySeparator = "W575";
        }
      }
    }
    $myHinsiLast = $hinsi;
    $myWords[$i] = sprintf("%s\x0d\n", $thisWord );
    if( defined($mySeparator) && length($mySeparator) != 0 ) {
      $phoneticCountFromW575 = 0;
      $myHinsiLast = "";
      $myWords[$i] .= sprintf("%s\x0d\n", $mySeparator );
    }
  }
#
#
#
  my $result = "";
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    if( length($thisWord) != 0 ) {
      $result .= $thisWord;
    }
  }
  return $result;
}
########################################################################
#
#   サブルーチン名:ParseSentence
#
#    文章全体を解析する。
#
#    Mecab拡張形式入力
#
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#   9,ミク発音         :$lyricPhonetics
#    10,発音数          :$phoneticCount
#
#    Mecab拡張形式出力(●部分)
#
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#   9,ミク発音         :$lyricPhonetics
#    10,発音数          :$phoneticCount
# ●11,文章終端までの形態素数  :$eosCount
# ●12,息継ぎまでの形態素数   :$brCount
# ●13,575区切りまでの形態素数:$w575Count
#
#
sub ParseSentence {
  my @myWords = split(/\n/, $_[0]);
  my $myEosCount  = 0;
  my $myBrCount   = 0;
  my $myW575Count = 0;

  my $i=0;
  for($i=@myWords-1; $i>=0; $i--) {
    #
    # 現在着目している単語
    #
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;
    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];
    if( !defined($thisWord19) || length($thisWord19)==0 ) {
      if( $midasi eq "EOS" ) {
        $myEosCount  = 0;
        $myBrCount   = 0;
        $myW575Count = 0;
      } elsif( $midasi eq "BR" ) {
        $myBrCount   = 0;
        $myW575Count = 0;
      } elsif( $midasi eq "W575" ) {
        $myW575Count = 0;
      }
      $myWords[$i] = sprintf("%s\x0d\n",$thisWord);
    } else {
      my( $hinsi, $yomi, $lyricphonetics, $phoneticCount )
      = (split( /,/, $thisWord19 ))[0,8,9,10];

      $myWords[$i] = sprintf("%s,%d,%d,%d\x0d\n",
        $thisWord,$myEosCount,$myBrCount,$myW575Count );
      if( $phoneticCount != 0 && index($lyricphonetics,"br") < 0 ) {
        $myEosCount++;
        $myBrCount++;
        $myW575Count++;
      }
    }
  }
  my $result = "";
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    $result .= $thisWord;
  }
  return $result;
}
########################################################################
#
# 現在のセッションを識別する文字列を生成する(年月日時分妙から生成)
# なお、hack されにくくするため末尾に8桁の乱数を付加する。
#
sub GetSessionId {
#  my $ss,$mn,$hh, $dd, $mm, $yy, $yb;
  my ($ss, $mn, $hh, $dd, $mm, $yy, $yb) = localtime(time);
  $yy += 1900;
  $mm++;
  my $mySessionId = sprintf("%04d%02d%02d%02d%02d%02d%08d",
    $yy, $mm, $dd, $hh, $mn, $ss, int(rand(99999999)));
  return $mySessionId;
}
########################################################################
#
#    形態素の正当性チェック:行が 'EOS' または TAB を含めば正当とする。
#    正当ならば 0、不当ならばエラー行番号を返すこと。
#
sub checkMa {
  my @myWords = split(/\n/, $_[0]);
  my $mySessionId = $_[1];

  my $lineNumber = 1;
  my $thisWord = "";
  foreach $thisWord (@myWords) {
    chomp($thisWord);
    if( substr($thisWord,0,3) eq "EOS" ) {
      next;
    }
    my( $midasi, $thisWord2 ) = (split(/\t/, $thisWord))[0,1];
    if( length($thisWord2) == 0 ) {
      return $lineNumber;
    }
    $lineNumber++;
  }
  return 0;
}
########################################################################
#
#   サブルーチン名:mecab2VsqGenerate
#
#   機能:Mecab 拡張形式からVSQファイルを生成する
#
#   第1引数:Mecabの出力
#   第2引数:出力VSQファイル名
#
#    Mecab拡張形式入力
#
#    意味             :変数
#-------------------------------------------------
#    見出し            :$midasi
#    タブ区切り
#     0,品詞           :$hinsi
#     8,読み           :$yomi
#   9,ミク発音         :$lyricPhonetics
#    10,発音数          :$phoneticCount
#    11,文章終端までの形態素数  :$eosCount
#    12,息継ぎまでの形態素数   :$brCount
#    13,575区切りまでの形態素数:$w575Count
#
#
sub mecab2VsqGenerate {
my @myWords = split(/\n/, $_[0]);
my $myVsqFile = $_[1];

#
# マスタートラックのイベント定義。
#
my @masterEvents = (
  ['track_name',    0, 'Master Track'],
  ['set_tempo',     0, 500_000], # 1qn = .50 seconds
  ['time_signature',0,4,2,24,8 ],
  ['end_track' ,    0],
);
#
# ミクの発音用テキストに於ける初期値の設定。
#
  my @myCommonSection =();
  push @myCommonSection, "[Common]";
  push @myCommonSection, "Version=DSB301";
  push @myCommonSection, "Name=Voice1";
  push @myCommonSection, "Color=181,162,123";
  push @myCommonSection, "DynamicsMode=1";
  push @myCommonSection, "PlayMode=1";

  my @myMasterSection =();
  push @myMasterSection, "[Master]";
  push @myMasterSection, "PreMeasure=4";

  my @myMixerSection =();
  push @myMixerSection, "[Mixer]";
  push @myMixerSection, "MasterFeder=0";
  push @myMixerSection, "MasterPanpot=0";
  push @myMixerSection, "MasterMute=0";
  push @myMixerSection, "OutputMode=0";
  push @myMixerSection, "Tracks=1";
  push @myMixerSection, "Feder0=0";
  push @myMixerSection, "Panpot0=0";
  push @myMixerSection, "Mute0=0";
  push @myMixerSection, "Solo0=0";

  my @myEventListSection =();
  push @myEventListSection, "[EventList]";
  push @myEventListSection, "0=ID#0000";

  my @myIDSection =();
  push @myIDSection, "[ID#0000]";
  push @myIDSection, "Type=Singer";
  push @myIDSection, "IconHandle=h#0000";

  my @myHandleSection =();
  push @myHandleSection, "[h#0000]";
  push @myHandleSection, "IconID=\$07010000";
  push @myHandleSection, "IDS=Miku";
  push @myHandleSection, "Original=0";
  push @myHandleSection, "Caption=";
  push @myHandleSection, "Length=1";
  push @myHandleSection, "Language=0";
  push @myHandleSection, "Program=0";

  my @myDynamicsBPListSection = ();
  push @myDynamicsBPListSection, "[DynamicsBPList]";

  my @myPitchBendBPListSection = ();
  push @myPitchBendBPListSection, "[PitchBendBPList]";

  my @myPitchBendSensBPListSection = ();
  push @myPitchBendSensBPListSection, "[PitchBendSensBPList]";
  push @myPitchBendSensBPListSection, "7680=6";

  my @mikuMidiEvents = ();
  push @mikuMidiEvents,['control_change' , 0, 0,  99, 96];

#
#  MIDIイベントを生成する。
#
  my $myPhoneticTotalCount = 0;    # 発音数のカウント
  my $pitch_normal = 120;        # 通常の発音期間 [mSEC]
  my $pitch_important = 180;    # 重要語の発音期間 [mSEC]
  my $pitch_bress = 240;        # 息継ぎの発音期間 [mSEC]
  my $note = 64;                # ノート(音の高さ)
  my $myIdPos = 7680;            # 発音タイミング [mSEC]
  my $myIdPosLast = $myIdPos;    # 直前の発音タイミング
  my $myHinsiLast = "";            # 直前の品詞
  my $myPitchBendInit  = 2400;    # ピッチベンドの初期値
  my $myPitchBend = $myPitchBendInit;    # ピッチベンドのベース
  my $myPitchBendHinsi = 0;                # 品詞毎のピッチベンドの差分
  my $myPitchBendDelta = 0;                # ピッチベンド変化量の初期値
  my $myLyricCount = 0;                    # 仮名文字数(息継ぎのため)
  my $myIsBress    = 0;                    # ブレスを使ったか
  my $myProminence = 1;                    # 発音のプロミネンスか?
  my $lastSeparator = "";
  my $nextSeparator = "";

  my $i=0;
  for($i=0; $i<@myWords; $i++) {
    my $thisWord = $myWords[$i];
    chomp($thisWord);
    $thisWord =~ s/\x0d//g;

    my( $midasi, $thisWord19 ) = (split( /\t/, $thisWord ))[0,1];
    if( !defined($thisWord19) || length($thisWord19) == 0 ) {
      $lastSeparator = $midasi;
      if( $lastSeparator eq "EOS" ) {
        $myProminence = 1;                    # 発音のプロミネンスか?
        $myIdPos += 240;                    # ブレスと文末に必要な間隔
        $myPitchBend = $myPitchBendInit;    # ピッチベンドの初期値。
      } elsif( $lastSeparator eq "BR" ) {
        $myProminence = 1;                    # 発音のプロミネンスか?
        $myIdPos += 120;                    # ブレスに必要な間隔
        $myPitchBend = $myPitchBendInit;    # ピッチベンドの初期値。
      } elsif( $lastSeparator eq "W575" ) {
        $myProminence = 1;                    # 発音のプロミネンスか?
        $myIdPos += 60;                        # 575区切りに必要な間隔
        if( $myPitchBend < -3600 ) {
          $myPitchBend = 0;    # ピッチベンドの初期値。
        }
      }
      next;
    }
    my( $hinsi,
        $yomi,
        $lyricPhonetics,
        $phoneticCount,
        $eosCount,
        $brCount,
        $w575Count ) = (split( /,/, $thisWord19 ))[0,8,9,10,11,12,13];

    my $nextWord = $myWords[$i+1];
    chomp($nextWord);
    $nextWord =~ s/\x0d//g;
    my( $nextMidasi, $nextWord19 ) = (split( /\t/, $nextWord ))[0,1];
    if( !defined($nextWord19) || length($nextWord19) == 0 ) {
      $nextSeparator = $nextMidasi;
    } else {
      $nextSeparator = "";
    }
#
# 記号の区切りであったとき。
#
    if( $nextSeparator eq "BR" || $nextSeparator eq "EOS" ){
#
# 無音期間を設ける
#
      $myIdPos += 120;                    # ブレスに必要な間隔
      $myPitchBend = $myPitchBendInit;    # ピッチベンドの初期値。
    }
    if( $midasi eq "「" || $midasi eq "『" || $midasi eq "(" ) {
       if( $note < 70 ) { # E5 の音階は88
         $note += 1;
       }
    }
    if( $midasi eq "」" || $midasi eq "』" || $midasi eq ")" ) {
       if( 64 < $note ) {    # A3 の音階は69
         $note -= 1;
       }
    }
#
# 特殊(記号)でかつ発音がなければ、1文字分の期間をおく。
#
    if(($hinsi eq "特殊" || $hinsi eq "記号")
    &&  $phoneticCount == 0 ) {
      $myIdPos += 120;
      next;
    }
#
# 品詞ごとの音量を規定する。
#
    if( $hinsi eq "名詞" ) {
      push @myDynamicsBPListSection, ($myIdPos)."=80";
    } elsif( $hinsi eq "形容詞" || $hinsi eq "形容動詞"
    ||  $hinsi eq "接頭詞" || $hinsi eq "感動詞" || $hinsi eq "接頭辞"
    ||  $hinsi eq "副詞" ) {
      push @myDynamicsBPListSection, ($myIdPos)."=72";
    } else {
      push @myDynamicsBPListSection, ($myIdPos)."=64";
    }

#
# 読みに対応したミクの発音記号を得る。
#
    my $lyricCount = 0;
    my @eachLyricPhonetics = split( /;/, $lyricPhonetics );
    my $thisLyricPhonetic = "";
    foreach $thisLyricPhonetic (@eachLyricPhonetics) {
      my ($thisLyric, $thisPhonetic ) = split(/:/,$thisLyricPhonetic);
      my $myLength = 120;
#
#     文末の「。?!」は長く息継ぎする。
      if( $nextSeparator = "EOS" && substr($thisPhonetic,0,2) eq "br" ) {
        $myLength = 240;
      }
#
#    長音記号があったならば、その分は長く発音する。
#
      if( 0 < index($thisLyric,"ー",0) ) {
        $myLength *= (length($thisLyric) - index($thisLyric,"ー",0))/3 + 1;
        $thisLyric = substr($thisLyric,0,index($thisLyric,"ー",0));
      } elsif( 0 < index($thisLyric,"-",0) ) {
        $myLength *= (length($thisLyric) - index($thisLyric,"-",0))/3 + 1;
        $thisLyric = substr($thisLyric,0,index($thisLyric,"-",0));
      }
#
# 語尾ならば、ピッチを下げて発音する。
#
      if( $eosCount == 0 ) {
        $myPitchBendDelta = -400;
        $myPitchBendHinsi = -3600;
        if( $nextMidasi eq "?" && $lyricCount == $phoneticCount - 1) {
#
# 疑問文のときは語尾を上げる。
#
          $myPitchBendDelta = +400;
        }
      } elsif( $brCount == 0 ) {
#
# もし、ブレス直前だったならばトーンを落とす。
#
        $myPitchBendHinsi = -3600;
        $myPitchBendDelta = -400;
      } else {
#
# もし、以下の品詞だったならば、自然な音節の下降を付与する。
#
        if( $hinsi eq "名詞"   || $hinsi eq "形容詞" || $hinsi eq "形容動詞"
        ||  $hinsi eq "接頭詞" || $hinsi eq "感動詞" || $hinsi eq "接頭辞"
        ||  $hinsi eq "副詞" ) {
          $myPitchBendDelta = -200;
          $myPitchBendHinsi = 0;
          if( $hinsi eq "名詞" && $lyricCount == 0 && 2 < $phoneticCount && $myLength == 120) {
            $myPitchBendDelta = +400;
          }
        } else {
          $myPitchBendDelta = -200;
          $myPitchBendHinsi = -1200;
          if( $w575Count == 0 ) {
            $myPitchBendHinsi = -2400;
          }
        }
      }

      if( $myProminence == 1 ) {
        $myPitchBendDelta = +400;
        $myProminence = 0;
      }

      if( $thisPhonetic ne "" ) {
        push @myEventListSection, sprintf("%d=ID#%04d",$myIdPos,$myPhoneticTotalCount+1);
        push @myIDSection, sprintf("[ID#%04d]",$myPhoneticTotalCount+1);
        push @myIDSection, "Type=Anote";
        push @myIDSection, "Length=".$myLength;
        push @myIDSection, "Note#=".$note;
#       if( $myPhoneticTotalCount == 0 ) {

#
# か行、が行、さ行、ざ行、「つ」はベロシティを大きく(子音を短く)
#
        my @phonetic_array  = split(/ /, $thisPhonetic);
        my $myConsonant = $phonetic_array[0];
        if( $myConsonant eq "k" || $myConsonant eq "g"
        ||  $myConsonant eq "s" || $myConsonant eq "dz" || $myConsonant eq "dZ"
        ||  $thisPhonetic eq "ts M") {
          push @myIDSection, "Dynamics=80";
        } elsif( $myConsonant eq "4" ) {
#
# ら行はベロシティを小さく(子音を長く)
#
          push @myIDSection, "Dynamics=20";
        } else {
          push @myIDSection, "Dynamics=50";
        }
          push @myIDSection, "PMBendDepth=6";          #20";
          push @myIDSection, "PMBendLength=0";
          push @myIDSection, "PMbPortamentoUse=0";
          push @myIDSection, "DEMdecGainRate=0";    #50";
          push @myIDSection, "DEMaccent=4";        #50";
#       }
        push @myIDSection, sprintf("LyricHandle=h#%04d", $myPhoneticTotalCount+1);
        push @myHandleSection, sprintf("[h#%04d]", $myPhoneticTotalCount+1);
        push @myHandleSection, "L0=\"". Jcode->new($thisLyric,'utf8')->sjis
          ."\",\"". $thisPhonetic."\",1.000000,64,0,0";

        if( substr($thisPhonetic,0,2) eq "br" ) {
          $myPitchBend = $myPitchBendInit;        # ピッチベンドの初期値
        } else {
          my $myLocalId = 0;
          for($myLocalId = 0; $myLocalId<$myLength; $myLocalId += 120 ) {
            $myPitchBend += $myPitchBendDelta*2;
            if( $myPitchBend < -8192 ) {
              $myPitchBend = -8192;
            } elsif( 8191 < $myPitchBend ) {
              $myPitchBend = 8191;
            }
            my $myPitchBendOut = $myPitchBend + $myPitchBendHinsi;
            if( $myPitchBendOut < -8192 ) {
              $myPitchBendOut = -8192;
            } elsif( 8191 < $myPitchBendOut ) {
              $myPitchBendOut = 8191;
            }
            push @myPitchBendBPListSection, ($myIdPos+$myLocalId)."=".$myPitchBendOut;
          }
        }
        $myIdPos += $myLength;
        if( $myPhoneticTotalCount == 0 ) {
          push @mikuMidiEvents,['control_change', 5760, 0, 99,  80];
        } else {
          push @mikuMidiEvents,['control_change', $myIdPos - $myIdPosLast, 0, 99,  80];
        }
        $myPhoneticTotalCount++;
      } else {
#       発音できない記号は、単に時間間隔を空ける。
        $myIdPos += $myLength;
      }
      $myIdPosLast = $myIdPos;
      $lyricCount++;
    }
    $myHinsiLast = $hinsi;
  }
  push @mikuMidiEvents,['end_track' , $pitch_normal+1920];
  push @myEventListSection, sprintf("%d=EOS",$myIdPos);
#
#  ミク発音用メタデータのセクションを結合する
#
  my $my_miku_phonetics="";
  my $phonetic = "";
  foreach $phonetic (@myCommonSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myMasterSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myMixerSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myEventListSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myIDSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myHandleSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myDynamicsBPListSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myPitchBendBPListSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  foreach $phonetic (@myPitchBendSensBPListSection) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
#
#  Voice1トラックのイベントを生成する。
#
my @voice1Events = (
  ['track_name',    0, 'Voice1'],
);
  for($i=0; $i*119<length($my_miku_phonetics); $i++) {
    push @voice1Events, ['text_event', 0,
      sprintf("DM:%04d:",$i).substr($my_miku_phonetics,$i*119,119) ];
  }
  my $mikuMidi = "";
  foreach $mikuMidi (@mikuMidiEvents) {
    push @voice1Events,$mikuMidi;
  }
#
# マスタートラックとVoice1トラックからVSQファイルを生成する。
#
  my $master_track = MIDI::Track->new({ 'events' => \@masterEvents });
  my $voice1_track = MIDI::Track->new({ 'events' => \@voice1Events });
  my $opus = MIDI::Opus->new(
    { 'format' => 1, 'ticks' => 480, 'tracks' => [ $master_track, $voice1_track ] } );
  $opus->write_to_file( $myVsqFile );
}

 なお、サーバー上で同プログラムを動かすためには、サーバー上に MIDI-Perl のファイル、CGIのモジュール及びJcodeのモジュールが必要です。infoseek はデフォルト状態では MIDI-Perl が存在しませんので、以下のファイルをサーバ上に転送しました。

(1) \cgi-bin 直下に MIDI.pm 及び Jcode.pm を転送する。
(2) \cgi-bin\MIDI に Event.pm, Opus.pm, Score.pm, Simple.pm, Track.pm, Filespec.pod を転送する。

| | コメント (2) | トラックバック (1)

400P=yuukiss氏のVSQファイルの解析#5

 zhuoさんが作成されたツール "Ripples 0.0.8" を使って、①人間の歌声のビブラート ②初音ミクのビブラート機能 ③400P=yuukiss氏の「ぼかんないんです><」 それぞれの音程(PIT)と音量(DYN)のグラフを描いて、②と③どちらが人間の歌声に近いか考察してみました。グラフの縦軸は音量(DYN)または音程(PIT)で、横軸は全て時間です。
 以下のグラフは Ripples 0.0.8 のテキスト出力を Excelでグラフ化したものです。Ripples を作成された zhuoさんに感謝いたします。

①人間の歌声のビブラート
 音量(DYN)と音程(PIT)は、約10Hzの正弦波であり、その振幅は次第に大きくなっています。これがビブラートとして認識されると判断いたします。時間が経過すると共に音量(DYN)と音程(PIT)は次第に下降します。これは人間の生理現象によるものです。
Mydearest_subete_dyn
Mydearest_subete_pit

②初音ミクのビブラート機能
 音量(DYN)には殆ど振幅は存在せず、音程(PIT)に約20Hzの弱い振幅が見られます。これがビブラートとして認識されると判断いたします。音量(DYN)と音程(PIT)ともに山なりのカーブを描き、全体として下降カーブを示します。
Miku_default_subete_dyn
Miku_default_subete_pit

③400P=yuukiss氏の「ぼかんないんです><」

 音量(DYN)と音程(PIT)は、約11Hzの綺麗な正弦波であり、その振幅は次第に大きくなっています。これがビブラートとして認識されると判断いたします。時間が経過すると共に音量(DYN)と音程(PIT)は次第に下降しており、人間の生理現象によるものを上手くシミュレートしています。

Vocannaidesu_subete_dyn
Vocannaidesu_subete_pit

 総合的に見て、②初音ミクのビブラート機能 よりも、③「ぼかんないんです><」の技法 の方が明瞭にビブラートを認識できると判断いたします。③はビブラートの振幅が明瞭で、周波数が人間の(自分の)ビブラートに近いからです。

 従来のVOCALOID向け楽曲の、ビブラートの効きが悪い部分に「ぼかんないんです><」技法を適用することで、ビブラート効果の改善が見込めると思われます。

| | コメント (0) | トラックバック (0)

400P=yuukiss氏のVSQファイルの解析#4

 zhuoさんが作成されたツール "Ripples 0.0.8" を使って、人間の歌声、特にビブラートがどのようなグラフを描くかを見てみました。ここに、Ripples を作成された zhuoさんに感謝いたします。
 本当は浜崎あゆみの生ボーカルが分析できるとよかったのですが、CDからボーカルをきれいに抽出できなかったので、やむをえず自分で(笑)歌ってみたものを分析しました。歌詞「すべて」の「」の部分にビブラートが聞こえているので、人間の歌唱のビブラートの実験サンプルとしては使えると思います。
 分析した歌声に対応する歌詞は「すべて」で、3つの発音要素を含み、音量(DYN)と音程(PIT)に対応する部分があります。全体として音量(DYN)と音程(PIT)が極めて高い相関を示す事発音要素の区切りごとに音量(DYN)の谷間がある事などもわかります。これらは400P=yuukiss氏の調教法の特徴でもあります。
 3番目の発音要素「」は音量(DYN)が約10Hzで振動しており、これがビブラートとして聞こえることが判ります。また、この振動波形は正弦波からほど遠い「汚い」波形であることに着目すべきです。音程(PIT)は目立った振動は見当たりません。これは自分の歌唱力の無さによるものか、それとも人間の歌唱はこのようなものなのかは不明です。また、音量(DYN)は右肩下がりとなっておりますが、これは肺の空気量が少なくなると音量が下がるという生理的現象によるものと思われます。

Mydearest_subete_cut

図1、自分の歌唱の音量(DYN)音程(PIT)

 次に、400P=yuukiss氏の VSQファイルに対応するWAVファイルを解析してみました。VSQファイルの音量(DYN)と音程(PIT)のパラメータがWAVファイル上にどのように反映されるかを見る事と、400P=yuukiss氏の VSQファイルのビブラートが、Ripples上にどのように反映されるかを見る事が目的です。

400_dyn_subete
図2、400P=yuukiss氏のVSQファイルのDYN(音量)

400_pit_sutete
図3、400P=yuukiss氏のVSQファイルの音階(PIT)

Subete
図4、400P=yuukiss氏のVSQファイルの音量(DYN)音程(PIT)

 Vocaloid Editor 上の音量(DYN)と音階(PIT)はWAVファイル上に精確に表されている事と、音量(DYN)のカーブは人間の(自分の)発音とほぼ一致している事が判ります。しかし、3番目の発音要素「」の音程は、約11Hzの綺麗な正弦波を描いており、人間の(自分の)音程とやや相違します。この相違点の理由は不明です。

結論:
 400P=yuukiss氏のVSQファイルは、人間の歌唱から変換したものではないと判断します。人間の歌唱を変換したならば綺麗な正弦波とはならない為です。400P=yuukiss氏は、人間の歌唱音の音程と音階を詳細に分析し、VSQファイル上に何らかの方法で再構成したのだと判断します。

| | コメント (0) | トラックバック (1)

iPod課金

iPod課金を提案=著作権法改正も-文化庁
5月8日16時32分配信 時事通信
http://headlines.yahoo.co.jp/hl?a=20080508-00000102-jij-soci

 著作権保護のためにデジタル方式の録音録画機器に補償金を課す制度について、文化庁は8日、iPodなどのデジタル携帯プレーヤーとハードディスク駆動装置(HDD)内蔵型録画機器を対象に加える見直し案を、文化審議会の私的録音録画小委員会に提示した。(以下略)

 自分はデジタル携帯プレーヤーへの補償金には反対します。さいきんの自分は市販の著作権コンテンツは殆ど聞いておらず、VOCALOIDオリジナル曲ばかりでを聞いており補償金を支払う理由がない事と、自分がiPodに入れているCDコンテンツは正規購入したもので、同様に補償金を支払う理由がない事です。

 著作権法の法目的は1条に記載されているように、文化の発展に寄与することです。

第一条  この法律は、著作物並びに実演、レコード、放送及び有線放送に関し著作者の権利及びこれに隣接する権利を定め、これらの文化的所産の公正な利用に留意しつつ、著作者等の権利の保護を図り、もつて文化の発展に寄与することを目的とする

 よって、著作権者等の権利の保護を図ることは手段にすぎず、また著作権者等の保護の上では文化的所産の公正な利用に留意しなければなりませんが、文化庁の施策は著作権者等の権利の保護に偏りすぎ、かつアナログ時代の補償金の風習をそのままデジタルコンテンツに適用したため、デジタル時代の文化的所産の公正な利用を阻害する恐れがあり、よって文化の発展に寄与できないように思えます。

| | コメント (0) | トラックバック (0)

Nostalogic

今日のiPod BGM はこちらを聞いてました。

「ぼかりす」の発表から間もなく、耳コピした曲を発表されるというのは只者ではないとは思っておりました。このオリジナル曲「 Nostalogic 」は、バックはやはり自らキーボードで演奏されたのでしょうか。

 もう少し400氏=yuukiss氏のVSQを解析をしてみます。発音要素の時間長さが100mSEC台のときのDYN/PITグラフを描いておらず、「ぼかんないんです><」の技法が完全には理解できていないのです。

 当該ブログをHPで紹介いただいておりまずzhuoさんも、400氏=yuukiss氏の手法の再現に挑戦しておられます。

Ripples 0.07

 既にツールまで作っておられるのがスゴイ! 果たして 「Dearest」の音程と音量はどうなっていたのでしょうか? 時間が出来たらすぐに、CDを買って Ripples の人柱となって試したいところです。

| | コメント (0) | トラックバック (0)

vocannaindesu

 当ブログで、謎の神調教師「400氏」のVSQファイル解析結果を記載しておりましたが、その400氏=yuukiss氏が動画をアップロードされ、当技術を「ぼかんないんです><」と命名されました。


 結局、このVSQファイルがどのような素性で出来上がったかのかは明示されていないのですが、「ぼかりす」を聞いた印象が、「あ、それってOKだったんですか」「じゃあ自分も一度やっちゃおうかな」というところから、何らかのスクリプトで自動生成したか、もしくは原曲の情報をツールで抜き出したのではないかと推定します。詳しくは次の「初音ミク」の作品のコメントを待ちたいと思います。

 自分としては、以下のコメントでニヤニヤしたり。

400_douga00

 yuukiss氏が、自らピアノを演奏できたりするのが、ちょっと羨ましかったり。

 来週から自分の子供をヤマハ音楽教室に通わせるので、付き添い「ついで」に自分もキーボードをこっそり練習しようかと考えています。

| | コメント (0) | トラックバック (0)

特開2002-221978

 400氏のVSQ解析中に、特開2002-221978「ボーカルデータ生成装置、ボーカルデータ生成方法および歌唱音合成装置」が、初音ミクに実装されている証拠らしきデータを得ました。特開2002-221978の要約を以下に引用します。

【課題】 音節を構成する音素のうち、子音に対向する音素を音符の発生タイミングにあわせて発声することにより、伴奏に合わせたバーチャルシンガによる自然な歌唱を実現する。
【解 決手段】 歌詞に対応した音節毎の発音タイミングデータを含むボーカルデータを予め記憶する。再生処理を始めると、音符「ド」に対応した音節「さ」を発声させると き、子音「s」の発声動作を音符の発音タイミングよりも前に始め、母音「a」の発音タイミングを音符「ド」の発音タイミングに合わせる。これにより、伴奏 に遅れることなく、バーチャルシンガによる自然な歌唱を可能にする。

 こちらが初音ミクの「あ [a]」の発音波形の図で、横軸が時間[秒]で縦軸が音声の振幅です。凡そ8.058秒から発音が始まっており、主たる母音は 8.070秒から発音されていることがわかります。

A_wav00_2
図1、初音ミクの「あ」の発音波形

 こちらは、全く同じタイミングで初音ミクが「か [ka] 」を発音したときの波形です。8.047秒から高い周波数成分の発音が始まり、8.070秒まで続き、その後に低い周波数成分が続きます。高い周波数成分は子音の[k]で、低い周波数成分は母音の[a]と思われます。
 この推測が正しいならば、初音ミクの子音成分は母音成分よりも先に発音されており、特開2002-221978に記載された発明が、初音ミクに実装されていると確認できたことになります。

Ka_wav00
図1、初音ミクの「か」の発音波形

| | コメント (1) | トラックバック (0)

400氏のVSQファイルの解析#3

 まずは最初に前回の解析結果に関する修正報告です。

 Vocaloid2 Editorは任意時間長の入力ができます。左上のLength と Quantize 双方ともにOFFにすると、任意時間長の入力が可能であることを確認いたしました。(下図参照)コメントいただいたkmさんに感謝いたします。400氏のVSQファイルに、30の倍数以外の時間長が記載されていたとしても、何ら不思議ではありません。よって、これだけの証拠で400氏が Vocaloid2 Editor を使用していないと推定したのは、やや勇み足でした。

 

Vocaloid2editor_off_off
図1、任意時間長を入力できる設定 (Length/Quantize 双方とも off)

 今回は、400氏のVSQファイルのうちPIT(ピッチベンド・音程)と、DYN(ダイナミックス・音量)について調査してみました。400氏がどのように神調教を実現し、VSQファイルを生成したかを知るためです。

1、パラメータ調査結果について
1)PIT(ピッチベンド・音程)
 横軸を時間[mSEC]、縦軸をピッチベンド(PIT)とし、400氏のVSQファイル中の歌詞「たいせつなあ」の「なあ」の部分を赤色で描き歌詞「すてて」の2番目の「て」の部分を青色で描いたものです。
 どちらも正弦波カーブが描かれており、これがビブラートとして人間に認識されます。赤色のグラフと青色のグラフの振幅と周期は極めて良く一致します。これだけ正確な正弦波を複数箇所で人間が描けるとは考えにくいです
 また、赤色のグラフは下端の-8192でクリップされていることに着目すべきです。
人間がVocaloid2 Editor でパラメータを描画した場合、下端でクリップされることは避けて描画すると思われます。 
400_pend500_pit_2
 こちらは、発音長が300mSEC~400mSEC の場合の発音要素(基本的に仮名1文字の発音)の PIT(ピッチベンド)の正弦波曲線です。周期が極めて良く一致していることが判ります。それぞれ微妙な周期ずれが有る理由は不明です。
400_pend300_pit

2)DYN(ダイナミックス・音量)
 文節の先頭・中間・末尾種別で、発音要素(仮名文字1文字)のDYN(ダイナミックス)のカーブが相違します。最初に文節の先頭部分をご覧ください。

 黄色の曲線が「ほんとうに」の「ほ」の発音要素、赤色の曲線が「もおのいがい」の「も」の発音要素、青色の曲線が「すてて」の「す」の発音要素のDYN(ダイナミックス)のカーブです。
 赤青黄の曲線すべてが発音要素の30mSECほど前から立ち上がっています。VOCALOIDは楽譜の母音のタイミングが楽譜のタイミングと一致させるため、子音を早めに発音している事と関係すると推定しました。子音の発音が始まる前からDYN(ダイナミックス)を上げておかないと、子音部分が聞き取れず、母音部分のみが強調された不自然な歌唱となります
 試しに初音ミクのデフォルト状態で「か」と「あ」を発音させた場合、「か」の方が20mSEC先に発音が始まりました。デフォルトの初音ミクでは子音は20mSEC先行して発音が始まるようですので、それを見越してDYN(ダイナミックス・音量)を調整する必要があります。
 また、400氏のVSQファイルは次の発音に入る直前に50mSEC程度、DYN(ダイナミックス・音量)を絞っています。これにより、人間が発音要素ごとに区切って喋るさまを表したのではと思います。
 赤青の曲線は良く一致していますが。黄色の曲線はやや他と乖離しています。この理由は不明です。
400_ptop_dyn

 文節の中間部分の発音要素のDYNグラフをご覧ください。グラフ形状が極めて良く相似します。 次の発音に入る直前に50mSEC程度、DYN(ダイナミックス・音量)を絞っている様子が観察できます。水色の曲線はやや他と相違していますが、その理由は不明です。
400_pmid_dyn
 文節の末尾部分の発音要素のDYNグラフをご覧ください。ビブラートを表す正弦波曲線と共に右方下がりの曲線となっていますが、肺の中の空気量が少なくなるにつれ音量が下がるという人間の生理現象を表現していると思われます。
400_pend_dyn

2、まとめ
 400氏は、Vocaloid2 Editor のパラメータ描画機能は使っていないと推定します。フリーハンドで描画したにしては、PIT(ピッチベンド・音程)の曲線が綺麗すぎ、周期が精確すぎるからです。また、人間がパラメータを描画した場合、PIT(ピッチベンド)の下端でクリップされることは避けて描画すると思われるからです。
 400氏は、WAVファイルをVSQ変換していないと推定します。人間の歌唱ファイルを元に変換したにしては、PIT(ピッチベンド・音程)の曲線が綺麗すぎ、かつ周期が精確すぎるからです。
 では、400氏はどうやってこの VSQファイルを作成したのでしょうか? そして400氏と「ぼかりす」とは何らかの関係を有しているのでしょうか?

3、400氏へのメッセージ
 PIT(ピッチベンド)の下端クリップや上端クリップを避ける為には、PBS(ピッチベンドセンシティビティ)の値を2に設定し、PIT(ピッチベンド)の値を半分にすればOKです。ご参考までに。

追記:400氏がまた書込まれていたようです。
http://pc11.2ch.net/test/read.cgi/streaming/1209997849/

716 名前:何スレか前の400 本日のレス 投稿日:2008/05/06(火) 08:57:45 U0wKRW7z0 ?

>>686 >>687 >>691 >>694
あー、mp3は消してしまいました。
調声もまだ途中だったし、カラオケ音源を使ったものを
いつまでも残しておくのもアレったので。

進捗状況ですが、MEIKOさんと初音ミクさんの音源はとりあえず完成しました。
今はMEIKOさんの動画をしこしこ制作中です。
実は、同時公開予定のオマケ(?)のほうが先に出来上がってしまったという。

「同時公開予定のオマケ?」とは、もしかして400氏流のDYN/PIT調整ツールでしょうか?

| | コメント (0) | トラックバック (0)

400氏のVSQファイルの解析#2

 400氏のVSQファイルの解析で見逃していたことがありましたので、ご報告します。

 まず最初に、Vocaloid2 Editor で作成したと思われるVSQファイル「奇跡の海」 Ver.1.1 の冒頭部を示します。Length (発音時間 [mSEC])は全て30の倍数となっており、この楽曲の場合のVocaloid2 Editor の最小時間設定単位が30mSECであったと思われます。

奇跡の海 Ver.1.1 のVSQファイルはこちらです。
http://www9.uploader.jp/dl/tukuru_koubou/tukuru_koubou_uljp00004.zip.html

[ID#0001]
Type=Anote
Length=60
Note#=62
Dynamics=63
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=0
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0001
[ID#0002]
Type=Anote
Length=480
Note#=63
Dynamics=96
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=3
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0002
VibratoHandle=h#0003
VibratoDelay=161
[ID#0003]
Type=Anote
Length=720
Note#=71
Dynamics=64
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=0
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0004
[ID#0004]
Type=Anote
Length=180
Note#=68
Dynamics=64
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=0
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0005
[ID#0005]
Type=Anote
Length=30
Note#=68
Dynamics=0
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=0
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0006
[ID#0006]
Type=Anote
Length=180
Note#=70
Dynamics=64
PMBendDepth=5
PMBendLength=1
PMbPortamentoUse=3
DEMdecGainRate=3
DEMaccent=3
LyricHandle=h#0007

次に、400氏のVSQファイルのメタテキストの一部をご覧ください。Lengthの値を太字にいたしました。

[ID#0021]
Type=Anote
Length=239
Note#=61
Dynamics=64
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0021
[ID#0022]
Type=Anote
Length=147
Note#=66
Dynamics=79
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0022
[ID#0023]
Type=Anote
Length=361
Note#=64
Dynamics=87
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0023
[ID#0024]
Type=Anote
Length=250
Note#=61
Dynamics=63
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0024
[ID#0025]
Type=Anote
Length=122
Note#=64
Dynamics=72
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0025
[ID#0026]
Type=Anote
Length=676
Note#=66
Dynamics=93
PMBendDepth=0
PMBendLength=0
PMbPortamentoUse=0
DEMdecGainRate=50
DEMaccent=50
LyricHandle=h#0026

 Vocaloid2 Editor は、縦が音階、横が時間を表す升目からなり、発音の長さなどは、設定最小単位以下は設定できませんし、任意時間長をVocaloid2 Editor 入力する方法は、寡聞にして知りません。
 しかし、上記のように400氏のVSQファイルは、発音の長さを任意に設定しています。
 よって、自分のVocaloid2 Editor に係る知識が不足しているのでなければ、400氏は Vocaloid2 Editor 以外の方法で、このVSQファイルを作成したと思われます。
 どのような方法でこのVSQファイルを作成したのでしょうか? 専用MIDIプログラム? それとも専用の変換ソフトウエア? そして400氏の正体は誰なのでしょうか?

| | コメント (2) | トラックバック (0)

中野さん-後藤さんのコメント

VocaListener の作者であらせられる:中野倫靖さん, 後藤 真孝さんのコメントがWEBに掲載されています。これで「ぼかりす=VocaListener」であることが確定しました。
http://staff.aist.go.jp/m.goto/VocaListener/index-j.html

2008年5月28日~29日に開催される 音楽情報科学研究会 にて学会発表予定の

      VocaListener: ユーザ歌唱を真似る歌声合成パラメータを自動推定するシステムの提案
      中野 倫靖, 後藤 真孝 (産総研)

のデモンストレーション動画の一部を、試験的に 【初音ミク】 PROLOGUE 【ぼかりす】 に掲載させて頂きました。(以下略)

この論文の筆頭執筆者の中野倫靖さんは、全く特許出願はヒットしませんでしたが、論文を検索すると幾つかヒットします。ずいぶん若い方なのかな?

・Voice Drummer:口ドラムでドラムを叩く楽譜入力インタフェース …… 101
 中野倫靖*,後藤真孝**,緒方淳**,平賀譲*
 *筑波大学図書館情報メディア研究科.**産業技術総合研究所
http://www.interaction-ipsj.org/archives/paper2005/pdf2005/interactive/A152.pdf

組織名から見ると、中野倫靖さんが筑波大学の学生だった頃のものでしょう。代表図を以下に引用します。
Voicedrummerping

3つの色分けされた領域のうち、オレンジ部分はドラム用の原楽譜、緑色部分は演奏者が「ドン」「トン」などを口頭で喋ることによって演奏された履歴、青色部分は演奏者の口頭での喋り部分が表示されます。何となく初音ミクのピアノロールエディタっぽいですね。

中野さんの技術専門分野は、音楽情報処理(音楽音響信号処理)で、学生の頃の研究でビブラート部分の自動検出などを試されていたようです。(以下図参照)
Nakano_00
中野さんはプライベートでは、筑波大学の管弦楽団でバイオリン奏者として活躍されていましたが、ヤマハ(株)の剣持秀樹さんも同様に管弦楽団でバイオリン奏者として活躍されています。音楽関係の研究者の趣味とは似通うものですね。

| | コメント (2) | トラックバック (1)

400氏のVSQファイル解析

 初音ミクみくの記事「出た!VocaListenerの秘密の一端解明か?謎の調教師が置き土産!」を見て、さっそく問題のVSQファイルを解析してみました。これにより、更に初音ミクの楽曲が高度なものとなれば幸いです。

 謎の調教師を仮に「400氏」と呼びます。400は初出のレス番号から由来するものです。

 「400氏」は噂の「ぼかりす」と匹敵するような高品質な初音ミクの歌声を作成してアップロードされ、歌声の元となるVSQファイルもアップロードされました。「400氏」のVSQファイルはこちらです。

http://www.42ch.net/UploaderSmall/source/1209596322.zip
pass=miku

(1)デフォルト歌唱スタイル

デフォルト歌唱スタイルですが、何も初期設定から変わっていません。

400_setting_2

 VEL(ベロシティ)/DYN(ダイナミックス)/PIT(ピッチベンド)のパラメータが操作されています。それ以外のBRE/BRI/CLE/GEN/POR/PBSは初期値のままです。

(2)VEL(ベロシティ)の操作の意味について

 VEL(ベロシティ)は子音の発音の強さで、小さいほど子音が強く表現されます。

 400氏のVSQファイルは、音節の最初ほどVEL(ベロシティ)が小さく、後ろにゆくほど大きくなっています。すなわち、文節の最初は子音を強く発音させ、文節の終端ほど子音を弱く発音させています。人間は文節ごとに息継ぎをします。息継ぎ後には強く発音されていた子音が、文節の終端ほど段々小さく発音されていく様を表したものとおもいます。

400_vel

(3)DYN(ダイナミックス)について
 DYN(ダイナミックス)は音量です。この値が大きければ音量が大きくなります。

 400氏のVSQファイルは、ある程度短い発音要素「す」は山なりに段々と大きくし、「べ」など極めて短い発音要素は極めて鋭い山なりにしています。
 特徴的なのは、ある程度長い発音要素の場合には、しだいに大きくなる正弦波カーブを描くことです。この正弦波によってビブラートを実現していると推定します。
 また、音節全体でゆるやかな山なりのカーブを描いている点も着目すべきです。ここでは「すべて」の山なりのカーブと、「すてて」の山なりのカーブが観察できます。

400_dyn

(4)PIT(ピッチベンド)について
 PIT(ピッチベンド)は音程です。この値が大きければ音程が高くなります。

 400氏のVSQファイルのPITをDYNと共に表示します、PITはDYNと極めて高い相関性をもって変化する特徴を有します。ただし、発音要素が短いときにはDYNは極めて大きな山なりカーブになるのに対して、PITは発音要素が短くても長くてもあまり変化せず、音節全体のカーブもゆるやかです。その代わり長い発音要素のときの正弦波状のカーブはDYNよりも振幅が大きいです。400氏のVSQファイルから感じるビブラートの主たる要素は、音程の周期的な変化で、従たる要素は音量の周期的な変化なのだと推定します。

400_pit

念押しでVSQファイルを直にエディタで見てみましたが、他に操作していたパラメータは見当たりませんでした。

 なお、MIKU_TALK の作成、及び400氏のVSQファイル解析にあたり、「日本語アクセントの概要」を参考とさせていただきました。

| | コメント (7) | トラックバック (0)

ぼかりす

 久しぶりに心踊るような技術が出てきました。まあ聞いてみてください。藤田咲さんが生で歌っているよと言われたら信じてしまいそうな出来ですが、これは「初音ミク」なんですよね。

さて、この「ぼかりす」ですが、2008年5月28日(水)に開催される「第75回音楽情報科学研究会」で研究成果として発表されるVocaListenerという技術だそうです。以下に表題と発表者を引用します。

(9) VocaListener: ユーザ歌唱を真似る歌声合成パラメータを自動推定するシステムの提案   
中野倫靖,後藤真孝(産総研)

 VocaListerner が何をやっているかは現時点では不明です。よって、さっそく後藤真孝さんの素性を調べてみました。とりあえず特許検索ということで、後藤さんの音関係の特許出願及び登録特許を列挙します。リンクを叩くとPDFが開きます。

特開2001-125562 音高推定方法及び装置

(57)【要約】
【課題】本発明は、入力音響信号に対してあるパート(メロディーやベース)の音高推定を可能にするために、混合音中で優勢な音高を推定することを目的としている。
【解決手段】本発明は、入力音響信号に対してマルチレート信号処理をおこなって瞬時周波数を計算し、瞬時周波数に関連した尺度に基づいて周波数成分の候補を抽出する。次に、2種類のバンドパスフィルタ(メロディーライン用とベースライン用)を適用し、それぞれの出力に基づいて、基本周波数(音高)の確率密度関数を求める。そして、マルチエージェントモデルを導入し、その確率密度関数の中で有望な各ピークの軌跡を異なるエージェントが追跡して、それぞれの信頼度を評価する。最後に、最も信頼度の高いエージェントが持つ優勢な基本周波数の軌跡を出力する。

特許3413634 音高推定方法及び装置(上記出願が権利化したもの)

特開2008-058753 音分析装置およびプログラム

(57)【要約】
【課題】 記憶する音モデルの個数が比較的少なくて済み、かつ、高い推定精度で基本周波数を推定できるようにする。
【解決手段】 音モデル補間処理5では、記憶装置に記憶された複数種類の音モデルに補間処理を施し、各音モデルの中間の基本周波数に対応した複数種類の音モデルを生成する。基本周波数の確率密度関数の推定41では、記憶された音モデルおよび補間処理により得られた音モデルを用いて、様々な基本周波数の音モデルの混合分布を構成し、この混合分布が入力音響信号の周波数成分の分布となるように、各音モデルに対する重み値を最適化し、最適化された各音モデルの重み値を音源の音の基本周波数の確率密度関数とする。

特開2008-058754 音分析装置およびプログラム

57)【要約】
【課題】 混合音を示す入力音響信号の周波数成分から各音の基本周波数を推定する際に、基本周波数の誤った推定が行われるのを防止する。
【解決手段】 周波数帯域の制限3では、入力音響信号から音源の音の基本周波数成分または高調波成分となる可能性のある周波数成分を抽出する。基本周波数の確率密度関数の推定41では、抽出された周波数成分が各々高調波構造を有し、異なる基本周波数に対応した音モデルの混合分布から生じたと考え、基本周波数の確率密度関数を推定する。音モデル変形処理5では、その際の誤推定の可能性を低減するための音モデルの変形を行う。

特開2008-058755 音分析装置およびプログラム

(57)【要約】
【課題】 EMアルゴリズムにより、入力音響信号から、鳴っている音の基本周波数を求める際に、楽器固有の事前知識を利用して、精度良く基本周波数を推定する。
【解決手段】 フォーム推定413では、EステップおよびMステップ411により各種の基本周波数に対応した重み値を逐次更新される過程において、音源構造データ413Fにより定義された制約条件を満たすように、重み値のピークの中から、発音されている可能性が高いと推定される音のものを選択する。事前分布付与414では、この選択したピークが強調されるように、各音モデルに対する重み値に事前分布を与える。

特開2008-058885 音高推定装置、音高推定方法およびプログラム

(57)【要約】
【課題】音高を高精度に推定する。
【解決手段】音響推定装置Dは、音響信号Vを複数の音モデルの混合分布としてモデル化したときの各音モデルの重み値ω[F]の分布である基本周波数の確率密度関数Pから音響信号Vの基本周波数F0を推定する装置である。関数推定部20は、重み値ω[F]を更新する単位処理を反復するEMアルゴリズムによって確率密度関数Pを推定する。重み値修正部22は、単位処理で算定された重み値ω[F]に現れる複数のピークのピーク値を増加させた修正値ωa[F]を、次回の単位処理で使用される重み値ω[F]として生成する。音高特定部40は、確率密度関数Pのピークに対応した基本周波数F0を特定する。

特開2008-058886 音高推定装置、音高推定方法およびプログラム

(57)【要約】
【課題】音高を高精度に推定する。
【解決手段】音響推定装置Dは、音響信号Vを複数の音モデルM[F]の混合分布としてモデル化したときの各音モデルM[F]の重み値ω[F]の分布である基本周波数の確率密度関数Pから音響信号Vの基本周波数F0を推定する装置である。重み値算定部23は、音モデルM[F]が音響信号Vの高調波構造を支持する程度を示す推定形状C[F]に基づいて重み値ω[F]を算定する。推定形状特定部21は、音響信号Vの振幅スペクトルSと音モデルM[F]と重み値ω[F]とに基づいて推定形状C[F]を特定する。類否解析部271は、音モデルM[F]とこの音モデルM[F]から特定された推定形状C[F]との類否を示す類否指標値R[F]を算定する。重み値修正部273は、重み値ω[F]のうち類否指標値R[F]が非類似を示す基本周波数Fの重み値ω[F]を低下させる。

 いずれの特許出願も音高(PIT)を高精度に推定するというもので、課題が共通しています。この中で、もっとも最初に出願された特開2001-125562(特願平11-305770)が「ぼかりす」に適用された発明ではないかと推定しました。以下に図5を引用します。人間の歌声を入力として、出力された melody line をボーカロイド2の音階に割り当てれば、かなり正確な音高が初音ミクで再現できるのではないでしょうか。

Jpa_2001125562_fig6

 しかし、「ぼかりす」は、音高(PIT)のみで出力しているにしては自然すぎ、更に幾つかの隠し技を入れているようにも思えます。詳しくは5月28日の有志の報告を待つことにしたいと思います。

 最初の特許を除く5件の特許は産業技術総合研究所とヤマハ株式会社の共同出願だったので、ちょっと驚いてしまいました。初音ミクのヒットの前から着実に活動していますね。この「ぼかりす」の仕掛け人も、恐らくヤマハ株式会社だったのでしょう。この5件の特許の出願日は初音ミク発売のおよそ1年前の2006年9月1日と9月4日で、共同発明者はいずれもヤマハ株式会社の藤島琢哉さんと有元慶太さんです。

追記:MiruSinger:歌を「歌って/聴いて/描いて」見る歌唱力向上支援インタフェース も何か関係するかもしれません。

論文はこちらです。

MiruSinger:歌を「歌って/聴いて/描いて」見る歌唱力向上支援インタフェース」。

 この論文には音高と共にビブラートを自動検出する技術が記載されており、著者のうち2人はVocaListernerと一致しています。よって、「ぼかりす」は MiruSinger と同様に音階と共にビブラートを検出して、VSQに反映させていると思われます。以下に論文の要点を引用します。

3 MiruSinger の実現方法
入力信号中で最も優勢な(パワーの大きい) 高調波構造を求める手法[4]混合音中で最も優勢な音高を推定する手法(PreFEst)[5]推定されたF0 軌跡の1 次差分の短時間フーリエ変換によってビブラートらしさを得る手法[3] を用いた。ただし、混合音からのF0 推定では、中高域で最も優勢な高調波構造を持つF0 がボーカルのF0 であると仮定した。

| | コメント (5) | トラックバック (1)

« 2008年4月 | トップページ | 2008年6月 »