GAMDX改造:ADPCMアップサンプリングをSpeexで

このシリーズもそろそろ終わりです。

もとのGAMDXではADPCMはもともと15625Hzなのを62500Hzにアップサンプリング(ちょうど4倍なので4回同じデータを読み出す形でアップサンプリングして、ローパスフィルターを2回通している)して、FM音源と合成して、その後ダウンサンプリングしています。ここまでのところで、ダウンサンプラーを入れ替えることで音質向上になることがわかりました。

せっかくリサンプラーをいれたので、ADPCMをアップサンプリングするところもSpeexライブラリでやってみてはどうかと考えました。

1)もとのADPCMアップサンプラー(私が改造したものを使っているのでローパスフィルターを1回しか通っていないです。したがってやや高音のノイズが多い)+Speexダウンサンプラー

defaultupsampler

2)ADPCMにSpeexアップサンプラーを使用+Speexダウンサンプラー

speexupsampler

殆ど変わりません。アップサンプリングが15625->62500とちょうど4倍なので比較的ノイズが乗りにくいようです。そこで、内部44.1KHzにしたときを比較してみましょう

3)もとのアップサンプラーで44.1KHzにアップサンプリングして、44.1KHzのFM音源と合成、そのまま出力したもの

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-19-18-14-18

4)Speexでアップサンプリングして44.1KHzのFM音源と合成、そのまま出力したもの

speex441

4)は1),2)によく似ています。ということはアップサンプリングがうまく行っているということでしょう。非整数倍にアップサンプリングするときにはちゃんとした?リサンプラーを使ったほうが良さそうです。なお、このアップサンプリングはダウンサンプリングに比べてCPU時間が半分くらいですんでいます。

広告

GAMDX改造:リサンプラーのCPU使用率

ここまでの流れで、GAMDX音質向上を図ってみた結果もとのGAMDXのリサンプラーはあまり音質が良くないようなので差し替えてみることとしました。iOSでは比較的性能がよくおそらく最適化されているであろうAppleのリサンプラーが利用できますが、他のプラットフォームでも還元できるように、リサンプラーをfree sourceのSpeexプロジェクトから利用させてもらうようにしました。

当然、CPUに負担がかかると思いますので、使用率を比べてみることとしました。

同じ曲をiPhone5sで再生したときのCPU使用率をプロファイリングしてみました。

1)GAMDX内蔵のダウンサンプラー

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-16-17-11-21

アプリのCPU時間のうち1%も使っていません。

2)Speexリサンプラー Quality=4

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-16-12-14-51

Qualityを0-10のうち4にしたときはCPU時間のうち60%程がリサンプラーに使われてしまいます。これはやりすぎか・・・

Qualityを2にするとFM音源エミュレートと同じくらいのCPUパワーがリサンプラーに使われて、0だとエミュレートの半分くらいのCPUパワーが使われるようです。Appleのリサンプラーを使ったときはアプリの外側でリサンプラーが動くので直接比較できません(が、CPUパワーの負担は軽いと思われます)。

AudacityでiPhoneの出力を取り込んで音質を比較してみたところではあまり変わりないようですし、Qualityは0〜2で十分に思われます。

GAMDX改造:ADPCM変更の効果は?

このところGAMDX改造の話題が続きましたがそろそろ終わりになります。

もとのGAMDXではADPCMの15.6KHzの音源を内部周波数の62.5KHzにアップサンプリング、その際にローパスフィルターを通していますが何故かpcm8.cppおよびX68pcm8.cppという2つのルーチンで2重にローパスフィルターを通っています。ローパスフィルターのパラメータは固定なので、アップサンプリングする周波数が変わってしまうと問題が生じそうです。また、2回LPFを通るので音の歪みなどが必要以上に乗ってしまう可能性はあるかもしれません。追記:LPFの効果を強めたい場合、2つのLPFを直列につなぐのは「あり」のようですので、音質の劣化はあまり心配しなくていいかもしれません。

この処理を少し変えて、GAMDX内部での周波数(可変にしてみました)に合わせてアップサンプリング、そのあとADPCMが15.6KHzなのでその半分の7KHz以上の成分はノイズと考えられるのでアップサンプリングした周波数に合わせてローパスフィルタを通す、という風にしてあります。

フィルタが変わったことで音質の比較のため内蔵の「X68030のテーマ」のボイスパートを使ってみました。ADPCMの比較をするために、FM音源のところはプログラム上でカットしてあります。

1)もとのGAMDX(MDX player 2.0, 62.5KHz出力を使用。したがってダウンサンプラーはAppleのものが使われます)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-48-27

出だし約10秒間を詳しく周波数分析したもの

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-48-42

2)改造版、ダウンサンプラーはAppleの物を使用

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-41-01

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-41-15

3)改造版、ダウンサンプラーはSpeex(Quality=2)を使用

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-43-27

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-43-57

4)改造版、Speexリサンプラー(Quality=4)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-56-30

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-13-17-56-57

 

SpeexリサンプラーはQuality=2と4でほぼ同じ結果のようです。あとでソースを読んで見る必要あり。AppleよりもSpeexのほうがローパスな傾向があるのと、私が改造したADPCMルーチンは8KHz以上の本来はカットされるべき部分が結構残っているようなのでLPFのパラメータはいじる余地がありそうです。

GAMDXのリサンプラーをいれかえてみる

前回に引き続きGAMDXの改造を継続。

まずADPCMをいじっているときに、内部で使用しているSample型が16bitに設定されていたのでPCMデータがオーバーフローする状況に遭遇。ローパスフィルターを整理するとともに極力データのロスがないように、原則データロスにつながる操作をしないようにしてみた結果なのですが。ということでSample 型は32bitにしてあります。

そしてもともとのダウンサンプラーの性能が良くないと指摘してAppleの(iOS組み込みの)ダウンサンプラーを使っていたのですが、他のOSに移植することもあるかもしれませんし、ダウンサンプラーを差し替えてみようと考えました。

ダウンサンプラーとアップサンプラーをあわせてリサンプラーというのですがそのものを総合的に解説したHPがあります:Digital Audio Resampling Home Page

色々解説が書いてありますがこれを勉強して一から書くのは相当大変というか無理です。ということでこのHPのFree Resampling Softwaresというところでフリーの実装を物色してみます。SoXというのが有名らしいがかなりボリュームが多いしGPLだ・・と思っていたら一番下の方でSpeexライブラリがBSDライセンス(商用利用も可能)となっています。Speex自体はVoIPで音声を圧縮して通話することが主目的のライブラリですが、リサンプラーも半ば独立したものがあるみたい(Speex自体は開発終了していてOpusという新しいプロジェクトに移っているようですが、リサンプラーはあまり変わらないようです)。通話目的のプロジェクトなので、速度も重視されているようです。

ということで秋の夜長、Speexのresampler.cを移植してみました。1.2rc3をダウンロードして、そのものズバリresampler.cというのを入れてみて、コンパイルエラーが起こらないまでにヘッダーを持ち込みます。.cファイルは一つだけというのが好感が持てます。リサンプルの精度は0-10で選べます。ARMのNEON命令セットに対応しているようですが、今はうまく動かないようです。

GAMDXの内部にはMXDRVG_MakeResampler,  MXDRVG_ClearResamplerという2つの関数を追加しただけで、他はほぼ透過的にリサンプルする・しないが選べます。もとのGAMDXではMXDRVG_Startという関数で出力周波数を指定しますが、ここでは内部処理の周波数を指定して、出力周波数を決めるのはResamplerでという風にしたのでフレキシブルになっていると思います。

手元にUSB-DAC/ADCがないのでリサンプラーごとの性能比較が今はできないので後日。

先述の通りSpeexのリサンプラーは精度が0-10で選べます。デフォルトは4になっていて,0では線形補間のレベルと書いてあります(が、ソースの中をちゃんと読んでいないので後の課題にしておきましょう)。5以上のレベルはCPUにかかる負荷が重くなりそうなので、レベル4,2,0について調べてみました。62.5KHzの内部周波数で、48KHzにダウンサンプリングして出力したものです。

レベル4

level4

レベル2

level2

レベル0

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-11-16-26-00

もとのGAMDXリサンプラーと直接比べられるように同じ曲を調べてみました。ノイズは明らかに減っていて、Appleのリサンプラーとあまり違いないレベルでしょうか。レベルごとの違いについて、実際に耳で聞いたところでもあまり変わらないようですが、CPU使用率は結構違います。iPhone5sではレベル4でCPUの使用率30%程度、レベル0で20%程度となります。レベル2くらいでいいのかもしれません。

なお、前回の48KHzの出力で1)GAMDX内部は62500Hz、Appleのリサンプラーで48KHzに変換 3)GAMDX内部から48KHzで処理、を比較してみる話ですが、手元にあったVeyrlen氏のSonic Boom Stage 1 (高校生の時に松山銀天街のセガでやったのを思い出す・・・)はあきらかに1)のほうが良いみたいです。ほかの曲では大きな違いがない様に聞こえるのですが。

ということで現時点での結論としてiOS についてはベストの音質は62.5KHzにApple resamplerをかましたもの、となりver2.0からはあまり大きな改善は見込めなさそうです。他のOSについてはSpeex resamplerがうまくいけば音質向上になると思います。

GAMDX改造の効果は?(続き)

昨日に引き続き、今度はFM音源の出力を本来の62500Hzではなく48000Hzにしたときの比較をしてみます。

1)MDXPlayer for iOS ver2.0 62.5KHz: GAMDX  FM音源62500Hz  – iOS内蔵のダウンサンプラー経由で48KHz出力

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-07-11

2)MDXPlayer for iOS ver2.0 48KHz: GAMDX  FM音源62500Hz  – GAMDX内蔵のダウンサンプラー経由で48KHz出力

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-07-57

3)改造版:GAMDX 改造して FM音源48000Hz  -ダウンサンプラー通さず48KHz出力

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-06-58

ということで、周波数帯の灰色の部分は無音に近いということになりますから、2)は全体的にホワイトノイズが乗ったような感じになっているといえます。ダウンサンプラーを通さないことで余計なノイズは乗らず1)と3)ほぼ互角のように見えます。ただ、FM音源の出力を間引いて出力しているかもしれないので、細かい波形の歪みが出ていないかが気になります。192KHzでキャプチャして、こまかいところまでみてみました。なお、本日使用した曲はVeyrlen氏によるS.D.I.のAn Imminent Warです(FM音源の名曲ですので対決にちょうどよいかと)

前述の1)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-24-53

2)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-26-41

3)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-17-24-39

うーん、少なくとも波形の極端な歪みなどはなさそうですが、比較が困難です。すくなくとも、FMgenから48000Hzで出力しても、大きな破綻はないと考えていいでしょうか?

あとは62500Hzの原音と48000Hzの音の波形を比べてみるのが良いのでしょうが、そうなるとまずMacのかんたんなプログラム(コマンドラインから起動?)で62500HzのデータをWAVなどの形でダンプするプログラムを作って、1)のダウンサンプラーを通したほうが良いか、3)のFM音源エミュレータから48000Hzで出したのでかまわないのか、比較する他ないかと思います。あとはご自身の耳でも聴き比べてみてください。

MDX音質向上研究:GAMDX改造

前回の続きでMDX Player for iOSの音質向上を図ってみます。

まず前提として、X68内部ではFM音源は62500Hz, ADPCMは15625Hzで出力されています。

MDX Player for iOSではGAMDXエンジンを使用していて、FM音源とADPCM音源をミックスしています。GAMDXエンジンの内部では

  1. FM音源は62500Hzで生成、
  2. ADPCM音源を62500Hzになるよう4倍化した上でフィルタをかけて高音域に乗ったノイズを除去、
  3. FMとADPCMをミックスした上で目的の周波数(44100Hzとか)にダウンサンプル、

となっています。前回指摘したのは、このダウンサンプルのところでノイズが乗ってしまっているのでは、ということでした(周波数変換自体は非常に奥深い問題で、速度と品質のトレードオフなどもあり一筋縄では行きません。各種の周波数変換ルーチンの比較をするサイトもあります)。

前回、MDX Player for iOS v2.0では62.5KHzの出力にした時は、内部のダウンサンプルルーチンを使わずにAppleのダウンサンプルルーチンを使うようになっていて、その結果音質が向上していることを確認しました。その結果をふまえて、GAMDX 内部をいじってみて音質向上を図ってみます。v2.0にはせっかく22/44/48/62KHzと切り替える機能もついているので、内部的な周波数を変更できるようにしてみました。

まずGAMDXでは内部的に62500Hzに統一していますが、これを可変にしてみます。実はFM音源のエミュレートをしているFmgenは周波数が変わっても出力は可能(周波数が下がると音質も落ちますが)です。また、ADPCM音源のエミュレートはX68pcm8.cpp, pcm8.cppという2段階で行われていますが、何故かローパスフィルタを2回通っています。またローパスフィルタの係数は固定されているので、内部の周波数が変わったときにうまくいかなくなると思われます。ということで、改造したエンジンでは

  1.  FM音源は指定した周波数 xxHzで生成
  2. ADPCMをxxHzにアップサンプリングする。途中までは余計なフィルタは通さず、FM音源とミックスする直前にローパスフィルタ(指定の周波数xxHzによりパラメータを変更するタイプ)を通す
  3. 直接xxHzのデータをiOSに渡して再生してもらう;iOSの機能で必要に応じて44KHzや48KHzに周波数変換してくれるし、もし44KHzで生成すればダウンサンプリング不要となるのでそこでのロスがない

というかたちにしてみました。62KHzでは素のver2.0とほぼ同様です。22, 44, 48KHzの存在意義ですが、再生ルーチンの負担が軽くなるので62KHzに比べて22KHzではCPUにかかる負荷が半分くらいになるようです。なお、MMDSP風の画面更新は周波数に比例した頻度で行うので、22KHzだと画面はスローがかかったようにみえるかもしれません(Frame per secondがひくい)。

再生音質の比較をしたいのですが、わたしはiPhoneを1つしか持っていないので改造版ともとのやつを比較するのにXCodeでプロジェクトを切り替えてインストールして・・・を反復しないといけません。本来なら、GAMDXエンジンで62500Hzを44100Hzにダウンサンプルした場合と、はじめから44100Hzで生成してダウンサンプルしない場合とを比較した方がいいのでしょうが。

もう少し時間のあるときにいろいろ調べてみますが、今はとりあえず新規導入したADPCMのローパスフィルタの性能を評価してみました。ADPCMのみのパート(アサルト2ステージ出だしのドラムだけのところ)を周波数分析してみます:

1)ローパスフィルタを通さずにそのままま出力:15625Hzを中心にエイリアシング(折り返し雑音)が見られます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-05-16-00-14

2)もとのGAMDXのエンジン:ローパスフィルタが効いています。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-05-16-50-54

3)今回導入した可変ローパスフィルタ:7KHzより上の周波数は本来は雑音ということになるので2)のフィルタよりも少し性能は悪いかもしれませんが、2)のフィルタは前述の通り2回のフィルタ操作を通っているのでもう少し素直な音がしてくれることが期待できるかも・・・??

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-05-16-00-25

 

ということで、ここまでの変更はhttps://github.com/sinn246/MDXPlayer/tree/HiDefにあげておきます。

GAMDXの内部構造としてはローパスフィルタを別ルーチンにしたのでPCM周りは少しスッキリしたと思います。あとは優秀な周波数変換ルーチンがあればAndroidなどでも音質向上できるはずです(と言うか、私が加えた変更よりも周波数変換ルーチンの差し替えだけでも十分かもしれません)。

続きがあります