ディエンファ
シス(de-emphasis)IIR フィルタ ─数値計算ソフトのSCILABを使って係数の計算─
むかし、アナログ機器の時代、録音機の特性がまだよくなかったころ、試聴時のノイズ感を少なくするため、わざと音の高い高域の成分を大きく録音しておい
て、再生するときには逆に高域の成分を小さく再生すること(ディエンファシス、強調の逆と言う意味)で、ノイズ感を改善することがおこなわれていた。デジ
タル機器に進化した現在でも、CDやMP3ファイルの中には、実際には
あまり使われていないかもしれないが、ディエンファシスをOFF/ONするための設定が
残されている。(MP3でエンファシスを設定
したサンプルデータ)
もともと、ディエンファシスはアナログフィルター回路の時定数で定義されていた。例えば、CDのディエンファシス フィルターの時定数は、
50/15uSである。このアナログの時定数50/15uSに相当する、IIRデジタルフィルタの係数を計算してみた。サンプリング周波数がCDと同じ
44.1KHzのときの、1次のIIRフィルターの係数である。IIRのフィルターの計算をC言語風に書いてみた。 デジタルフィルターでは、サンプリン
グ周波数が違うとフィルターの係数の値も違うので注意してほしい。
int i;
double a[2],b[2],w[2];
#define NUMBER xxxx <=データの個数を設定する。
double in0[NUMBER],out0[NUMBER];
/* 1次 IIR ディエンファシス フィルター
*/
/* アナログの時定数1 = 50uS
*/
/* アナログの時定数2 = 15uS
*/
/* サンプリング周波数 44.100KHz
*/
/* フィルターの係数 a[], b[]
*/
a[1]=0.6303142;
b[0]=0.4599584;
b[1]=-0.0902726;
/* 直接形2
*/
/* in[i] 入力 out[i] 出力
*/
/* w[] は前の計算データを保持しておくための記憶域 。他の用途に使わないこと。 */
/* w[1]=0.0 は ゼロに初期化してから使うこと。
*/
w[1] = 0.0;
for (i=0; i< NUMBER ; ++i)
{
w[0] = in0[i] + a[1] * w[1];
out0[i] = b[0] * w[0] + b[1] * w[1];
w[1] = w[0];
}
もうひとつの例として
int i;
double a[2],b[2],wi[2],wo[2];
#define NUMBER xxxx <=データの個数を設定する。
double in0[NUMBER],out0[NUMBER];
/* 1次 IIR ディエンファシス フィルター
*/
/* アナログの時定数1 = 50uS
*/
/* アナログの時定数2 = 15uS
*/
/* サンプリング周波数 44.100KHz
*/
/* フィルターの係数 a[], b[]
*/
a[1]=0.6303142;
b[0]=0.4599584;
b[1]=-0.0902726;
/* 直接形 1
*/
/* in[i] 入力 out[i] 出力
*/
/* wi[],wo[] は前の計算データを保持しておくための記憶域 。他の用途に使わないこと。 */
/* wi[1]=0.0 wo[1]=0.0は ゼロに初期化してから使うこと。
*/
wi[1] = 0.0;
wo[1] = 0.0;
for (i=0; i< NUMBER ; ++i)
{
out0[i] = b[0] * in0[i] + b[1] * wi[1] + a[1]
*
wo[1];
wi[1] = in0[i];
wo[1] = out0[i];
}
もともと、アナログフィルターとデジタルフィルターはまったく同じではないので、下図の様に周波数特性に違いが出てしまう。一番上がアナログフィルターの
周波数特性で、2番目がこんかいのデジタルフィルターで、一番下がアナログとデジタルの差である。1dBぐらいの差であると音の
レベルの違いは判ってしまうが、こんかいは差は小さいので実用的には問題ないレベルではないかと思う。
一般的に、係数を有限なBIT数に変換したり、有限なBIT数での乗算と加算を計算するときに演算誤差が発生する。(参考)
さて、フランス発の数値演算ライブラリ SCILAB を使ってディエン
ファシス(de-emphasis)IIR
フィルタの係数を計算するサンプルプログラム(de-emphasis.sci)を作ってみたので紹介しよう。
1次のフィルターは双線形変換で求めたが、アナログの時定数2のほうを手動で補正してアナログとの差が小さくなるように合わせこんでいる(15uの方を
12.5%増しで計
算している)ので、50/15uをそのまま双線形変
換した値とは異なっている。双線形変換の場合、アナログとデジタルの間で、周波数がリニアに変換されず、たかめの周波数ではアナログとデジタルの周波数の
違いが大きくなる。そこで、今回は、高い周波数の方の15uの値を手動で特性の差が小さくなるように調整した。
また、2次以上のフィルターの計算では、scilabのleast-squareの関数(たぶん、アナログとデジタルの振幅特性の2乗差が小さくなるよう
に、係数を探索するアルゴリズム)を使用している。
はじめに 変換の方法をひとつ選ぶ。
上右側にあるstep1 の(1)で値の設定、
step1 の(2)でIIRの係数を求めて周波数特性を描く。
step2の
(1)でフィルターの安定性の確認を行う。
極 ポール pole Xと、零点 zero ○を 求めて、極 pole Xがおおきさ1の単位円の内側に入っていることを確認する。
step2の
(2)では、実際にSCILABを使って、振幅が1のSIN波をつくり それを入力としてIIRフィルタに入れたときの出力を計算して、理論値と計算値に
違いがないかを確認できる。
たかめの周波数の信号になると、信号に対してサンプリングの間隔が荒くなってしまうため、SIN波をサンプリングするとSIN波の形とはだいぶ違ったもの
になる。下図のXマークがついたところが、16KHzのSIN波をサンプリングした例である(サンプリング周波数は44.1KHz)。
サンプリングされたデジタル信号からの振幅の推定は、
サンプリングされたものから最小2乗法を使って ちょうどピッタリ合う連続的なSIN波を求めることで、IIRフィルターの出力の振幅を推定している。上
図は、16000Hzの、デジタルフィルターの利得の理論値が-9.0855823dBに対して、IIRの出力は-9.0700912dBとなっている一
例である。
但し、過渡的な部分等で、見かけ上 DC成分が存在しているように見える場合もあるが、ここではDC成分の補正はしていない。
step3では、ここで求めたIIRのフィルターの係数をテキストファイルに書き出すものである。
実用的には、多段のフィルターは2次のIIRフィルターの組み合わせで合成されることがあるが、ここでは、2次フィルターで分割した形式のものにはなって
いない。(バンドパスフィルターを4つの2次フィルターで構成したときの例。 ずらしたピークを組み合わ
せることで全体の特性を出している。)
step4では、一番はじめだけ1でそれ以降はすべて零の値(インパルス)を入力したときの出力の波形を見ることができる。入出力の動作チェックにも使え
るかもしれない。 (インパルスの波形の一例)
step5では、実際にIIRフィルターの音を聞いてみようと言うもので、.wavファイルの頭の30秒だけ読み込んで(maxdurationで長さを
設定する)、フィルターを計算して、また、.
wavファイルに書き出すものである。step5は、scilabのバージョン、OSの種類、サウンド・デバイス、PCのメモリー容量などに依存している
ので、も
しかしたら動かないかもしれない。また、計算に少々時間がかかる。
このサンプルを実際に動作させるためには、
ご使用されるプログラミング環境に合わせて修正・変更・追加などが必要かもしれません。
また、バグが含まれている可能性があります。
万一、このサンプルを動作させる場合は、あなたの責任でおこなってくださいね。
//-------------------------------------------------------------------------------------------
//
// IIR digital de-emphasis filter design
// as almost same as analog de-emphasis filter 50/15uS
//
// for window scilab-4.1.2
//
//-------------------------------------------------------------------------------------------
// PLEASE PAY ATTENTION that this program may have some bugs and also
you may modify program
// to fit your circumstances.
// If you use this program, everything should be done by your own risk.
// Thanks.
//===========================================================================================
// global variables No. 1
c50=50.0; // constant 1
c15=15.0; // constant 2
fs=44100.0; // sampling frequency
iiro=4; // oder of iir filter
start_freq=20.0;
end_freq=20000.0;
step_freq=1000.0; // many is good
scale_mode=0; // 0 linear, 1 log
trans_mode=1; // 0 least-square filter design, 1 bilinear
transform (= SOU SENKEI HENKAN in jappanese ) filter design
c15_change=0.0; // c15 = c15 * (1.0 + c15_change/100) This is available
only when trans_mode=1
//
z=poly(0,'z');
H1=z/(z-.5);
H0=syslin('d',H1); // dummy set, digital discrete time system
s=poly(0,'s');
S1=(1+2*s)/s^2;
S1A=syslin('c',S1); // dummy set, analog continuous time
system
//
//-------------------------------------------------------------------------------------------
// choose trans_mode
SEL_CODE=x_choose(['bilinear transform filter design'; 'SOU SENKEI
HENKAN + HOSEI filter design'; 'least-square filter desin'],['Please
select one'],'default');
if SEL_CODE == 1 then
trans_mode=1;
elseif SEL_CODE == 2 then
trans_mode=1;
c15_change=12.5;
disp('message: constant 2 correction factor is set 12.5');
elseif SEL_CODE == 3 then
trans_mode=0;
else
trans_mode=1;
end
if trans_mode == 0 then
disp('least-square filter design');
elseif trans_mode == 1 then
disp('bilinear transform (= SOU SENKEI HENKAN in jappanese )
filter design');
end
//
//-------------------------------------------------------------------------------------------
function [wc50, wc15, wfs, wiiro, wc15_change]= set_constant()
if trans_mode==0 then
// 0 least-square filter design,
txt1=['constant 1 (default 50us)';'constant 2 (default 15us)';
'sampling frequency (default 44.1KHz)'; 'order of IIR filter'];
wstr1=sprintf('%f',c50);
wstr2=sprintf('%f',c15);
wstr3=sprintf('%f',fs);
wstr4=sprintf('%d',iiro);
sig1=x_mdialog('Input constant of analog de-emphasis filter,
sampling frequency and IIR order',txt1, [wstr1 ; wstr2 ; wstr3 ; wstr4
]);
if sig1==[] then
arg1=evstr(wstr1);
arg2=evstr(wstr2);
arg3=evstr(wstr3);
arg4=evstr(wstr4);
else
arg1=evstr(sig1(1));
arg2=evstr(sig1(2));
arg3=evstr(sig1(3));
arg4=evstr(sig1(4));
end
wc50=arg1;
wc15=arg2;
wfs=arg3;
wiiro=arg4;
wc15_change=0.0;
end //if trans_mode==0 then
//
//
//
if trans_mode==1 then
// 1 bilinear transform filter design
txt1=['constant 1 (default 50us)';'constant 2 (default 15us)';
'sampling frequency (default 44.1KHz)'; 'constant 2 correction factor
[%] (ex: 12.5)'];
wstr1=sprintf('%f',c50);
wstr2=sprintf('%f',c15);
wstr3=sprintf('%f',fs);
wstr4=sprintf('%f',c15_change);
sig1=x_mdialog('Input constant of analog de-emphasis filter,
sampling frequency and constant 2 correction factor ',txt1, [wstr1 ;
wstr2 ; wstr3; wstr4 ]);
if sig1==[] then
arg1=evstr(wstr1);
arg2=evstr(wstr2);
arg3=evstr(wstr3);
arg4=evstr(wstr4);
else
arg1=evstr(sig1(1));
arg2=evstr(sig1(2));
arg3=evstr(sig1(3));
arg4=evstr(sig1(4));
end
wc50=arg1;
wc15=arg2;
wfs=arg3;
wiiro=0;
wc15_change=arg4;
end //if trans_mode==1 then
endfunction
//---------------------------------------------------------------------------------------------------------------
function factor0=correct_factor( wc15)
//
fc=1.0 / ( (wc15 * 0.000001) * 2.0 * %pi );
wd= (fc / (fs /2.0)) * %pi;
fcc=tan( wd / 2.0) * 2.0 / ( 1. / fs) / ( 2.0 * %pi);
factor0= (fc /fcc - 1.0 ) * 100.0; // beacause unit is [%]
endfunction
//---------------------------------------------------------------------------------------------------------------
function [freqa, freqd, kosuu]=get_freqs()
//
mode0=scale_mode;
if end_freq > (1.1 * (fs/2.0)) then
end_freq= 0.9 * (fs/2.0);
end
if mode0==0 then // linear scale
step_freq=(end_freq-start_freq)/step_freq;
freqa=(start_freq:step_freq:end_freq);
freqd=((start_freq/fs):(step_freq/fs):(end_freq/fs));
end
if mode0==1 then // log scale
step0= (log(end_freq) - log(start_freq)) / step_freq;
bairitu0= exp( step0 );
freqa=zeros(1,2);
freqd=zeros(1,2);
freqa(1)=start_freq;
freqd(1)=freqa(1)/fs;
for v=1:int(step_freq)
freqa(v+1)=freqa(v) * bairitu0;
freqd(v+1)=freqa(v)/fs;
end
end
s0=size(freqa);
kosuu=s0(1,2);
endfunction
//---------------------------------------------------------------------------------------------------------------
function [wH0, wS1A , wiiro2]=filterdesign()
// analog_response
//
// dom='c' for a continuous time system,
// dom='d' for a discrete time system,
// n for a sampled system with sampling
period n (in seconds).
//
n-1
n-2
// B(z)
b(1)z + b(2)z + .... + b(n)
// H(z)= ---- = ---------------------------------
//
n-1 n-2
// A(z) z +
a(2)z + .... + a(n)
if trans_mode==0 then
// least-square filter design
//
s=poly(0,'s');
H1=(1+(c15 * 0.000001)*s)/(1+(c50 * 0.000001)*s),
wS1A=syslin('c',H1);
disp( wS1A );
//
[freqa, freqd, kosuu]=get_freqs();
[freqs, respa]=repfreq(wS1A, freqa);
freqz=zeros(1,2);
freqz(1)=0;
freqz(2)= fs /2.0;
[freqs, respz]=repfreq(wS1A, freqz);
wrespd=zeros(1,kosuu+2);
wfreqd=zeros(1,kosuu+2);
//
for v=1:kosuu
wrespd(v+1)= abs(respa(v));
wfreqd(v+1)= freqa(v) / (fs / 2.);
end
//
wrespd(1)=abs(respz(1));
wfreqd(1)=0.0;
wrespd(kosuu+2)=abs(respz(2));
wfreqd(kosuu+2)=1.0;
//
wH0=yulewalk(iiro,wfreqd,wrespd);
//
disp( wH0 );
end // if trans_mode==0 then
if trans_mode==1 then
// bilinear transform design
//
s=poly(0,'s');
H1=(1+(c15 * 0.000001)*s)/(1+(c50 * 0.000001)*s),
wS1A=syslin('c',H1);
disp( wS1A );
// bilinear transform from including correction factor
c15=c15 * ( 1.0 + c15_change/100.0);
H1=(1+(c15 * 0.000001)*s)/(1+(c50 * 0.000001)*s),
wS1A2=syslin('c',H1);
wS1Ass=tf2ss(wS1A2); //Now in state-space form
sl1=cls2dls(wS1Ass,1/fs); //sl1= output of cls2dls
wH0=ss2tf(sl1); // Converts in transfer form
disp( wH0 );
end // if trans_mode==1 then
[H0r,H0nx]=syssize( wH0 ); // get size
wiiro2=H0nx;
H0bunbo=denom( wH0 ); // get BUNBO
H0bunsi=numer( wH0 ); // get BUNSHI
//H0poles=roots( H0bunbo ); // get poles
//H0zeros=roots( H0bunsi ); // get zeros
[wcoeff_bunbo]=get_coeff( H0bunbo, wiiro2 );
[wcoeff_bunsi]=get_coeff( H0bunsi, wiiro2 );
//plzr( wH0 ); // plot zeros and poles
//
global ac0
global bcb0
global bc0
//
//disp('digital discrete time system');
//disp( H0nx );
//disp( '*bunbo/poles/x*');
//disp( H0bunbo);
//disp( wcoeff_bunbo(1), 'a[0] is always 1' );
for v=1:wiiro2
ac0(v)= - wcoeff_bunbo(v+1);
wstr1= 'a[' + string(v) + ']';
//disp( ac0(v), wstr1 );
end
//disp('poles are');
//disp( H0poles);
//disp( '*bunsi/zeros/o*')
//disp( H0bunsi);
bcb0=wcoeff_bunsi(1);
//disp( wcoeff_bunsi(1), 'b[0]' );
for v=1:wiiro2
bc0(v)= wcoeff_bunsi(v+1);
wstr1= 'b[' + string(v) + ']';
//disp( bc0(v), wstr1 );
end
//disp('zeros are');
//disp( H0zeros);
endfunction
//---------------------------------------------------------------------------------------------------------------
function freq_response(disp0, sub0, H0, S1A)
//
wb0=xget('window'); // stack old window
xset('window',disp0); // create new windows
clf();
//
subplot(311);
[freqa, freqd, kosuu]=get_freqs();
[freqs,respa]=repfreq(S1A, freqa);
[db_fft1,phi_fft1] =dbphi(respa);
gainplot(freqa,db_fft1,phi_fft1);
wstr1 = 'analog frequency
response
Hz'
xtitle( wstr1 ,'','dB');
subplot(312);
[frq,respf]=repfreq(H0, freqd );
[db_fft2,phi_fft2] =dbphi(respf);
gainplot(freqa,db_fft2,phi_fft2);
wstr1 = 'IIR digital filter frequency
response Hz'
xtitle( wstr1,'','dB' );
subplot(313);
gainplot(freqa,(db_fft2-db_fft1),(phi_fft2-phi_fft1));
wstr1 =
'difference
Hz'
xtitle( wstr1,'','dB' );
//
xset('window',wb0); // push old windows
endfunction
//===============================================================================================================
// check routine
//
//
iiro2=0; // order of the IIR filter
mc0=10; // maximum order IIR filter quantity
global ac0
global bcb0
global bc0
global wk0
ac0=zeros(1,mc0); // coefficient matrix of a[1,..,mc0]
bcb0=zeros(1,1); // coefficient matrix of b[0]
bc0=zeros(1,mc0); // coefficient matrix of b[1,..,mc0]
wk0=zeros(1,mc0*2); // data stack memory
mc1=1; // maximum 1st order IIR filter quantity
global ac1
global bcb1
global bc1
global wk1
ac1=zeros(mc1,1); // coefficient matrix a[*][1]
bcb1=zeros(mc1,1); // coefficient matrix of b[*][0]
bc1=zeros(mc1,1); // coefficient matrix of b[*][1]
wk1=zeros(mc1,2); // data stack memory
mc2=5; // maximum 2nd order IIR filter cascade quantity
global ac2
global bcb2
global bc2
global wk2
ac2=zeros(mc2,2); // coefficient matrix of b[*][1,2]
bcb2=zeros(mc2,1); // coefficient matrix of b[*][0]
bc2=zeros(mc2,2); // coefficient matrix of b[*][1,2]
wk2=zeros(mc2,4); // data stack memory
//
freqx=5000.0; // Hz
cyclex=5;
skip_cyclex=2;
//
sin_delta=0.1; // dummy set
sin_level=1.0; // sin's level when actual IIR calculation
//
in0=zeros(1,1); // dummy set
out0=zeros(1,1); // dummy set
m=0; // dummy set // size of input
xopt0=zeros(1,2); // dummy set
xopt1=zeros(1,2); // dummy set
//
//---------------------------------------------------------------------------------------------------------------
function [wcoeff]=get_coeff( wH0bunsi, wiiro2 )
//
z=poly(0,'z');
//
H0nx=wiiro2;
wcoeff=zeros(1,H0nx+1);
wcoeff(H0nx+1)= horner( wH0bunsi, 0.);
for v=1: H0nx
wH0bunsi=(wH0bunsi-wcoeff(H0nx+1-(v-1))) / z;
wcoeff(H0nx+1-v)= horner( wH0bunsi, 0.);
end
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function [wiiro2]=system_stable_check( disp0, wH0, wS1A)
//
wb0=xget('window'); // stack old window
xset('window',disp0); // create new windows
clf();
[H0r,H0nx]=syssize( wH0 ); // get size
wiiro2=H0nx;
H0bunbo=denom( wH0 ); // get BUNBO
H0bunsi=numer( wH0 ); // get BUNSHI
H0poles=roots( H0bunbo ); // get poles
H0zeros=roots( H0bunsi ); // get zeros
[wcoeff_bunbo]=get_coeff( H0bunbo, wiiro2 );
[wcoeff_bunsi]=get_coeff( H0bunsi, wiiro2 );
plzr( wH0 ); // plot zeros and poles
//
global ac0
global bcb0
global bc0
//
disp('digital discrete time system');
disp( H0nx );
disp( '*bunbo/poles/x*');
disp( H0bunbo);
disp( wcoeff_bunbo(1), 'a[0] is always 1' );
for v=1:wiiro2
ac0(v)= - wcoeff_bunbo(v+1);
wstr1= 'a[' + string(v) + ']';
disp( ac0(v), wstr1 );
end
disp('poles are');
disp( H0poles);
disp( '*bunsi/zeros/o*')
disp( H0bunsi);
bcb0=wcoeff_bunsi(1);
disp( wcoeff_bunsi(1), 'b[0]' );
for v=1:wiiro2
bc0(v)= wcoeff_bunsi(v+1);
wstr1= 'b[' + string(v) + ']';
disp( bc0(v), wstr1 );
end
disp('zeros are');
disp( H0zeros);
//
//
xset('window',wb0); // push old windows
endfunction
//-------------------------------------------------------------------------------------------
function [wfreqx, wcycle, wskip_cycle]= set_synth()
//
txt1=['frequency [Hz]'; 'cycle (integral number)'; 'start
skip cycle (integral number)'];
wstr1=sprintf('%f',freqx);
wstr2=sprintf('%d',cyclex);
wstr3=sprintf('%d',skip_cyclex);
sig1=x_mdialog('do actual IIR filter calculation',txt1,
[wstr1 ; wstr2 ; wstr3 ]);
if sig1==[] then
arg1=evstr(wstr1);
arg2=evstr(wstr2);
arg3=evstr(wstr3);
else
arg1=evstr(sig1(1));
arg2=evstr(sig1(2));
arg3=evstr(sig1(3));
end
wfreqx=arg1;
wcycle=arg2;
wskip_cycle=arg3;
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function [win0,wsin_delta,xm,xsm]= make_sin()
//
wsin_delta = freqx / fs * 2. * %pi;
xm= int( ((1.0/ freqx) / (1.0 /fs ) * cyclex) + 1.0);
xsm= int( ((1.0/ freqx) / (1.0 /fs ) * skip_cyclex) + 1.0);
win0=zeros(1,xm);
for v=1:xm
win0(v)= sin_level * sin( wsin_delta * (v-1));
end
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function [win0,wout0,xm]=start_skip()
xm=m-sm;
win0=zeros(1,xm);
wout0=zeros(1,xm);
for v=(sm+1):m
win0( v - sm) = in0(v);
wout0( v - sm) = out0(v);
end
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function [wout0]= cal_iir2(init_flag)
//
global wk0
if init_flag == 1 then
for v=1:(mc0*2)
wk0(v)=0.0;
end
end
//
//
wout0=zeros(1, m);
//
for i=1:m
w = in0(i);
for v=1:iiro2
w= w + ac0(v) * wk0(v);
wout0(i)= wout0(i) + bc0(v) * wk0(v);
end
wout0(i) = wout0(i) + bcb0 * w;
for v=1:(iiro2-1)
wk0( iiro2 - v + 1) = wk0( iiro2 - v);
end
wk0(1)=w;
end
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function plotfit(disp0)
wb0=xget('window'); // stack old window
xset('window',disp0); // create new windows
clf();
//
g0= 20.0 * log10( xopt1(1) / xopt0(1));
ph0= 360 * (xopt1(2)-xopt0(2))/2./%pi
//
freqa=[freqx,freqx];
freqd=[(freqx/fs),(freqx/fs)];
[freqs,respa]=repfreq(S1A, freqa);
[db_fft1,phi_fft1] =dbphi(respa);
[frq,respf]=repfreq(H0, freqd );
[db_fft2,phi_fft2] =dbphi(respf);
//
subplot(211);
tm=[0:1:(m-1)];
tm=tm';
plot(tm,in0','+',tm,yth(tm,xopt0),'-');
wstr1 = 'input of iir of ' + string(freqx) + 'Hz /' + '
theoretical analog gain' + string(db_fft1(1)) + ' dB' ;
xtitle( wstr1 ,'','');
//
subplot(212);
plot(tm,out0','+',tm,yth(tm,xopt1),'-');
wstr1 = 'output of iir of ' + string(g0) + ' dB ' + string( ph0)
+ ' vs ' + ' theoretical digital gain' + string(db_fft2(1)) + '
dB' ;
xtitle( wstr1 ,'','');
//
xset('window',wb0);
endfunction
//---------------------------------------------------------------------------------------------------------------
function y = yth(t, x)
y = x(1) * sin( sin_delta * t + x(2))
//y = x(1) * sin( t + x(2))
endfunction
//--
// myfun(x0, tm, in0, wm)
// wm .* ( yth(tm, x0) - in0)
function e = myfun(x, tm, ym, wm)
e = wm .* ( yth(tm, x) - ym )
endfunction
//--
function [xopt]=sin_fit(wym)
// ym is samples
tm=[0:1:(m-1)];
tm=tm';
wm=ones(m,1);
// estimated function
// initial parameter
wz=abs(wym(1));
for v=1:m
if abs(wym(v)) > wz then
wz=abs(wym(v));
end
end
x0 = [ wz ; 0.0];
// 1- the simplest call
[f,xopt, gropt] = leastsq(list(myfun,tm,wym',wm),x0);
disp( xopt,'xopt');
endfunction
//---------------------------------------------------------------------------------------------------------------
function save_para()
//
savefilename= input(' + enter file name for save parameters (ex:
para1.txt)',["string"]);
[fd0,err0]=mopen(savefilename,'w');
wstr1='/* ' + string(iiro2) + ' ORDER IIR DIGITAL
DE-EMPHASIS FILTER
COEFFICIENT */'
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* CONSTANT1 = ' + string(c50) +
'
*/'
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* CONSTANT2 = ' + string(c15) +
'
*/'
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* SAMPLING FREQUENCY = ' + string(fs) +
'
*/'
mfprintf(fd0,'%s\n',wstr1);
mfprintf(fd0,'\n');
for v=1:iiro2
wstr1 = 'a[' + string(v) + ']=' + string( ac0(v)) ;
//mputstr(wstr1,fd0);
mfprintf(fd0,' %s;\n',wstr1);
end
wstr1 = 'b[0]=' + string( bcb0) ;
mfprintf(fd0,' %s;\n',wstr1);
for v=1:iiro2
wstr1 = 'b[' + string(v) + ']=' + string( bc0(v)) ;
//mputstr(wstr1,fd0);
mfprintf(fd0,' %s;\n',wstr1);
end
//mfprintf(fd0,'\n');
mfprintf(fd0,'\n');
mfprintf(fd0,'\n');
mfprintf(fd0,'\n');
wstr1='/* An example of TYOKUSETU-GATA
2
*/';
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* in[i] is input, out[i] is
output
*/';
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* w[] are memory to keep stack old
data
*/';
mfprintf(fd0,'%s\n',wstr1);
wstr1='/* initialize all w[1]=.....=0.0, and
then use it */';
mfprintf(fd0,'%s\n',wstr1);
for v=1:iiro2
wstr1= 'w[' + string(v) + '] = 0.0';
mfprintf(fd0,' %s;\n',wstr1);
end
mfprintf(fd0,'\n');
mfprintf(fd0,'\n');
wstr1='for (i=0; i< number ; ++i) ';
mfprintf(fd0,' %s\n',wstr1);
wstr1='{';
mfprintf(fd0,' %s\n',wstr1);
wstr1='w[0] = in[i] + ';
for v=1:iiro2
wstr1= wstr1 + 'a[' + string(v) + '] * w[' + string(v) + ']';
if v < iiro2
wstr1= wstr1 + ' + ';
end
end
mfprintf(fd0,' %s;\n',wstr1);
wstr1='out[i] = ';
for v=0:iiro2
wstr1= wstr1 + 'b[' + string(v) + '] * w[' + string(v) + ']';
if v < iiro2
wstr1= wstr1 + ' + ';
end
end
mfprintf(fd0,' %s;\n',wstr1);
mfprintf(fd0,'\n');
for v=1:iiro2
wstr1= 'w[' + string(iiro2-v+1) +'] = w[' +
string(iiro2-v) + ']';
mfprintf(fd0,' %s;\n',wstr1);
end
wstr1='}';
mfprintf(fd0,' %s\n',wstr1);
//
err0=mclose([fd0]);
endfunction
//-------------------------------------------------------------------------------------------
impulse_steps=100;
//-------------------------------------------------------------------------------------------
function [ximpulse_steps]= set_synth2()
//
txt1=['steps (integral number)'];
wstr1=sprintf('%d',impulse_steps);
sig1=x_mdialog('impulse response based on do actual IIR
filter calculation',txt1, [wstr1 ]);
if sig1==[] then
arg1=evstr(wstr1);
else
arg1=evstr(sig1(1));
end
ximpulse_steps=arg1;
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function [win0,wm]= make_impulse(ximpulse_steps)
//
win0=zeros(1,ximpulse_steps);
win0(1)=sin_level;
wm=ximpulse_steps;
//
endfunction
//---------------------------------------------------------------------------------------------------------------
function plotimpulse(disp0)
wb0=xget('window'); // stack old window
xset('window',disp0); // create new windows
clf();
//
plot(out0);
wstr1 = 'impulse response ' ;
xtitle( wstr1 ,'','');
//
xset('window',wb0);
endfunction
//-----------------------------------------------------------------------------------
function plotimpulse2(disp0,wdat1x)
wb0=xget('window'); // stack old window
xset('window',disp0); // create new windows
clf();
//
sz=size(wdat1x);
if sz(1,1)== 2 then
subplot(311);
plot(out0);
wstr1 = 'impulse response ' ;
xtitle( wstr1 ,'','');
subplot(312);
win1=zeros(1,impulse_steps);
for v=1:impulse_steps
win1(1,v)=wdat1x(1,v);
end
plot(win1);
wstr1 = 'wdat ch1 ' ;
xtitle( wstr1 ,'','');
subplot(313);
win1=zeros(1,impulse_steps);
for v=1:impulse_steps
win1(1,v)=wdat1x(2,v);
end
plot(win1);
wstr1 = 'wdat ch2 ' ;
xtitle( wstr1 ,'','');
elseif sz(1,1) == 1 then
subplot(211);
plot(out0);
wstr1 = 'impulse response ' ;
xtitle( wstr1 ,'','');
subplot(212);
win1=zeros(1,impulse_steps);
for v=1:impulse_steps
win1(1,v)=wdat1x(1,v);
end
plot(win1);
wstr1 = 'wdat ' ;
xtitle( wstr1 ,'','');
end
//
xset('window',wb0);
endfunction
//---------------------------------------------------------------------------------------------------------------
//
// .wav file process
//
//
// for .wav 1
chs1=0; // channels
qty1=0; // data quantity, samples
size1=0; // actual loaded data quantity
fs1=0; // sampling frequency
bit1=0; // bits
wavfile1=''; // file name, this will be overwritten.
wdat1=zeros(1,10);// data of the .wav, only one first channel,
this will be overwritten.
wdat2=zeros(1,10);// data of synthesized .wav, this will be
overwritten.
// for others
f412=0; // flag to detect scilab 4.1.2
defch1=1; // default channel 1
f_win=1; // flag if windows
//
// max stack size of input wave file
maxduration=30; // unit is second
//-----------------------------------------------------------------
if isdir('c:\\') then
f_win=1;
else
f_win=0;
end
//-------------------------------------------------------------------
function [xwdat1,wavfile1,chs1,qty1,fs1,bit1,f412]=get_wavfile_pro()
// choose wave file
wavfile1=tk_getfile(Title="Choose xxx.wav file name");
// read channels and samples
cs1=wavread(wavfile1,'size');
chs1=cs1(2); // channel
qty1=cs1(1); // samples
//...
if chs1 > 2 then // invert data for scilab-4.1.2
chs1=cs1(1);
qty1=cs1(2);
f412=1;
else
f412=0;
end
//...
sizeof0=8;
maxstacksize= 44100 * 2 * maxduration * sizeof0; // fs=44.1KHz 2
channels * maxduration seconds
if ( chs1 * qty1 * sizeof0 ) > maxstacksize then
qty1 = int((maxstacksize / (chs1 * sizeof0)));
disp('Waring: force to decrease data quantity(samples) ');
end
sz=stacksize();
if (sz(1)-sz(2)) < maxstacksize then
stacksize( (maxstacksize+sz(1)));
disp('increase stack memory ');
end
//
if f412 == 1 then // for windows scilab-4.1.2
[xwdat1,fs1,bit1]=wavread(wavfile1,[1,qty1]);
else
[xwdat1b,fs1,bit1]=wavread(wavfile1,[1,qty1]);
xwdat1=xwdat1b';
end
//
disp('read done');
endfunction
//----------------------------------------------------------------
function snd_play2(xwdat2)
// this sound doesnot work well on windows scilab-3.1.1 and linux
scilab-3.1
// but, this sound works on windows scilab-4.1.2. But, linux
scilab-4.1.2 doesnot!
//
sz=size(xwdat2);
size2=sz(2);
if f_win == 1 then
if f412 == 1 then // for windows scilab-4.1.2
sound(xwdat2 ,fs1,bit1);
else
// for windows scilab-3.1.1
disp('This function does not work.');
end
else // if f_win == 1 then
if f412 == 1 then // for scilab-4.1.2
disp('If sound setting is good for scilab, this function maybe
work.');
sound(xwdat2 ,fs1,bit1);
else
disp('This function does not work.');
end
end //if f_win == 1 then
endfunction
//
//----------------------------------------------------------------
function snd_save2( xwdat2)
wavefilename= input(' + enter file name for saved .wav file
=>',["string"]);
//
if f412 == 1 then // for windows scilab-4.1.2
wavwrite(xwdat2 ,fs1,bit1,wavefilename );
else
// for windows scilab-3.1.1
wavwrite(xwdat2',fs1,bit1, wavefilename);
end
endfunction
//
//----------------------------------------------------------------
// function display the .wav property
function disp_pro_wav()
disp(qty1,'data quantity',bit1,
'bits',chs1,'channels',fs1,'sampling frequency');
endfunction
//--------------------------------------
function [xwdat2]=do_iir_filtering(xwdat1)
sz=size(xwdat1);
xwdat2=zeros(sz(1),sz(2));
disp( sz(1),'channels ', sz(2),'data quantity ');
//
wk0=zeros(sz(1),iiro2);
//
for i=1:sz(2) // long
a=int( i / 44100);
b= i - 44100 * a;
if b == 0 then
disp( i );
end
for p=1:sz(1) // ch
w = xwdat1(p,i);
for v=1:iiro2
w= w + ac0(v) * wk0(p,v);
xwdat2(p,i)= xwdat2(p,i) + bc0(v) * wk0(p,v);
end
xwdat2(p,i) = xwdat2(p,i) + bcb0 * w;
for v=1:(iiro2-1)
wk0( p, iiro2 - v + 1) = wk0( p,iiro2 - v);
end
wk0(p,1)=w;
if xwdat2(p,i) > 1.0 then
xwdat2(p,i) =1.0;
elseif xwdat2(p,i) < -1.0 then
xwdat2(p,i)=-1.0;
end
end
end
//
disp('do iir filter done');
endfunction
//-------------------------------------------------------------------------------------
function [xwdat2]=do_iir_filtering2(wH0, xwdat1)
sz=size(xwdat1);
disp( sz(1),'channels ', sz(2),'data quantity ');
//
//
if sz(1) == 2 then
sl=tf2ss([ wH0, 0; 0, wH0]);
disp('from transfer to state-space');
xwdat2=dsimul(sl,xwdat1);
elseif sz(1) == 1 then
sl=tf2ss(wH0);
disp('from transfer to state-space');
xwdat2=dsimul(sl,xwdat1);
else
disp('error: not define yet. ');
end
//
disp('do iir filter done');
endfunction
//-------------------------------------------------------------------------------------
function [xwdat2]=do_iir_filtering3(wH0, xwdat1)
sz=size(xwdat1);
disp( sz(1),'channels ', sz(2),'data quantity ');
//
//
if sz(1) == 2 then
[H0r,H0nx]=syssize( wH0 ); // get size
viiro2=H0nx;
H0bunbo=denom( wH0 ); // get BUNBO
H0bunsi=numer( wH0 ); // get BUNSHI
vnum=[ H0bunsi,0; 0,H0bunsi];
vdenom=[ H0bunbo,0; 0,H0bunbo];
up=zeros(2,viiro2);
yp=zeros(2,viiro2);
xwdat2=rtitr(vnum,vdenom,xwdat1 ,up,yp);
elseif sz(1) == 1 then
[H0r,H0nx]=syssize( wH0 ); // get size
viiro2=H0nx;
H0bunbo=denom( wH0 ); // get BUNBO
H0bunsi=numer( wH0 ); // get BUNSHI
vnum= H0bunsi;
vdenom=H0bunbo;
up=zeros(1,viiro2);
yp=zeros(1,viiro2);
xwdat2=rtitr(vnum,vdenom,xwdat1 ,up,yp);
else
disp('error: not define yet. ');
end
//
disp('do iir filter done');
endfunction
//
//
//
//----------------------------------------------------------------
//===================================================================
//
// ++ MENU MENU MENU =====================
//
// Add menu buttons of which name are 'a_plotwav' and ''
//
ADD_MENU_PLOT=1; // set ADD_MENU 1
to add menu button of some functions
//
//
if ADD_MENU_PLOT == 1 then
delmenu('step1');
addmenu('step1',[ '(1)set_constant '; '(2)design IIR filter' ]);
step1=[ '[c50, c15, fs, iiro, c15_change]=set_constant()' ;' [H0,
S1A, iiro2]=filterdesign(); freq_response(0, 3, H0, S1A);'] ;
end //if ADD_MENU_PLOT == 1 then
//
//
//
ADD_MENU_KAISEI=1; // set ADD_MENU 1 to add menu button of
some functions
//
if ADD_MENU_KAISEI == 1 then
delmenu('step2');
addmenu('step2',[ '(1)system stable check '; '(2)gain by actual
IIR calculation' ]);
step2=[ '[iiro2]=system_stable_check(1, H0, S1A);' ; '[freqx, cyclex,
skip_cyclex]= set_synth(); [in0,sin_delta,m,sm]= make_sin(); [out0]=
cal_iir2(1); [in0,out0,m]=start_skip(); [xopt0]=sin_fit(in0);
[xopt1]=sin_fit(out0); plotfit(3);'] ;
end //if ADD_MENU_KAISEI == 1 then
//
//
//
ADD_MENU_SAVE=1; // set ADD_MENU 1 to add menu button of
some functions
//
if ADD_MENU_SAVE == 1 then
delmenu('step3');
addmenu('step3',[ '(1)save coefficient in a text file.' ]);
step3=[ 'save_para();'] ;
end //if ADD_MENU_SAVE == 1 then
//
//
//
ADD_MENU_IMPULSE=1; // set ADD_MENU 1 to add menu button of
some functions
//
if ADD_MENU_IMPULSE == 1 then
delmenu('step4');
addmenu('step4',[ '(1a)impulse response ', '(1b)impulse response
(state-space method)']);
step4=[ '[impulse_steps]= set_synth2(); [in0,m]=
make_impulse(impulse_steps); [out0]= cal_iir2(1); plotimpulse(4)';
'[impulse_steps]= set_synth2(); [in0,m]= make_impulse(impulse_steps);
[out0]= do_iir_filtering2(H0, in0); plotimpulse(4)' ] ;
end //if ADD_MENU_IMPULSE == 1 then
////
//
//-----------------------------------------------------------------
//
ADD_MENU_WAV=1; // set ADD_MENU 1
to add menu button of some functions
//
//
if ADD_MENU_WAV == 1 then
delmenu('step5');
addmenu('step5',[ '(1)read a .wav file (read only limited duration)',
'(2a)do IIR filtering (rtitr)' , '(2b)do IIR filtering (takes time)'
,'(3)play the wav filtered' , '(4)save as a .wav file' ]);
step5=[ 'wdat1=zeros(1,1); wdat2=zeros(1,1);
[wdat1,wavfile1,chs1,qty1,fs1,bit1,f412]=get_wavfile_pro();
disp_pro_wav(); ','[wdat2]=do_iir_filtering3(H0, wdat1);',
'[wdat2]=do_iir_filtering(wdat1);','snd_play2(wdat2);','snd_save2(
wdat2);'];
end //if ADD_MENU_WAV == 1 then
//-----------------------------------------------------------------
//
ADD_MENU_WAVIMPU=1; // set ADD_MENU
1 to add menu button of some functions
//
//
if ADD_MENU_WAVIMPU == 0 then
delmenu('step6');
addmenu('step6',[ '(1)a .wav with impulse response (state-space
method)', '(2)wav filtered with impulse response (state-space
method)']);
step6=[ '[impulse_steps]= set_synth2(); [in0,m]=
make_impulse(impulse_steps); [out0]= do_iir_filtering2(H0, in0);
plotimpulse2(4,wdat1)' ,'[impulse_steps]= set_synth2(); [in0,m]=
make_impulse(impulse_steps); [out0]= do_iir_filtering2(H0, in0);
plotimpulse2(4,wdat2)'] ;
end //if ADD_MENU_WAVIMPU == 1 then
ディエンファシスのIIRフィルターの係数を16ビットに変換して、16ビットかける16ビットが32ビットの
乗算機を使って計算したとき、周波数特性がどのようになるかを調べるため、後半にあるプログラムを使って、擬似的に100Hz,5000Hz,
16000Hzの利得を計算してみた。ここでは前提条件として、16
ビットのPCMデータを入力して、16ビットのデータを出力すること
を想定している。
周波数
|
標準値
|
振幅 327267 (0dB)
|
振幅 33(-60dB)
|
100Hz
|
-0.00389dB
|
-0.004dB
|
-0.33dB
|
5000Hz
|
-4.53dB
|
-4.51dB
|
-4.76dB
|
16000Hz
|
-9.04dB
|
-9.09dB
|
-9.67dB
|
ぼほフルスイングである振幅が32767で 振幅が大きなときは だいたい標準値が出ているが、約-60dB(1/1000)まで振幅が小さいと、怪しげ
な値になっている。
更に、振幅を小さくして10にしたときの波形を下図の示す。灰色の出力波形に入力にないぎざぎざが発生している。
更に、減衰量がおおい16000Hzの波形を下図に示す。比較のため、浮動小数のdoubleで計算して最後に(short)で整数に変換して計算した出
力(計算精度を改善したもの)もこの図の一番下に加えてある。
下図では、周波数16000Hzで入力の振幅が3であると、理論上の出力の振幅は
1.059(=3x0.353183(-3dB)となる。振幅3はSIN波のピークの値であって、サンプリングが荒いため入力の実質的な値は、0,1,2
をとることが多く、出力はほぼ零になる計算であるが、出力が零にならないことが分かる。
比較のための一番したの浮動小数のdoubleの出力(計算精度を改善したもの)は零になっているが、これは、最後に(short)を使って整数に変換す
るときに、たとえば、
(short)0.789523024567117 = 0
(short)-0.602814426388397 =0
と置き換えられてしまうためである。それに反して、下記では32bitから16bitの置き換えを切り捨てでおこなっているため、誤差は平均するとマイ
ナスの値で生じることになる。
周波数が低いほど、入力の1周期分に対してのフィルターの演算量が多くなる。そこで、周波数の低い20Hzでの演算誤差の影響を見てみよう。下図は、周波
数20Hzの振幅30のSINを入力したときの出力の例である。出力の波形は滑らかではなく、ぎざぎざが生じている。 更に、周波数20Hzの振幅3の例では、まったく間違った値を出力している区間もある。
#define NCHANNEL2 2 /* チャンネル数 */
#define SHIFTx16 15 /*
data=(符号1ビット+データ15ビット) */
/* 係数16BIT 乗算機32BIT 版 */
void iir_deemphasis16(short *in0, short *out0, int init_flag,
unsigned long vol)
{
static long w[NCHANNEL2]; /* 前のデータを保持する記憶 */
long wout,wout2,w0;
int i;
/* de-emphasis IIR フィルターの係数 16bit換算の値。
32768=2^15が1に相当する。 */
short a1=20654; /* 0.6303142 * 2^15 */
short b0=15072; /* 0.4599584 * 2^15 */
short b1=-2958; /* -0.0902726 * 2^15 */
/* 前データが存在しないとき(例 初めての計算するときなど) wには零を入れる */
if ( init_flag == 1)
{
for (i=0;i<NCHANNEL2;++i) w[i] = 0;
}
for (i=0;i<NCHANNEL2;++i)
{
/* de-emphasis IIR フィルターの計算 */
w0= a1 * w[i];
w0 >>= SHIFTx16;
w0 += *(in0+i);
wout=b1 * w[i];
wout>>= SHIFTx16;
wout2= b0 * w0;
wout2 >>=SHIFTx16;
wout += wout2;
w[i]= w0;
/* ボリューム用の掛け算 */
/* 符号なし32bit整数のvolの値が32767以下ならば、volの値を乗算する */
/* vol=32768
が1倍に相当する。
*/
if (vol <= 32767 )
{
wout= wout * (long)vol;
wout >>=SHIFTx16;
}
/* 16bit の上限値と下限値の範囲になるようにする */
if (wout > 32767) wout=32767;
else if ( wout < -32768) wout=-32768;
*(out0+i)= (short)wout;
}
}
最後に、動作は保障できないが、もう少し精度のよいサンプルを示す。
係数は2の31乗をかけて、32bitの整数、
16bitの入力データは、2の12乗をかけて、28bitの整数に変換している。
ここでは、64bitの整数( __int64 または long long )が演算に使えると仮定している。
32bit x 28bit
は59bitになる(かりに ここでは 一番頭の1bitが符号を示すものとして考えている)。64bitの整数であるとオーバーフローに対してまだ
5bit分の余裕をもてる。但し、最後に、小数点のつじつまあわせに、1bit使ってしまうので、4bit分(=2の4乗は16)の余裕となるハズ、多
分。ディエンファシスフィルターの場合、利得が減衰する特性のフィルターなので出力も16bitを超えないと仮定すれば、IIRフィルターの計算の中で、
32bit x 28bit
の足し算は3回行われるので、2bit分(=2の2乗は4)あれば、オーバーフローがおきないことになる(定常出力の場合)。しかし、過渡的な応答の計算
の中では出力がどこまで大きくなるか分からないので、少し大きめに余裕をとってある。
まだ、28bitから 16bit
のデータに戻すときに、切り捨てでおこなっているので、あいかわらず誤差はよりマイナス側にでてくる。16bitのデータに戻す前に、小数点以下に適当な
値を加減算す
れば、見かけ上、誤差の平均を零として分散するようにできる かもしれない。
#define SHIFTx12 12 /* 28bit - 16bit */
#define NCHANNELS2 2 /* チャンネル数 */
/* 係数32BIT 乗算加算機32bit x 32(28)bit + 64(60)bit =
64(60)bit 途中計算28bit 版 */
void iir_deemphasis64(short *in0, short *out0, int init_flag)
{
static long w[2][NCHANNELS2]; /* 前のデータを保持する記憶
*/
long w0,x0,y0;
int i;
/* de-emphasis IIR フィルターの係数 32bit換算の値 */
long a1=1353589438; /* 0.6303142 * 2^31 */
long b0= 987753143; /* 0.4599584 * 2^31 */
long b1=-193858932; /* -0.0902726 * 2^31 */
/* 64bit 整数 __int64 叉は long long の有無 使い方は コンパイラーに依存する
! */
__int64 wout;
__int64 a64= 12345654321i64; /* 仮の意味のないデータをセット */
__int64 b64= 12345654321i64; /* 仮の意味のないデータをセット */
/* 前データが存在しないとき(例 初めての計算するときなど) wには零を入れる */
if ( init_flag == 1)
{
for (i=0;i<NCHANNELS2;++i) { w[0][i]
= 0; w[1][i] =0; }
}
for (i=0;i<NCHANNELS2;++i)
{
/* de-emphasis IIR フィルターの計算 */
x0=(long) *(in0+i);
/* 16bit から 28bit のデータにする */
x0 <<= SHIFTx12;
a64= b0;
b64= x0;
wout=a64 * b64; /* b0 * in; */
a64= b1;
b64= w[0][i];
wout += a64 * b64; /* b1 * w[0]; */
a64= a1;
b64= w[1][i];
wout += a64 * b64; /* a1 * w[1]; */
/*
上位32ビットを下位32ビットに移動し、32bitのy0に格納 */
wout >>= 32;
y0=(long)wout;
/* 小数点の調整 */
y0 <<=1;
/* 前データを格納 */
w[0][i]=x0;
w[1][i]=y0;
/* 28bitから 16bit のデータに戻す */
/* 右シフト演算であると 符号がマイナスのとき0が-1になってしまう対策 */
if (y0 < 0)
{
if (y0 > -4096)
y0=0;
else y0 >>= 12;
}
else y0 >>= 12;
/* 16bit の上限値と下限値の範囲になるようにする */
if (y0 > 32767) y0=32767;
else if ( y0 < -32768) y0=-32768;
*(out0+i)= (short)y0;
}
}
No.17b 2009年4月5日