我用C语言写了一个IIR 高通滤波器:
void iir_2nd_filter(int *d_x, int *d_y, int *x, int *y,
int factor1, int factor2, int ch_offset, int step, int nbytes)
{
int i;
// y[i] = (x[i] - x[i-1])
// - (x[i-1] - x[i-2])
// + y[i-1]
// + ((y[i-1]>>10)*factor1 - (y[i-2]>>10)*factor2);
y[ch_offset] = (x[ch_offset] - d_x[1])
- (d_x[1] - d_x[0])
+ d_y[1]
+((d_y[1]>>10)*factor1 - (d_y[0]>>10)*factor2);
y[step + ch_offset] = (x[step + ch_offset] - x[ch_offset])
- (x[ch_offset] - d_x[1])
+ y[ch_offset]
+((y[ch_offset]>>10)*factor1 - (d_y[1]>>10)*factor2);
nbytes = nbytes/4;
for(i=step*2+ch_offset; i<nbytes; i+=step) {
y[i] = (x[i] - x[i-step])
- (x[i-step] - x[i-(step<<1)])
+ y[i-step]
+ ((y[i-step]>>10)*factor1 - (y[i-(step<<1)]>>10)*factor2);
}
d_x[0] = x[i-(step<<1)];
d_x[1] = x[i-step];
d_y[0] = y[i-(step<<1)];
d_y[1] = y[i-step];
}
又用线性汇编写了一个功能相同的函数:
;extern void iir_2nd_Assembly(int *d_x, int *d_y, int *x, int *y,
; int factor1, int factor2, int ch_offset, int step, int nbytes);
.global iir_2nd_Assembly
;二阶IIR高通滤波器
iir_2nd_Assembly: .cproc d_x, d_y, x, y, factor1, factor2, ch_offset, step, nbytes ;线性汇编程序开始
; 变量声明
.reg xn,xn1,xn2,yn,yn1
.reg sum,tmp1,tmp2
SHL ch_offset, 2, ch_offset ;ch_offset = ch_offset*4
SHL step, 2, step ;step = step*4
LDW *d_x++, xn ;xn = x[n]
LDW *d_x, xn1 ;xn1 = x[n+1]
LDW *d_y++, yn ;yn = y[n]
LDW *d_y, yn1 ;yn1 = y[n+1]
ADD x, ch_offset, x ;
LDW *x, xn2 ;xn2 = x[n+2]
SUB xn2, xn1, tmp1 ;tmp1 = xn2 - xn1
SUB xn1, xn, tmp2 ;tmp2 = xn1 - xn
SUB tmp1, tmp2, sum ;sum = tmp1 - tmp2 = (xn2-xn1) - (xn1-xn)
ADD sum, yn1, sum ;sum = (xn2-xn1) - (xn1-xn) + yn1
SHR yn1, 10, tmp1 ;tmp1 = yn1>>10
MPY32 tmp1, factor1, tmp1 ;tmp1 = factor1*tmp1 = (yn1>>10)*factor1
SHR yn, 10, tmp2 ;tmp2 = yn>>10
MPY32 tmp2, factor2, tmp2 ;tmp2 = factor2*tmp2 = (yn>>10)*factor2
MV yn1, yn ;yn = yn1
SUB tmp1, tmp2, tmp1 ;tmp1 = tmp1 - tmp2 = (yn1>>10)*factor1 - (yn>>10)*factor2
ADD sum, tmp1, yn1 ;yn1 = sum + tmp1 = (xn2-xn1) - (xn1-xn) + yn1
; + ((yn1>>10)*factor1 - (yn>>10)*factor2)
ADD y, ch_offset, y
STW yn1, *y ;y[n+2] = yn1
MV xn1, xn ;xn = x[n+1]
MV xn2, xn1 ;xn1 = x[n+2]
SHR nbytes, 2, nbytes ;nbytes = nbytes/4
[nbytes] SUB nbytes, 1, nbytes ;nbytes -= 1
LOOP3: .trip 1 ;for循环起始位置
ADD x, step, x
LDW *x, xn2 ;xn2 = x[n+2]
SUB xn2, xn1, tmp1 ;tmp1 = xn2 - xn1
SUB xn1, xn, tmp2 ;tmp2 = xn1 - xn
SUB tmp1, tmp2, sum ;sum = tmp1 - tmp2 = (xn2-xn1) - (xn1-xn)
ADD sum, yn1, sum ;sum = (xn2-xn1) - (xn1-xn) + yn1
SHR yn1, 10, tmp1 ;tmp1 = yn1>>10
MPY32 tmp1, factor1, tmp1 ;tmp1 = factor1*tmp1 = (yn1>>10)*factor1
SHR yn, 10, tmp2 ;tmp2 = yn>>10
MPY32 tmp2, factor2, tmp2 ;tmp2 = factor2*tmp2 = (yn>>10)*factor2
MV yn1, yn ;yn = yn1
SUB tmp1, tmp2, tmp1 ;tmp1 = tmp1 - tmp2 = (yn1>>10)*factor1 - (yn>>10)*factor2
ADD sum, tmp1, yn1 ;yn1 = sum + tmp1 = (xn2-xn1) - (xn1-xn) + yn1
; + ((yn1>>10)*factor1 - (yn>>10)*factor2)
ADD y, step, y
STW yn1, *y ;y[n+2] = yn1
MV xn1, xn ;xn = x[n+1]
MV xn2, xn1 ;xn1 = x[n+2]
[nbytes] SUB nbytes, 1, nbytes ; nbytes -= 1
[nbytes] B LOOP3 ; if (nbytes!=0) goto loop ;for循环结束位置
STW xn1, *d_x--
STW xn, *d_x
STW yn1, *d_y--
STW yn, *d_y
.endproc ; 线性汇编程序结束
C文件中的测试函数如下:
#define Tn 1024
// IIR 输入
int IIR_In[Tn+4];
// IIR 输出
int IIR_Out[Tn+4];
// IIR 输入延迟
int delay_x[2] = {0,0};
// IIR 输出延迟
int delay_y[2] = {0,0};
extern void iir_2nd_Assembly(int *d_x, int *d_y, int *x, int *y,
int factor1, int factor2, int ch_offset, int step, int nbytes);
int iir_lowcut_test(void)
{
unsigned int bytes_read = 0, bytes_writed = 0;
int res = FR_OK;
res = f_open(&rec_file_ch1,"FileIn.wav", FA_READ);
res |= f_lseek(&rec_file_ch1, 44); //文件指针指向第一个音频数据的位置
if (FR_OK != res) {
return res;
}
res |= rec_wav_file_create("FileOut.wav", &rec_file_ch2, 48000, 32, 1);
if (FR_OK != res) {
return res;
}
while(!f_eof(&rec_file_ch1)) {
res = f_read(&rec_file_ch1, IIR_In, Tn*4, &bytes_read);
#if 1
iir_2nd_filter(delay_x, delay_y, IIR_In, IIR_Out, 967, 969, 0, 1, Tn*4);
#else
iir_2nd_Assembly(delay_x, delay_y, IIR_In, IIR_Out, 967, 969, 0, 1, Tn*4);
#endif
res |= f_write(&rec_file_ch2, IIR_Out, Tn*4, &bytes_writed);
if (FR_OK != res) {
break;
}
}
f_close(&rec_file_ch1);
rec_wav_file_close(&rec_file_ch2);
return res;
}
注:FileIn.wav是一个单声道音频文件,采样参数为48k/32bit。
967和969是二阶IIR高通滤波器参数,对应Fs=48kHz,Fs=300Hz。
测试函数iir_lowcut_test()对iir_2nd_filter()和iir_2nd_Assembly()的调用结果相同。
但是,我在产品程序的SWI中调用iir_2nd_Assembly()则出现异常,而调用iir_2nd_filter()没有问题。
我的问题是,线性汇编函数,在C文件中调用有什么限制吗?