Select Your Language

免責事項

  • 本サイトの情報の利用、内容、サービスによって、利用者にいかなる損害、被害が生じても、著者は一切の責任を負いません。ユーザーご自身の責任においてご利用いただきますようお願いいたします。

    本サイトで頒布している基板およびキットは、技術者、またはそれに準ずる電気的知識をお持ちの電子工作ファンの方のためのものです。 一般のオーディオファンの方のためのものではありません。
    また、頒布基板およびキットは、いかなる条件でも動作を保証するものではございませんので、あらかじめご了承ください。

    電子工作では、火傷、感電、火災などの可能性があります。 十分に注意をして作業して下さい。

    営利目的のご使用は認めておりません。  記事の転載や、基板・キットの商用利用の方は、ご連絡ください。
    学生やサークルの学習目的でまとめてご購入する場合は特別なコースをご用意させていただきます。

スポンサー

« I2S-DACを348kHzで駆動すると、どういうメリットがあるの? | トップページ | MPDをソースコードからコンパイルしてPi 2 Pi 3に最適化する方法 »

2016年8月16日 (火)

(続) I2S-DACを348kHzで駆動すると、どういうメリットがあるの?

ちょっと下調べが足りなかったようです。 こちらのつづきです。

 

digififanさんからの情報によるとmpdに含まれているdsd2pcm はフィルタ特性が高域に伸びすぎていてノイズが取りきれていないとのことでした。 

dsd2pcmのプログラムはこちらが元でしょうか? 

こちらに載っているデジタルフィルタの特性は下記のような特性です。 

Dsd2pcm_filter_s  

帯域外の減衰特性は-150dBとすごいものの周波数は約100kHzまで伸びています。 

 

以前にDSDのダイナミックレンジと帯域外ノイズについて記載した図をのせておきます。

Dsd_figure_zz

こんな感じで、DSDでは20kHzまでは十分にノイズを押し下げていますが、20kHzから上の領域では多くのノイズが含まれています。 

理論上100kHz以上まで記録することが出来るというのは嘘ではありませんが、ノイズフロアが上昇しているので、あまり高域を伸ばしすぎるのは得策ではありません。 SACDの規格では50kHzで-3dBのフィルタを入れることになっているのは、以前に書いたとおりです。 

 

 

さて、digififanさんの推奨のフィルタ特性はといいますと

 フィルタ長 321
 窓の種類 Kaiser窓
 正規化遮断周波数 0.0124(35KHz)
 阻止域での必要減衰量 120db 

石川高専のhttp://dsp.jpn.org/dfdesign/fir/mado.shtml で算出

Dsd2pcm_filter_kai  

 

このような形です。 ちょっとグラフの帯域が広すぎて分かりにくいかもしれませんが、70kHzで-100dB以下と絶妙な特性に設定されています。 

追記==================>

表示領域を100kHzまでとした拡大図をのせておきます。 

Dsd2pcm_filter_kai2

==================> 追記ここまで

 

ちなみに、デジタルフィルタの特性の表示にはOctaveを使用しました。 

freqz([** ** ** ・・・・・],1, 2048, 2822400) 

と入力するだけで表示できます。 

**はFIRの係数です。 96TAPではスペースで区切って96個入れます。
2822400はサンプリング周波数です。 DSDのフィルタなので2.8MHzを指定しました。 

 

更に追記======================

Octaveを使ってFirフィルタの係数を算出する方法を書いておきます。

条件は

 フィルタ長 320
 窓の種類 Kaiser窓
 カットオフ周波数  36kHz
 阻止帯域の減衰量 120dB 程度 

以下のコマンドで打っていきます。 

pkg load signal

fs=2822400

fc=36000/(fs/2)

tap=320

lowpass=fir1(tap-1,fc,'low',kaiser(tap,12))

freqz(lowpass,1,2048,fs)

これで周波数特性が表示されます。 freqzの”2048”はプロットの解像度なので大きな数値を入れると拡大した時にも滑らかに見えます。 

320tap36k  

100kHz以下を拡大したところです。 

係数の保存は

save -ascii Low320tap lowpass

これで、320個の係数がテキストファイル(Low320tap)に保存されています。 

簡単ですね。 ここまでは。。。 

 

Raspberry Piを活用するという意味では

  MATLAB Home     (1万5千円)
  Signal Processing Toolbox  (5千円)

を使うというのが、あるべき姿なのかもしれません。  

 

 

 

 

にほんブログ村 PC家電ブログ PCオーディオへ にほんブログ村
ブログランキングに参加中です。 めざせ1位! 
もしよろしければ「ぽちっと」お願いします。 



« I2S-DACを348kHzで駆動すると、どういうメリットがあるの? | トップページ | MPDをソースコードからコンパイルしてPi 2 Pi 3に最適化する方法 »

コメント

タカジンさん


> さて、digififanさんの推奨のフィルタ特性はといいますと

> 70kHzで-100dB以下と絶妙な特性に設定されています。 

raspi2でdsd64を352.8Kのpcmに変換する場合、係数のtap数は321がほぼ限界になります。
tap数=321の条件で

> 正規化遮断周波数 0.0124(35KHz)
> 阻止域での必要減衰量 120db 

を決定しています。
正規化遮断周波数をこれより下げたり、減衰量を150dbにすると20kHzまでフラットが
実現できなくなります。

DSD64を88KHzのPCMに変換するさいのフィルターは

フィルター長 1281
窓の種類 Kaiser窓
正規化遮断周波数 0.0084
阻止域減衰量 120dB

になっています。
本来なら減衰量は150dBまで落としたいのですが、そうすると20KHzまでフラットが
実現できなくります。
窓関数法では阻止域減衰量以降はだら下がりなのでこれで妥協しています。

これならNOSのDAC+12db/oct程度のポストフィルターでも大丈夫かなと考えています。


前後しますが、

> dsd2pcmのプログラムはこちらが元でしょうか? 

そのとおりです。このプログラムは有名なプログラムのようで殆どのplayerソフトの
元になっているようです。xldというソフトもこれをベースにしていました。
入力が0,1であることを利用して8サンプルごとに予め係数の積和を行っておき、
実行時にその積和の結果の加算だけを行っています。
さらに1バイトに8サンプルがパックされてますから、パックしたまま演算が行えるので
1点を求める計算量は

ceil(tap数/8)回の加算

になります。

385.2KHzの場合2.8uSec毎に41回の演算を行うことになります。(1chあたり)

lightMPDではdouble floatで計算をおこなっているのでneonとかも使えないので
このあたりが限界かなと思ってます。(オリジナルはfloatで行っています)

digififan さん

なるほど。 そういう処理なのですか。precalc()は一体なにをしているのだろうと不思議に思っていました。 

double floatとはすごいですね。 lightMPDでDSD音源をじっくり聴いていなかったので、確認してみます。 

フィルタのTAP数を変えてもHTAPS さえ指定してあげれば、動作するのでしょうか。
久しぶりにmpdをコンパイルしてみようかと思っています。

たかじんさん

> double floatとはすごいですね。 lightMPDでDSD音源をじっくり聴いていなかったので、確認してみます。 
最終結果はfloatに丸められるのですが、firでtap数を大きくすると係数のレンジが大きくなりfloatで計算するといわゆる情報落ちという誤差が生じそうなので中間結果はdoubleで計算しています。やってることはctableをdoubleにしただけです。

> フィルタのTAP数を変えてもHTAPS さえ指定してあげれば、動作するのでしょうか。
dsd2pcmでのfirの係数長は偶数に限定されます。HTAPSは(係数長 / 2) になります。
係数は左右対称なので右半分だけをhtapsにセットします。
係数長をNとすると
static const double htaps[HTAPS] = {
N/2 番目の係数,
N/2 + 1 番目の係数,
N/2 + 2 番目の係数,
...
...
N - 1 番目の係数
}
になります。

FIFOSIZEも係数長に依存します。
firの場合、計算するサンプリングポイント以前のデータ(係数長分)が必要になりそのバッファーの長さがFIFOSIZEになります。
FIFOSIZEは

1. 2のべき乗
2. FIFOSIZE * 8 が係数長以上

の条件に合う数字のうち最も小さい値を選択します。FIFOSIZE * 8がプリエコーの長さになります。

係数長が偶数なので、窓関数法で求めた係数が使えません。
石川高専のDigital Filter Design Services なら Parks-McClellan法を使います。

Parks-McClella法でLPFの係数を求める場合はフィルター長の他に
 
Fh1 : 正規化遮断周波数
Fh2 : 正規化阻止域周波数

を指定します。

阻止域での減衰量は遷移域の幅(Fh2 - Fh1)で変わります。

手順として

1 Fh1 を決める
2 Fh2 を決める

で係数を求め、阻止域での減衰量が満足できなければ、Fh2を徐々に大きくしていきます。

あとlightMPDではL-Rのチャンネルをopenmpを使って並列動作させています。
並列動作させないと352.8KHzで321タップは難しいかもしれません。

難しすぎて話しにサッパリついていけないのですが石川高専と山田洋士先生のキーワードだけに過敏に反応してしまいました。
電気嫌いの機械課卒ですがなぜか自作オーディオの道に目覚め、在校時には興味を持つことすら想像出来なかった電気の世界(このHP)で母校の先生の偉業を知り、世の中の縁の不思議さを体感した次第です(笑)

digififan さん

openMPで並列動作ですか。 じゃないとmpd単体でCPU負荷が1コア100%以上になって音飛びしそうですね。 色々と情報ありがとうございます。 
私にどこまでできるかわかりませんが、色々とトライしてみようと思います。


anni さん

なんと石川高専の卒業生ですか。 素晴らしいサイトですね。 Web上でこういった数値演算ができるというのは、ほんと助かります。 

たかじんさん

ちょっと修正です。

> 正規化遮断周波数をこれより下げたり、減衰量を150dbにすると20kHzまでフラットが
> 実現できなくなります。
正規化遮断周波数をこれより下げたり、減衰量を150dbにすると阻止域周波数が大きくなってノイズがとりきれなくなります。

> 本来なら減衰量は150dBまで落としたいのですが、そうすると20KHzまでフラットが
> 実現できなくります。
本来なら減衰量は150dBまで落としたいのですが、そうすると阻止域周波数が大きくなってしまいノイズがとりきれなくなります。

に訂正します。


> openMPで並列動作ですか。 じゃないとmpd単体でCPU負荷が1コア100%以上になって音飛びしそうですね。 色々と情報ありがとうございます。 

dsd2pcm_translate()はsrc/pcm/PcmDsd.cxxのToFloat()から呼ばれます。

ToFloat()のfor分の前に

#ifdef _OPENMP
#pragma omp parallel for
#endif

を挿入して、-fopenmpをつけてコンパイルするとL,R並列でdsd2pcm_translate()が呼ばれるようになります。

digififanさん

遮断周波数については、おっしゃる通りですね。 パラメータを変えるとどうなるか見えてきました。

openmpの方も、ありがとうございます。 実際にやってみると1コアに集中していたものが4コアに分散されることろまで確認できました。 ただ、openmpを使わないときは35%くらいの負荷が110%くらいまであがります。 4コアそれぞれ25~30%くらいに綺麗に分散しています。

もうひとつ教えていただきたいのですが、フィルタのTAP数を大きくすると音量が下がってしまう問題が発生しています。 

96TAPで係数を差換えは問題なし。
2倍の192TAPだと微かに聞こえる程度の音量。 320TAPだと聴こえません。

dsd2pcmの変換原理を理解していない状態でフィルタだけをいじろうとしている所に無理があるのは重々承知しておりますが、ヒントをお願いできれば幸いです。 

よろしくお願いいたします。

たかじんさん

> 2倍の192TAPだと微かに聞こえる程度の音量。 320TAPだと聴こえません。

fir1では

fir1(tap-1,fc,'low',kaiser(tap,12),'noscale')

とすると正規化しないとなっています。

'noscale' を指定するとどうでしょうか?

プログラムの問題なのか、係数の問題なのかを見極めるために、ちょっと乱暴ですが、石川高専のプログラムで作成した係数の最後の係数を削除して強引に320tapにして試したらどうでしょうか?
正しい音はでないかもしれませんが、音量は変わらないと思います。

321のものは私のところではちゃんと再生できています。

digififan さん

確かに切り分けが必要そうですね。

石川高専の321個の真ん中(最大値)から最後の1つをカットした160個を係数に入れてみました。

結果、負荷を見ると再生しているようですが音は聴こえません。

https://github.com/clivem/dsd2pcm

clivemさんのdsd2pcmのprecalc()関数 ==============
void dsd2pcm_precalc(void)
{
int t, e, m, k;
double acc;
if (precalculated) return;
for (t=0, e=0; t>=1)
;
}
for (t=0; t8) k=8;
for (e=0; e> (7-m)) & 1)*2-1) * htaps[t*8+m];
}
ctables[CTABLES-1-t][e] = (float)acc;
}
}
precalculated = 1;
}

mpd-0.19.18のdsd2pcmのprecalc()関数 ===========
static void precalc(void)
{
int t, e, m, k;
double acc;
if (precalculated) return;
for (t=0; t8) k=8;
for (e=0; e> (7-m)) & 1)*2-1) * htaps[t*8+m];
}
ctables[CTABLES-1-t][e] = (float)acc;
}
}
precalculated = 1;
}

と、少し違っています。

同様にdsd2pcm_translate()関数も
clivemさん
  *p = dsd2pcm_bitreverse[*p & 0xFF];

mpd-0.19.18
  *p = bit_reverse(*p);
と違いがあるようです。

clivemさんのdsd2pcmをmpdに組み込んだ方が良いのでしょうか。

たかじんさん

> clivemさんのdsd2pcmをmpdに組み込んだ方が良いのでしょうか。
いまは、DSD2PCMの使用自体を変更してしまったのでmpd付属のdsd2pcmで検証はできないのですが、以前たかじんさんと同じようにhtapsを変更して実験してました。
その時はちゃんと動作していたように記憶しています。

係数を石川高専のものに入れ替えても現象に変化がないようですので、修正方法に誤りがあるのだと思います。

ちょっと気になるのが

> が4コアに分散されることろまで確認できました。 ただ、openmpを使わないときは35%くらいの負荷が110%くらいまであがります。 4コアそれぞれ25~30%くらい

こちらで確認したらCPUは200%ぐらいになります。(htopで計測しました)
HTAPSが48のままではないでしょうか?
そう考えるとCPUの負荷が低いのも、TAPSが大きくなるほど音が小さくなるのも納得できます。

> #define HTAPS 48
> #define FIFOSIZE 16

#define HTAPS 320
#define FIFOSIZE 128

に変更しましたか?

先ほどの投稿に誤りがありました。

> #define HTAPS 320
> #define FIFOSIZE 128

ではなく

> #define HTAPS 160
> #define FIFOSIZE 64

です。

digififan さん

320tapのときは

#define HTAPS 160
#define FIFOSIZE 40

にしてます。 HTAPSが間違ってるとコンパイル時にエラーでますね。

96tapで石川高専やoctaveのカイザーで算出した係数に差し替えた場合は大丈夫です。 fcを約50kHzから25kHzくらいに下げたもので普通に鳴りますね。 

openMP時の負荷は、フィルタ係数を変更する前の96tapのときのものでした。  320tapにすると200%くらいいくようです。 topで各コア47%~55%くらいを表示してました。

384kHzのままDACに流せるのでsoxr分の負荷がない分、シングルスレッドで30~40%ととても軽いです。 

あとは何が違うのか。。。 謎です。 

digififan さん

#define FIFOSIZE 40   を 64 にしたら鳴りました。 

お騒がせいたしました。 ありがとうございます。

検討を進めてみます。

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/587107/64069256

この記事へのトラックバック一覧です: (続) I2S-DACを348kHzで駆動すると、どういうメリットがあるの?:

« I2S-DACを348kHzで駆動すると、どういうメリットがあるの? | トップページ | MPDをソースコードからコンパイルしてPi 2 Pi 3に最適化する方法 »

サイト内検索

Sponsors link

2018年6月
          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
無料ブログはココログ