8607
|
1 /*=============================================================================
|
|
2 //
|
|
3 // This software has been released under the terms of the GNU Public
|
|
4 // license. See http://www.gnu.org/copyleft/gpl.html for details.
|
|
5 //
|
|
6 // Copyright 2002 Anders Johansson ajh@atri.curtin.edu.au
|
|
7 //
|
|
8 //=============================================================================
|
|
9 */
|
|
10
|
|
11 /* This file contains the resampling engine, the sample format is
|
|
12 controlled by the FORMAT parameter, the filter length by the L
|
|
13 parameter and the resampling type by UP and DN. This file should
|
|
14 only be included by af_resample.c
|
|
15 */
|
|
16
|
|
17 #undef L
|
|
18 #undef SHIFT
|
|
19 #undef FORMAT
|
|
20 #undef FIR
|
|
21 #undef ADDQUE
|
|
22
|
|
23 /* The lenght Lxx definition selects the length of each poly phase
|
|
24 component. Valid definitions are L8 and L16 where the number
|
|
25 defines the nuber of taps. This definition affects the
|
|
26 computational complexity, the performance and the memory usage.
|
|
27 */
|
|
28
|
|
29 /* The FORMAT_x parameter selects the sample format type currently
|
|
30 float and int16 are supported. Thes two formats are selected by
|
|
31 defining eiter FORMAT_F or FORMAT_I. The advantage of using float
|
|
32 is that the amplitude and therefore the SNR isn't affected by the
|
|
33 filtering, the disadvantage is that it is a lot slower.
|
|
34 */
|
|
35
|
|
36 #if defined(FORMAT_I)
|
|
37 #define SHIFT >>16
|
|
38 #define FORMAT int16_t
|
|
39 #else
|
|
40 #define SHIFT
|
|
41 #define FORMAT float
|
|
42 #endif
|
|
43
|
|
44 // Short filter
|
|
45 #if defined(L8)
|
|
46
|
|
47 #define L 8 // Filter length
|
|
48 // Unrolled loop to speed up execution
|
|
49 #define FIR(x,w,y) \
|
|
50 (y[0]) = ( w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3] \
|
|
51 + w[4]*x[4]+w[5]*x[5]+w[6]*x[6]+w[7]*x[7] ) SHIFT
|
|
52
|
|
53
|
|
54
|
|
55 #else /* L8/L16 */
|
|
56
|
|
57 #define L 16
|
|
58 // Unrolled loop to speed up execution
|
|
59 #define FIR(x,w,y) \
|
|
60 y[0] = ( w[0] *x[0] +w[1] *x[1] +w[2] *x[2] +w[3] *x[3] \
|
|
61 + w[4] *x[4] +w[5] *x[5] +w[6] *x[6] +w[7] *x[7] \
|
|
62 + w[8] *x[8] +w[9] *x[9] +w[10]*x[10]+w[11]*x[11] \
|
|
63 + w[12]*x[12]+w[13]*x[13]+w[14]*x[14]+w[15]*x[15] ) SHIFT
|
|
64
|
|
65 #endif /* L8/L16 */
|
|
66
|
|
67 // Macro to add data to circular que
|
|
68 #define ADDQUE(xi,xq,in)\
|
|
69 xq[xi]=xq[xi+L]=(*in);\
|
|
70 xi=(xi-1)&(L-1);
|
|
71
|
|
72 #if defined(UP)
|
|
73
|
|
74 uint32_t ci = l->nch; // Index for channels
|
|
75 uint32_t nch = l->nch; // Number of channels
|
|
76 uint32_t inc = s->up/s->dn;
|
|
77 uint32_t level = s->up%s->dn;
|
|
78 uint32_t up = s->up;
|
|
79 uint32_t dn = s->dn;
|
|
80 uint32_t ns = c->len/l->bps;
|
|
81 register FORMAT* w = s->w;
|
|
82
|
|
83 register uint32_t wi = 0;
|
|
84 register uint32_t xi = 0;
|
|
85
|
|
86 // Index current channel
|
|
87 while(ci--){
|
|
88 // Temporary pointers
|
|
89 register FORMAT* x = s->xq[ci];
|
|
90 register FORMAT* in = ((FORMAT*)c->audio)+ci;
|
|
91 register FORMAT* out = ((FORMAT*)l->audio)+ci;
|
|
92 FORMAT* end = in+ns; // Block loop end
|
|
93 wi = s->wi; xi = s->xi;
|
|
94
|
|
95 while(in < end){
|
|
96 register uint32_t i = inc;
|
|
97 if(wi<level) i++;
|
|
98
|
|
99 ADDQUE(xi,x,in);
|
|
100 in+=nch;
|
|
101 while(i--){
|
|
102 // Run the FIR filter
|
|
103 FIR((&x[xi]),(&w[wi*L]),out);
|
|
104 len++; out+=nch;
|
|
105 // Update wi to point at the correct polyphase component
|
|
106 wi=(wi+dn)%up;
|
|
107 }
|
|
108 }
|
|
109
|
|
110 }
|
|
111 // Save values that needs to be kept for next time
|
|
112 s->wi = wi;
|
|
113 s->xi = xi;
|
|
114 #endif /* UP */
|
|
115
|
|
116 #if defined(DN) /* DN */
|
|
117 uint32_t ci = l->nch; // Index for channels
|
|
118 uint32_t nch = l->nch; // Number of channels
|
|
119 uint32_t inc = s->dn/s->up;
|
|
120 uint32_t level = s->dn%s->up;
|
|
121 uint32_t up = s->up;
|
|
122 uint32_t dn = s->dn;
|
|
123 uint32_t ns = c->len/l->bps;
|
|
124 FORMAT* w = s->w;
|
|
125
|
|
126 register int32_t i = 0;
|
|
127 register uint32_t wi = 0;
|
|
128 register uint32_t xi = 0;
|
|
129
|
|
130 // Index current channel
|
|
131 while(ci--){
|
|
132 // Temporary pointers
|
|
133 register FORMAT* x = s->xq[ci];
|
|
134 register FORMAT* in = ((FORMAT*)c->audio)+ci;
|
|
135 register FORMAT* out = ((FORMAT*)l->audio)+ci;
|
|
136 register FORMAT* end = in+ns; // Block loop end
|
|
137 i = s->i; wi = s->wi; xi = s->xi;
|
|
138
|
|
139 while(in < end){
|
|
140
|
|
141 ADDQUE(xi,x,in);
|
|
142 in+=nch;
|
|
143 if((--i)<=0){
|
|
144 // Run the FIR filter
|
|
145 FIR((&x[xi]),(&w[wi*L]),out);
|
|
146 len++; out+=nch;
|
|
147
|
|
148 // Update wi to point at the correct polyphase component
|
|
149 wi=(wi+dn)%up;
|
|
150
|
|
151 // Insert i number of new samples in queue
|
|
152 i = inc;
|
|
153 if(wi<level) i++;
|
|
154 }
|
|
155 }
|
|
156 }
|
|
157 // Save values that needs to be kept for next time
|
|
158 s->wi = wi;
|
|
159 s->xi = xi;
|
|
160 s->i = i;
|
|
161 #endif /* DN */
|