yamamoto2002
yamamoto2002
オーディオ関連のフリーソフトウェアを作っています。 Amazon.co.jpのyamamoto2002さんは別人です。 楽天オークションのyamamoto2002さんも別人です。 Twitt…

マイルーム

yamamoto2002のページ
yamamoto2002のページ
yamamoto2002のページです。
所有製品

レビュー/コメント

カレンダー

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

最新のレス

お気に入り製品

お気に入り製品はありません

日記

44.1kHz PCMを2.8MHz 1bitに変換する

このエントリーをはてなブックマークに追加
2017年05月28日

定番の本[1]を参考に、44.1kHz PCMを2.8MHz 1bitに変換するプログラムを作った。

■変換手順

1. 44.1kHz PCMのFLACファイルを読み込み64倍アップサンプルして2.8MHzのPCMを作る。
2. 6dB音量を下げる。
3. 2.8MHz PCMをループフィルターに入力して量子化し、2.8MHz 1ビットの出力を得、DSFファイルとして出力する。

■ループフィルター回路の構造

ループフィルターの回路は本の97ページ図4-19のCRFB構造を使用する(図1~図4)。本の図は偶数次。奇数次の回路がどうなるかは98ページの中ほどの段落に書いてある。

図1 2次CRFB (画像をクリックすると拡大します)

図2 3次CRFB

図3 4次CRFB

図4 5次CRFB

■ノイズシェイピング関数の設計方法

89ページ表4-1に最適な関数の零の位置の表がある。

最適な極の位置を求める手順は、92ページの最下行~94ページ。この設計手順をプログラム化したMATLAB用のDelta Sigma Toolboxが利用できる。synthesizeNTF()関数に所望のフィルターの次数を入力すると最適な零と極の位置が出てくる(図5)。

図5

図5を作るMATLABのスクリプト: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/00doc/NTFinspect.m

synthesizeNTF()から出てきた零と極の位置: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/WWOfflineResampler/NTFHzcoeffs.cs#l117

■CRFB回路のa[],b[],g[]の計算

n次のノイズシェイピングフィルターの零の位置と極の多項式の係数d[i]を求めたら、次は回路(図1~図4)のa[i],b[i],g[i]を求める。最初に零の位置から98ページの1行目~2行目に書いてある方法でg[i]を求める。次にg[]と極の多項式の係数d[]からa[]を求める(図6~図8)。Microsoft MathematicsよりもRaspberry Pi用Mathematica 11の方が簡単に出来た。

図6 2次のCRFB(図1の回路)のNTFの分母の多項式の係数d0,d1,d2と分子のg0から図1のa0,a1を求める。Microsoft Mathematicsで計算。

図7 3次のCRFB(図2の回路)の係数a0, a1, a2の計算。Raspberry Pi用Mathematica 11で計算。

4次のCRFBのaの計算(Mathematicaのファイル): https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/00doc/CRFB4th.nb?format=raw

5次: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/00doc/CRFB5th.nb?format=raw

6次: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/00doc/CRFB6th.nb?format=raw

7次: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/00doc/CRFB7th.nb?format=raw

g[]とd[]からa[]を計算するプログラム: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/WWOfflineResampler/DsfWrite.cs#l67

STF=1の場合のb[]の求め方は96ページの「もう一つの興味深い選択は…」に書いてある。これによりa[],b[],g[]が定まり、回路が出来上がる。

CRFBフィルターの実装 : https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/WWOfflineResampler/LoopFilterCRFB.cs

■音を聴き比べる

2次~7次まで作って44.1kHz PCMを2.8MHz 1bitに変換してTEAC UD-501(DSDフィルター設定: FIR1)で再生し音を聴き比べてみた。

2次CRFB: 常時シュワワワーッという音が小さく出ていて気になる。
3次CRFB: シュワシュワ感がわずかに残っている感じがする。気のせいかもしれない。
4次CRFB: 全く問題ない
5次CRFB: 全く問題ない
6次CRFB: 全く問題ない
7次CRFB: 全く問題ない

4次~7次は、全く同じ音に聴こえる。

ジッターのように大きい音に大きい雑音が付いて小さい音に小さい雑音が付くわけではなく、ノイズシェイピングで出るシュワシュワ雑音の音量はあまり変わらないので弱音でアンプのボリュームを上げて聴き比べるとシュワシュワ音が相対的に大きくなって分かり易いと思う。

自作プログラムのデフォルト設定は5次にしようと思っている。

■オシロスコープの簡易スペアナ機能で可聴域外の様子を観察

44.1kHz PCM -6dB ホワイトノイズを3次CRFBおよび5次CRFBで2.8MHz 1bitに変換して、UD-501で再生、RCAアナログ出力をオシロにつないでFFT画面で可聴域外の雑音の様子を観察した(図8,図9)。オシロスコープはsoftDSP SDS 200A。

図を見比べると5次よりも3次の方が可聴域外の雑音は少なくて良好な感じだ。

図8 3次CRFB

図9 5次CRFB

作ったプログラムWWOfflineResamplerはPlayPcmWinのパッケージに入っている: https://sourceforge.net/p/playpcmwin/wiki/PlayPcmWinJp/

長さ4分の音楽を変換するのに12分かかる。

2017年6月2日追記

WWOfflineResampler 1.0.12で信号処理を内容を変えずにネイティブC++で書き直したところ長さ4分の音楽を1分半で変換できるようになった。

ネイティブC++で書き直した処理: https://sourceforge.net/p/playpcmwin/code/HEAD/tree/PlayPcmWin/WWFilterCpp/

2017年6月5日追記

■フィルターの係数の値

2次CRFB(図1)の係数g[], a[], b[]の値:
const double g[] = { 0.00080313670419096539 };
const double a[] = { 0.21573642353265832, 0.55866459878297114 };
const double b[] = { 0.21573642353265832, 0.55866459878297114, 1 };

3次CRFB(図2)の係数:
const double g[] = { 0.0014455686595564732 };
const double a[] = { 0.044083602820343515, 0.24307907841927734, 0.55590710005219635 };
const double b[] = { 0.044083602820343515, 0.24307907841927734, 0.55590710005219635, 1 };

4次CRFB(図3)の係数:
const double g[] = { 0.001786565462119416, 0.00027850892877778755 };
const double a[] = { 0.0057254522986342048, 0.051607454170822936, 0.24845882976302058, 0.556014463585628 };
const double b[] = { 0.0057254522986342048, 0.051607454170822936, 0.24845882976302058, 0.556014463585628, 1 };

5次CRFB(図4)の係数:
const double g[] = { 0.001978322017535783, 0.00069861261557968568 };
const double a[] = { 0.0006604571797801384, 0.0084244803698276111, 0.054686031805914838, 0.25018126352089132, 0.55615015456296357 };
const double b[] = { 0.0006604571797801384, 0.0084244803698276111, 0.054686031805914838, 0.25018126352089132, 0.55615015456296357, 1 };

6次CRFBの係数:
const double g[] = { 0.0020947554796657553, 0.0010533685306401974, 0.00013719891040198107 };
const double a[] = { 3.6853260251004396E-05, 0.00094337600866219477, 0.0095462940143367682, 0.055635743938546235, 0.25080932009012891, 0.55628518119683534 };
const double b[] = { 3.6853260251004396E-05, 0.00094337600866219477, 0.0095462940143367682, 0.055635743938546235, 0.25080932009012891, 0.55628518119683534, 1 };

7次CRFBの係数:
const double g[] = { 0.0021701630853732112, 0.0013247996692016262, 0.00039686524950655055 };
const double a[] = { 4.2050702848683841E-06, 8.4003236543615142E-05, 0.0011852306135776403, 0.010288882151915792, 0.05638407218686825, 0.25098258838930243, 0.55641974785348158 };
const double b[] = { 4.2050702848683841E-06, 8.4003236543615142E-05, 0.0011852306135776403, 0.010288882151915792, 0.05638407218686825, 0.25098258838930243, 0.55641974785348158, 1 };

■2017年6月7日追記

図10 5次NTFの極と零の位置をDelta Sigma ToolboxのplotPZ()でz平面にプロット。

■参考文献
[1]. R. Schreier and G.Temes,ΔΣ型アナログ/デジタル変換器入門, 丸善, 2007

次回の日記→

←前回の日記

レス一覧

  1. yamamoto2002さん、こんにちは。

    PCMからDSDの変換は、以前シミュレーションしてみたら、通常の方法ではやはり三次以上は発振してダメでした。1ビットでの変換に拘る必要はあまりないので、4ビットぐらいにすると高次の場合でも問題なく動作しましたので、結局1ビットはあまり追求せず、どんな方法論なのかなあとだけ思っていました。

    今使われている高い次数での変換は、こういう方法論なのですね。この参考文献は、和訳も出ているようなので、ちょっと調べてみようかと思います。

    by如月 at2017-05-29 13:44

  2. 如月さんこんばんは。

    コメントありがとうございます。この本は少々読み難いところがありますが内容が面白いのでおすすめです。図1の構造はbのお陰でSTFの特性が可変になり、gの値を変えると零の位置がz平面の単位円上を移動するので、本を見たとき用途にぴったりの回路だなぁ~と感心しました。この分野はかなり調べられており、定番の設計手順はすっかり“料理本化”していました。

    これとは全く異なる、デジタル的発想のPCMの1ビット化手法もあって、可能なビットの組をしらみつぶしに調べて最適なものを選んでいくという途方もないアイデアもあり、別次元の凄い性能が出るみたいです。

    byyamamoto2002 at2017-05-29 20:10

  3. yamamoto2002さん、こんにちは。

    [1]の参考文献を買いました。ΔΣの解説は、ネット上でもいろいろありますが、ページの量としての制約もあって、中々良いものはありません。それに比べてこの本は、まだ少しページをめくっただけですが、内容豊富で一冊あればすべてが片付く感じです。

    巻末の付録で少し触れている窓関数の功罪なども、中々他では見ない内容です。これは和訳が手に入るので、とても楽です。和訳されていない中にも、こういう良書は沢山あるのでしょう。英文を抵抗なく読めないと、もうこの分野では太刀打ちできないと、つくづく思います。

    by如月 at2017-05-31 13:22

レスを書く

レスを書くにはログインする必要があります
ログインする