📄 _csl_reszcalccoef.c
字号:
/** @file _csl_reszCalcCoef.c
*
* @brief File for functional layer of CSL API @a CSL_reszCalcCoef()
*
* Description
* - The @a CSL_reszCalcCoef() function definition & it's associated
* functions
*
* @date 10th May, 2005
* @author Jesse Villarreal (code borrowed from Ching-Yu).
*/
#include <csl_resz_aux.h>
#pragma CODE_SECTION (CSL_reszCalcCoef, ".text:csl_section:resz");
//#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* coefficients per direction =
8 phases x 4 taps (or 4 phases x 8 taps - only 7 are used) */
#define NUM_PHASES 8
#define NUM_TAPS 4
#define NUM_D2PH 4 /* for downsampling 2+x ~ 4x, number of phases */
#define NUM_D2TAPS 7 /* for downsampling 2+x ~ 4x, number of taps */
#define NUM_COEFS (NUM_PHASES * NUM_TAPS)
/* Note that NUM_D2PH*NUM_D2TAPS must <= NUM_COEFS */
/* filter bit depth = 10-bit = sign + 1.8 */
#define FIR_RND_ADD 128
#define FIR_RND_SHIFT 8
#define FIR_RND_SCALE 256
#define BLACKMAN_WINDOW 1
// rsz_calc_coef_sample(res, &vcoef[0]);
/** @brief Calculates the appropriate filter coefficients
*
*/
CSL_Status CSL_reszCalcCoef(
/** Resize value
*/
short rsz,
/** Array of coefficients
*/
short *coef_arr
){
int i, j;
int u, d, m, ntaps;
int nphases, w;
float win, t, c;
float interlv_coef[NUM_COEFS+1];
float deinterlv_coef[NUM_COEFS+1];
float acc;
float pi;
float scale;
int ofst_per_phase;
int max_idx, max_coef;
long acc_long;
pi = atan(1.0) * 4.0;
/* window length = W = 32 or 28 (8 phases x 4 taps or 4 phases x 7 taps)*/
/* first generate triangular window = i or (W - i), only i=1..W-1 nonzero */
/* then generate filter coefficients and multiply with window */
/* M = max(u,d),
coef(t) = sin(pi*t/M) / (pi*t/M), 3 lobes, zero at t=-2M, -M, M, 2M,
upsampling: M=u, interlv_coef[i] = coef((i-16)*u/8), i=0..32,
= sin(pi*(i-16)/8) / (pi*(i-16)/8)
downsampling 4-tap: M=d, coef sampled at u/8,
interlv_coef[i] = coef((i-16)*u/8), i=0..32,
= sin(pi*(i-16)*u/(8*d))/(pi*(i-16)*u/(8*d))
downsampling 7-tap: M=d, coef sampled at u/4,
interlv_coef[i] = coef((i-14)*u/4), i=0..28,
= sin(pi*(i-14)*u/(4*d))/(pi*(i-14)*u/(4*d))
*/
u = 256; d = rsz;
m = (u > d) ? u : d;
ntaps = (rsz > 512) ? NUM_D2TAPS : NUM_TAPS; /* < 1/2x -> 7-tap */
nphases = (rsz > 512) ? NUM_D2PH : NUM_PHASES;
ofst_per_phase = (rsz > 512) ? NUM_TAPS*2 : NUM_TAPS; /* 4 or 8, never 7 */
w = nphases * ntaps;
for (i=0; i<=w; i++) { /* note that we need one extra here */
#if BLACKMAN_WINDOW
win = 0.42 - 0.5*cos(2*pi*i/w) + 0.08*cos(4*pi*i/w);
#else
win = (i < w/2) ? i : (w-i);
#endif
t = ((float) i - w/2) * u / nphases;
interlv_coef[i] = (i == w/2) ? win : win * (sin(pi*t/m) / (pi*t/m));
}
for (j=0; j<NUM_COEFS; j++)
coef_arr[j] = 0; /* prefill 0 so that 7-tap mode gets 8th tap=0 */
/* de-interleave into phases (diagram is for 8-phase 4-tap case) */
/* phase_to_use = input_ptr % nphases, must agree in calc_coef and in resizer
(X = input points, o = possible output points, V = current output point)
X-o-o-o-o-o-o-o-X-o-o-o-o-o-o-o-X-o-o-o-o-o-o-o-X-o-o-o-o ...
inp_ptr ^ V
intlv_coef 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c ...
idx coef at inputs 8 16 24 (phase 0)
inp_ptr ^ V
intlv_coef 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c ...
idx coef at inputs 7 15 23 (phase 1)
...
inp_ptr ^ V
intlv_coef 0 c c c c c c c c c c c c c c c c c c c c c ...
idx coef at inputs 1 9 17 (phase 7)
*/
for (j=0; j<nphases; j++) /* j=phase */
for (i=0; i<ntaps; i++) /* i=tap */
deinterlv_coef[ofst_per_phase*j + i] =
interlv_coef[nphases*i + nphases - j];
/* normalize for each phase */
for (j=0; j<nphases; j++) { /* j=phase */
acc = 0.0;
for (i=0; i<ntaps; i++) /* i=tap */
acc += deinterlv_coef[ofst_per_phase*j + i];
scale = 1.0 / acc; /* normalize sum of weights to 1.0 */
for (i=0; i<ntaps; i++) /* taps */
coef_arr[ofst_per_phase*j + i] =
(short) (deinterlv_coef[ofst_per_phase*j + i] * FIR_RND_SCALE
* scale + 0.5);
}
/* sum up each phase and adjust largest coef to comprehend rounding errors
in previous pass */
for (j=0; j<nphases; j++) { /* j=phase */
acc_long = 0;
max_coef = 0;
max_idx = 0;
for (i=0; i<ntaps; i++) { /* taps */
acc_long += coef_arr[ofst_per_phase*j + i];
if (coef_arr[ofst_per_phase*j + i] > max_coef) {
max_coef = coef_arr[ofst_per_phase*j + i];
max_idx = ofst_per_phase*j + i;
}
}
acc_long = FIR_RND_SCALE - acc_long;
coef_arr[max_idx] += acc_long;
}
return (CSL_SOK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -