June 2010 Archives

mugene-win: simple MML authoring pad

| No Comments | No TrackBacks

VSQ/Vocaloidサポート統合まわりで躓いていたmugeneのIDE?構想だけど(テキスト音楽サクラみたいなのを想像すると近い)、とりあえずSMFだけでも簡単に作れるようにしようと思って、やっつけで編集ツールを作ることにした。はずだったのだけど、いくつか問題に当たって、回避しているうちに時間が無くなってしまったので、とりあえずやっつけでコンパイルと再生しかしてくれないmugene-winというwinformsツールが出来上がった。寝る時間が近づいてきたので、手短に。

  • mugenelibのコンパイラのエントリポイントにいろいろ手を加えて、コンソール以外からの呼び出しにもあまり不自由しないようにした。
  • 99.99%のユースケースで取り込まれるマクロは全て取り込むことにした。これでコマンドライン引数にはMMLファイルを渡すだけでコンパイルできるようになった。従来のモードは --nodefault オプションで対応した(csc/gmcsの--noconfigみたいなものだ)。VSQサポートに使われるマクロは、発音命令の意味が変わるので取り込まないが、--vsq が指定されたら --nodefault が無い限り取り込むようにした。
  • monodevelopのtarball packagingまわりがうまく動作しないところにいろいろハマったので、いろいろ手直しした。

さてmugene-winは、今日コードを書き始めた時は、Scintilla.NETを使っていた。しかしこれはwin32依存になってしまうし、そこまでして作ってもおいしくない気もしている。エディタとしてはTextBoxよりはるかにまともそうだけど。あとmonoで動かすとどうもcodepage1361が無いと言われてエラーになってしまう。調べてみると、確かにハングルの後出し仕様なんて対応していない(encodingの実装が書かれたのは2001年とか2002年とかだ)。これはencodingの実装を加えないと、mono on windowsですら動かせない。というわけでScintillaは使わないことにした。

そうするとTextBoxでやるくらいでやっつける以外の方法を思いつかなかったのだけど、TextBoxをエディタとして使うというのはさすがにナンセンスすぎるので、とりあえず編集不能にして、ファイル選択だけやらせて、MMLの編集は好きなエディタでやりましょうね、というツールに方向を変えた。

それでも、まだSMFをビルドしてそれをPortMidiPlayerに渡して自動再生させるという作業がある。また、winformsではやらないかと思うが、どうせならmldspみたいなビジュアルプレイヤーと連動させたい。

まあ、とりあえずはこれでmugeneは今までよりもはるかに使いやすくなったはずだ。これでVocaloidと連動して曲が再生できるようになったら楽しいのだけど。

TTS探訪

| No Comments | No TrackBacks

いろいろ調べてまとまってから書こうと思っていたが、なかなか終わらないので、途中までを記録しておこうと思う。

(1) flite

前回書いた通り、TTSをいじると、何やら面白い物が作れるのではないかという気がしたので、今週はそのまわりをいろいろと眺めてみた。とはいっても、日本語のものはaquestalkを使えば当面は遊べそうな気がしたので、どちらかと言えば英語をサポートしているTTSエンジンに興味が向かう。

そんなわけで、最初にTTSエンジンとして思い出したのはfestivalだ。CMUで開発されていて、C++ベースなのが難点だと思ったが、festival.hを見るとC++の色がついている感じではなかった...のだけど、実際にこれでP/Invokeするコードを書こうと思ったら、どうもこのヘッダにある関数だけでは足りず、インクルードされている他の型を使おうとしたらC++を避けて通ることはできなそうだ。

しかし、もう少し調べてみたら、このfestivalをベースにしてCで書き換えて組み込み用にしたfliteというものがあった。これなら問題なくP/Invokeできそうだ。と思ったが、グローバル変数などが使われていて、そのままでは使えなそうだ(といっても別のライブラリを作ってポインタを返せばいいだけだが)。今はとりあえず関数をソースに追加してビルドしている。これはまだ途中までしか出来ていないので、正しくinterop出来ているかどうかは分からない: FliteSharp.cs

flite.hにはwaveストリームにTTSの合成結果を落とし込むAPIが用意されていないようなので、flite.cでファイルに落としている関数を眺めつつ、相当のコードを書かなければならなそうだ。ただおそらくC#で書けるだろうと思う。

ちなみに、もうひとつ思いつくTTSエンジンでFreeTTSというJavaの実装があって、もうローカルに既定のプロトコルをしゃべるクライアント/サーバか何かを立てて、それ経由で共通APIを実装する形にしたらinteropもあまり気にしなくて良いだろう、と考えたのだけど、よく見たらFreeTTSはfliteに基づいているようだったので、とりあえずいらないと考えることにした。

(2) System.Speech.Synthesis

さて、実装できそうな雰囲気は何となく出てきたけど、これをどう使えばいいのかよく分からないし、TTSがどんなものなのかもあまり分かっていない。fliteのドキュメントはあまり親切ではなく、中で使われているfeaturesやpropertiesがどう提供されているのかもよく分からない。

そんなわけで、手始めにSystem.Speech.dllのSystem.Speech.Synthesis namespace相当のライブラリをこれで実装してみようかと思った。ただ、msdnを見ると分かるが、単なるSAPI (Speech API)のラッパーでしかなく、全くと言っていいほどドキュメントが無い。APIである程度分かるだろうと考えて、一通りのスタブ的なコードを書いて、pluggableな基底ライブラリを作ってみた。System.Speechはエンジン別に実装されたこれの派生クラスを生成して機能を呼び出すだけだ。fliteはLinux/Mac/Windowsで動くようなので、とりあえず普通に使えるだろう。

とりあえずfliteとSystem.Speechの機能の対応はこんな感じだろうと(現時点では)考えているが、実際に使ってみないと分からない:

  • 音声データベース: cst_voice / VoiceInfo
  • 発音センテンス: cst_utterance / Prompt(Builder)
  • lexicon(センテンス データベース)操作: flite_voice_add_lex_addenda() / SpeechSynthesizer.AddLexicon()

変換元としては、単純なテキスト文字列の他にSSMLというW3C標準の言語が使える。

SpeechSynthesizerは、発音の構成要素となるイベントを詳細に追いかけることが出来るeventなどを用意しているが、これがfliteでfeatureとして提供されているかは分からない。カスタムコールバックを提供している関数で、とりあえず把握しているのは、ストリーミングを出力とする実装で発音バッファがいっぱいになったら送られる、というものだけだ。

(3) SSML

SSMLはもう5年以上前にrecommendationになったXMLボキャブラリの仕様で、発音の仕方(上記のcst_utteranceやPromptに相当する)を記述する言語だ。fliteもSAPI/System.Speechもこれをサポートしている。

System.SpeechはSSMLを前提としているようなAPIにもなっている。たとえばVoiceGenderはvoice要素のgender属性の規定値と同じだ。VoiceAgeは年齢の数値ではなく列挙型になっているが、音色属性にageを含めるというのはSSMLと同じだ。

vocaloid(鏡音リン・レン)の場合はgender factorは数値で調整するが、TTSエンジンの音色データベース(cst_voiceやVoiceInfo)でそこまで調整できるとは考えにくい。最終目標は単なるTTSではないので、この辺は気になるところだが、むしろ合成結果の波形に対するエフェクトとして実装できるかどうか、ではないかと思う(出来ると期待したい)。いずれにしろ、エフェクトの類は、原理を全然知らないので、調べてみないと分からない。

vocaloidのようなものが実装できるかどうかに影響する、より重要な要素は、発音についてどれだけ詳細に記述できるかどうかだ。TTSは厳密な音の表現を目的としていないだろうから、「しゃべれれば何でも良い」になりそうに思う。この辺も調べてみないと分からない。以前mugeneで書いたVSQサポートの歌詞マクロ相当のことは出来てほしい。

今日はとりあえずここまで。とりあえずTTSでしゃべれるようにする必要がある。

demystified

| No Comments | No TrackBacks

vocaloidまわりで手を動かしていて、もうひとつ気づいたことがある。それは、vocaloidとほぼ同じような目的で作られているutauのことだ。存在自体は知っていたのだけど、今どんな感じで作られたり使われたりしているのかは、全く関心が無かった。vsqまわりのデバッグをしていて、ふと思い出してutauにもvsqをインポートする機能があるんじゃないかと思って、ダウンロードして試してみたら、やはり存在していた。インポートは完全ではなかったのだけど(発音表記と実際の発音記号が異なっている場合に、発音記号を正しくインポートしてもらえなかった。これは「-」などをどう処理するかで問題になる)、utauでも再生できるvsqが生成できていたことに、とりあえず満足したのだった。

もしかしたら、VSTやらReWireやらを要求されるvocaloidでうまくいっていない同時再生も、utauを使えば出来るんじゃないか、と思って見てみたのだけど、APIが用意されている雰囲気は無かった。その代わり、音声合成エンジンがどうなっているか等を知ることが出来て、参考になったのだった。

utauは、Wikipediaの項目にも書いてあるのだけど、音声合成エンジンとGUIエディタは別々のもので、音声合成エンジンはさらにAquesTalkというTTS (text to speech)エンジンと、発声したwavに音階等の合成を加えるエンジンが別に存在しているようだ。そしてAquesTalkはどうやら開発者が別で、しかもさまざまなプラットフォームで動作するようだ(iPhoneやAndroidまである)。Cで書かれているらしく、C#からP/Invokeしている人が多く見つかった。やはり考えることは同じらしい。

これはこれで興味深いのだけど、より驚いたのは、vocaloidと同様の技術は、TTSをベースに作れなくもないということ(に気づいてしまったこと)だ。確かに、考えてみたら、TTSで生成した音声に、音階をつけてやれば、歌っているのとだいたい同じようなことになる。音階は周波数を加工したり何かいろいろすれば(わかってない)、自然に出来るのだろう。この辺が一体の技術であると考える必要は無かったのだ。

ということは、AquesTalkを使わなくても、既存のTTSを使えば、utauと似たようなソフトウェアは作れるのではないか。utauはAquesTalkを使っていることもあってか、寄付歓迎シェアウェアという実態はフリーソフトにはなっていても、オープンソースにはなっていないし、AquesTalkがWindows版のみ無償利用可能(!)になっているので、クロスプラットフォームにもならない。しかしTTSには(英語しか無いだろうけど)クロスプラットフォームのものも存在している。それならば、何かこの辺で面白い物が作れたりしないものだろうか。

とまあ、そんなことを考えた。具体的にそれを実践する知識は何もないのだけど、基本的なやり方が何となく分かったというのは大きいと思っている。

VST hostingが上手くいかないの巻

| No Comments | No TrackBacks

mugeneはまだコンパイラとしてきちんと使いやすくなっているとは言い難い。今のところほぼ自分専用ツールになってしまっている。これはよろしくない。というわけで、ある種のテキスト編集機能をもったGUIと連動して演奏できるようなツールを作ろうと考えた。

しかし、テキストエディタを自作するのはいくら何でも無謀すぎるので、どちらかと言えば「ファイルを登録しておいてボタン1つでコンパイルして再生までやってくれる小物ツール」さえあれば足りると思うようになった。

それならば、どうせVSQもサポート出来ているのだから、vocaloidを同時にkickして同時再生できるようにしてしまいたい。...と思ったところから、今日の話にはだんだん暗雲が立ちこめてくる。

VSTは、そもそもプラットフォーム依存が大きいので(vocaloid自体Windows専用だ)、あまり積極的にサポートする意思は無かった。しかし、vocaloidはCrossoverを使うとwine経由で動かせるようだし、Linuxでもwine 1.2になると動くのではないかという期待が大きい(実のところ1.2RCをインストールしてあるので、必要なDLLさえセットアップすれば確認もできるのだが、まだ試していない)。まあどうせWindows依存になるのは仕方ないので、MIDIと同時に鳴らせたら楽しいだろうと思うことにして、いろいろ実験してみたのだった。

VSTのホストを作成するには、通常であればSteinbergからVST SDKをダウンロードしなければならない(クローズドソース)。これは面倒だ。

というわけで、まず、以前から気にはなっていたVST.NETを使うアプローチを探ることにした。これは本来はVSTを「動かす」ホストを作るためのものではなく、VST(ゲスト)を「作る」ために作られたライブラリなので、今回の目的とはベクトルが違うのだけど、どうやらホスト環境もある程度作られているようだ。そしてさらに、VST.NETは他にあるC#用ラッパーの類とは異なり、Steinbergのコードを必要としない。

というわけでこれを真っ先に試したのだけど、Visual StudioはExpressしか手元にないのに、C#とC++が混在するVST.NETのビルドではまって四苦八苦したのだった。VC++は特に慣れていないというのが結果的には大きかったのだけど。

何とかビルドできるようになって、一部のサンプルのHostを取り込みながら、VSTiを読み込むところまで書いてみたのだけど、これがVocaloid2のdllだと、dllmainなどの読み込みまでは成功するのに、その後でエラーになってしまって先に進めない。VOPMという別のVSTiを試してみたらあっさり読み込んだので、おそらくまだVST SDKのようには完動しないのだろう(と思うことにした)。

それから、仕方ないので公式VST SDKまわりでやっつけられないかと思い、Steinbergのわかりにくい公式サイトから何とかSDKのあるページを探し当てて(外部からもリンク切れだらけで実に到達しにくい)、ダウンロードしてきたのだけど、やはりC++なのでP/Invokeも出来ないし、そもそもラッパーを作る気にもなれず、面倒になってきた。

そんなわけで、とりあえず自分で実装するのはあきらめて、VSTHostとMIDI Yokeを使って、仮想MIDIデバイスに対してPortMidiPlayer...から名前を変えたmanaged-midiのコンソールプレーヤで.vsqファイルをSMFとして再生すれば、普通に出来るんじゃないか...と思いついた。思いついた時はいいhackだと思ったのだけど、調べてみたらVSTHostとMidiYokeは実に一般的なアプローチでいろんな人が試していたようだった。

ともあれまずvsqを生成するところから...と思ったら、生成されたvsqがmanaged-midiで正しく解析されず、しばらくバグ取りをすることになってしまった(生成側の問題だった)。それでvsqをVOCALOID2_Realtime.dllに向けて再生してみた。しかしやはりうまくいかない。VSTHostもMIDI Yokeも(そもそもVST自体)あまり理解しているとは言えないので、この辺は少し調べてみないと分からなそうだ。

なかなか先は遠い...というか、vocaloidは後回しにしてエディタツールだけ作った方が良いような気がしてきた。

WebSocketsの実験(未完)

| No Comments | No TrackBacks

仕事で何をしても良いという1週間だったのだけど、さすがに何でもというならMMLコンパイラを...というわけにもいかず、仕事に関係しうるものでほんの1週間で終わるものはほとんど趣味とかぶらなかったので、simplify mediaみたいなメディア共有サーバを作りたかったことを思い出して、何となくコードを書いてみることにした。そして、設計の途中でHTTPのduplex communicationがほしいと考え、それならゼロからWebSocketsを実装してしまおうと考えたのだった。結局WCFのバインディングを作るというところで未完に終わり、アプリを実装するところまでは全く及ばなかった。WCFのバインディングとして実装するのは、それなりに面倒だ。ただのTCPアプリケーションとして実装するなら1週間でもおつりがくるだろう。

HTTPサーバとも共存できるようHttpListenerを改造するところから始めたのだけど、冷静に考えたらほしいのはWebアプリケーション環境との統合だった。つまりいじるならxspのようなHTTPサーバだったかもしれない。そうなると簡単ではないけど。そもそもduplex通信のターゲットになるサーバは80とは別のポートで動いていても良いだろうし、C10Kなどの負荷が大きくなったらマシンごと分散するのが筋だろうから、スタンドアロン実装でも良かったかもしれない。とまあ、いろいろ考え直させられることはある。

あと、WebSocketsを実装していて気づいた大きな問題として、データフレームとしてUTF-8の文字列しか送受信できないことがある(現時点での仕様ではセクション5.3など)。これではバイナリデータの送受信ができない。もともとHTML5のDOMからJavascriptでコールバックを受けるために使うものだったのだから、そういう仕様になっているのだろうけど、これでは画像や音楽データは送れない。Web SocketsのフィードバックのMLを眺めると、同様の要望が寄せられているようなので、おそらく将来の仕様では対応することになるだろうと思う。

Web Socketsはまだ仕様がコロコロ変わっているように見えるので(たとえば世の中にあるサンプルの多くはまだMD5を使ったハンドシェイクを実装していない)、実装作業を再開して公開するのはもっと後でも良いかもしれない。

mobilesynth portを動かすアプローチでできることは、結局のところmobilesynthの機能の範囲で、その移植の安定化をはかってもあまり旨みが無いので、proof of conceptにしてももう少し魅力的な実装を使いたい。というわけで次に発見したのがSlMMLだ(正確に言えば発見したというより思い出した)。これは元々FlMMLというflashのライブラリがsilverlightに移植されたもので、他にもObjective-Cの移植がある。iPadアプリに使うということだけが目的ならocmmlをbtouchしてしまえば良いのだけど、それにしてもインターフェースを自作しないといけないので面倒だ。

というわけでいくつかslmmlのソースに手を加えて、一応MonoTouchでも使えるようにした。 http://github.com/atsushieno/slmmltouch

日本語の文字が入っていると落ちるとか、silverlight依存の部分を削ぎ落とす(もともとslmmlはMediaStreamSourceの応用なので当然にSLに依存している)といった作業と、CoreAudioのバインディングを作る作業(これはmobilesynth対応とあまり変わらない)がほとんどで、土日の半分くらいで出来た。

ただ、サンプルアプリがobjcのシグナルエラーやsegfaultで落ちることが多く、理由がいまいちよく分からない。しかもパフォーマンスがかなり悪い。任意のMMLを再生するのは諦めるしかない。この時点で高機能なバックエンドがほしいという目的はほとんど実現できなくなった...

この作業を続けるなら、まずSlMMLの最適化から始めるべきだろうけど、それだとmobilesynthのコードに深入りするのとあまり変わらない状況だ。

...というわけで、iPadまわりはこの程度で終わりにしておこうと思う。ちょうど明日にはようやくHTC Desireが届くので、今後はandroidに戦場を移すことになるだろう。

ただ、その前にmugeneアプリケーションを作成したいと思っている。

mobilesynth C# port (is not working)

| No Comments | No TrackBacks

iPadが出て、知人が無駄に見せてくれるというので、じゃあそれまでにMonoTouchを使って何かアプリを作ってやろうと思って、音を鳴らすおもちゃを何か作ってみようと考えた。考えたのだけど、CocoaTouchはMIDIすらまともに鳴らせないプラットフォームなので、音を鳴らすことすら望みどおりに行えない。仕方ないので、既存の音声合成ライブラリを使おうと思い至った。Objective-Cで書かれているものであれば、btouchというツールを使って、ちょっとIDLのようなインターフェースを書くだけで使うことができるし、Cで書かれたものであればP/Invokeすれば良い。

というわけで探してみて、最初に出てきたのがMobileSynthというアプリケーションのコードだった。これは実のところ今は作者が自らAppStoreに登録しているわけではないようだが、iPhoneでは無事動かすことはできた。しかしソースコードがC++だったので、このままでは使えない。というわけで最初Objective-Cのラッパーを作ろうとしたのだけど、ソースをよく見てみたら、コード量はたかだか数百行のソースが十数ファイルあるだけだ。というわけで、ざっくりとそのままC#に移植してみた。 http://gist.github.com/418212

これにはあくまで音声合成の機能しか含まれていないので、iPadでは、合成した音声はCoreAudioの機能を使って再生してやらなければならない。他にもいろいろパラメータを設定してやらなければならないので、最低限のパラメータコントローラーを実装したUIを作って鳴らしてみることにした。 http://dl.dropbox.com/u/493047/2010/iPadTest3.tar.bz2

といっても、やっていることはmobilesynthの縮小再生産のようなもので、今のところほぼ存在意義がない...どころか、どうもmobilesynth portがうまくいっていないのか、使い方が良くないのか、期待している通りの音が出ない。音声モジュールはUIのおまけにすぎない予定なので、ここに深入りするかどうかは未定だ。本当に作りたいものは、こういうおもちゃではないし、iPad版はandroid版に向けての単なる踏み台にするつもりでいる。

About this Archive

This page is an archive of entries from June 2010 listed from newest to oldest.

May 2010 is the previous archive.

July 2010 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.23-en