Mercurial > mplayer.hg
annotate libao2/pl_resample.c @ 9409:4518182fb630
2x0.5l
author | alex |
---|---|
date | Wed, 12 Feb 2003 17:19:02 +0000 |
parents | 46d21c0f36aa |
children | 12b1790038b0 |
rev | line source |
---|---|
3631 | 1 /*============================================================================= |
2 // | |
4049 | 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. | |
3631 | 5 // |
6 // Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au | |
7 // | |
8 //============================================================================= | |
9 */ | |
10 | |
11 /* This audio output plugin changes the sample rate. The output | |
12 samplerate from this plugin is specified by using the switch | |
13 `fout=F' where F is the desired output sample frequency | |
14 */ | |
15 | |
16 #define PLUGIN | |
17 | |
18 #include <stdio.h> | |
19 #include <stdlib.h> | |
20 #include <unistd.h> | |
21 #include <inttypes.h> | |
22 | |
23 #include "audio_out.h" | |
24 #include "audio_plugin.h" | |
25 #include "audio_plugin_internal.h" | |
26 #include "afmt.h" | |
27 | |
28 static ao_info_t info = | |
29 { | |
30 "Sample frequency conversion audio plugin", | |
31 "resample", | |
32 "Anders", | |
33 "" | |
34 }; | |
35 | |
36 LIBAO_PLUGIN_EXTERN(resample) | |
37 | |
38 #define min(a,b) (((a) < (b)) ? (a) : (b)) | |
39 #define max(a,b) (((a) > (b)) ? (a) : (b)) | |
40 | |
41 /* Below definition selects the length of each poly phase component. | |
4725
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
42 Valid definitions are L8 and L16, where the number denotes the |
3631 | 43 length of the filter. This definition affects the computational |
44 complexity (see play()), the performance (see filter.h) and the | |
4725
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
45 memory usage. The filterlenght is choosen to 8 if the machine is |
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
46 slow and to 16 if the machine is fast and has MMX. |
3631 | 47 */ |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
48 |
4725
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
49 #if !defined(HAVE_SSE) && !defined(HAVE_3DNOW) //This machine is slow |
4789 | 50 |
3631 | 51 #define W W8 // Filter bank parameters |
52 #define L 8 // Filter length | |
4789 | 53 #ifdef HAVE_MMX |
54 #define FIR(x,w,y) *y=(int16_t)firn(x,w,8); | |
55 #else /* HAVE_MMX */ | |
56 // Unrolled loop to speed up execution | |
57 #define FIR(x,w,y){ \ | |
58 int16_t a = (w[0]*x[0]+w[1]*x[1]+w[2]*x[2]+w[3]*x[3]) >> 16; \ | |
59 int16_t b = (w[4]*x[4]+w[5]*x[5]+w[6]*x[6]+w[7]*x[7]) >> 16; \ | |
60 y[0] = a+b; \ | |
61 } | |
62 #endif /* HAVE_MMX */ | |
63 | |
64 #else /* Fast machine */ | |
65 | |
4725
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
66 #define W W16 |
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
67 #define L 16 |
4789 | 68 #define FIR(x,w,y) *y=(int16_t)firn(x,w,16); |
69 | |
4725
534ef9323eca
MMX part rewritten and 16 tap filter added for better sound qualty
anders
parents:
4535
diff
changeset
|
70 #endif |
3631 | 71 |
72 #define CH 6 // Max number of channels | |
73 #define UP 128 /* Up sampling factor. Increasing this value will | |
74 improve frequency accuracy. Think about the L1 | |
75 cashing of filter parameters - how big can it be? */ | |
76 | |
77 #include "fir.h" | |
78 #include "filter.h" | |
79 | |
80 // local data | |
81 typedef struct pl_resample_s | |
82 { | |
83 int16_t* data; // Data buffer | |
84 int16_t* w; // Current filter weights | |
85 uint16_t dn; // Down sampling factor | |
86 uint16_t up; // Up sampling factor | |
87 int channels; // Number of channels | |
88 int len; // Lenght of buffer | |
89 int16_t ws[UP*L]; // List of all available filters | |
90 int16_t xs[CH][L*2]; // Circular buffers | |
91 } pl_resample_t; | |
92 | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
93 static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,W}; |
3631 | 94 |
95 // to set/get/query special features/parameters | |
96 static int control(int cmd,int arg){ | |
97 switch(cmd){ | |
98 case AOCONTROL_PLUGIN_SET_LEN: | |
99 if(pl_resample.data) | |
100 free(pl_resample.data); | |
101 pl_resample.len = ao_plugin_data.len; | |
102 pl_resample.data=(int16_t*)malloc(pl_resample.len); | |
103 if(!pl_resample.data) | |
104 return CONTROL_ERROR; | |
105 ao_plugin_data.len = (int)((double)ao_plugin_data.len * | |
4374
0a95c5074c50
Fixed sig 11 caused by resampling plugin, some cosmetic changes and speed improvements
anders
parents:
4171
diff
changeset
|
106 ((double)pl_resample.dn)/ |
0a95c5074c50
Fixed sig 11 caused by resampling plugin, some cosmetic changes and speed improvements
anders
parents:
4171
diff
changeset
|
107 ((double)pl_resample.up)); |
3631 | 108 return CONTROL_OK; |
109 } | |
110 return -1; | |
111 } | |
112 | |
113 // open & setup audio device | |
114 // return: 1=success 0=fail | |
115 static int init(){ | |
116 int fin=ao_plugin_data.rate; | |
117 int fout=ao_plugin_cfg.pl_resample_fout; | |
118 pl_resample.w=pl_resample.ws; | |
119 pl_resample.up=UP; | |
120 | |
121 // Sheck input format | |
8741
46d21c0f36aa
(nicer) endianness fix for every plugin except pl_format
colin
parents:
8740
diff
changeset
|
122 if(ao_plugin_data.format != AFMT_S16_NE){ |
3631 | 123 fprintf(stderr,"[pl_resample] Input audio format not yet suported. \n"); |
124 return 0; | |
125 } | |
126 // Sanity check and calculate down sampling factor | |
127 if((float)max(fin,fout)/(float)min(fin,fout) > 10){ | |
128 fprintf(stderr,"[pl_resample] The difference between fin and fout is too large.\n"); | |
129 return 0; | |
130 } | |
131 pl_resample.dn=(int)(0.5+((float)(fin*pl_resample.up))/((float)fout)); | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
132 |
3631 | 133 pl_resample.channels=ao_plugin_data.channels; |
134 if(ao_plugin_data.channels>CH){ | |
135 fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n"); | |
136 return 0; | |
137 } | |
138 | |
139 // Tell the world what we are up to | |
140 printf("[pl_resample] Up=%i, Down=%i, True fout=%f\n", | |
141 pl_resample.up,pl_resample.dn, | |
142 ((float)fin*pl_resample.up)/((float)pl_resample.dn)); | |
143 | |
144 // This plugin changes buffersize and adds some delay | |
145 ao_plugin_data.sz_mult/=((float)pl_resample.up)/((float)pl_resample.dn); | |
146 ao_plugin_data.delay_fix-= ((float)L/2) * (1/fout); | |
147 ao_plugin_data.rate=fout; | |
148 return 1; | |
149 } | |
150 | |
151 // close plugin | |
152 static void uninit(){ | |
153 if(pl_resample.data) | |
154 free(pl_resample.data); | |
155 pl_resample.data=NULL; | |
156 } | |
157 | |
158 // empty buffers | |
159 static void reset(){ | |
160 } | |
161 | |
8123
9fc45fe0d444
*HUGE* set of compiler warning fixes, unused variables removal
arpi
parents:
7472
diff
changeset
|
162 /* forward declarations */ |
9fc45fe0d444
*HUGE* set of compiler warning fixes, unused variables removal
arpi
parents:
7472
diff
changeset
|
163 int upsample(); |
9fc45fe0d444
*HUGE* set of compiler warning fixes, unused variables removal
arpi
parents:
7472
diff
changeset
|
164 int downsample(); |
9fc45fe0d444
*HUGE* set of compiler warning fixes, unused variables removal
arpi
parents:
7472
diff
changeset
|
165 |
3631 | 166 // processes 'ao_plugin_data.len' bytes of 'data' |
167 // called for every block of data | |
168 // FIXME: this routine needs to be optimized (it is probably possible to do a lot here) | |
169 static int play(){ | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
170 if(pl_resample.up==pl_resample.dn){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
171 register int16_t* in = ((int16_t*)ao_plugin_data.data); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
172 register int16_t* end = in+ao_plugin_data.len/2; |
8451 | 173 while(in < end) *(in++)>>=1; |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
174 return 1; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
175 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
176 if(pl_resample.up>pl_resample.dn) |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
177 return upsample(); |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
4789
diff
changeset
|
178 // if(pl_resample.up<pl_resample.dn) |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
179 return downsample(); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
180 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
181 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
182 int upsample(){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
183 static uint16_t pwi = 0; // Index for w |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
184 static uint16_t pxi = 0; // Index for circular queue |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
185 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
186 uint16_t ci = pl_resample.channels; // Index for channels |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
187 uint16_t nch = pl_resample.channels; // Number of channels |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
188 uint16_t len = 0; // Number of input samples |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
189 uint16_t inc = pl_resample.up/pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
190 uint16_t level = pl_resample.up%pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
191 uint16_t up = pl_resample.up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
192 uint16_t dn = pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
193 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
194 register int16_t* w = pl_resample.w; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
195 register uint16_t wi,xi; // Temporary indexes |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
196 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
197 // Index current channel |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
198 while(ci--){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
199 // Temporary pointers |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
200 register int16_t* x = pl_resample.xs[ci]; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
201 register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
202 register int16_t* out = pl_resample.data+ci; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
203 int16_t* end = in+ao_plugin_data.len/2; // Block loop end |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
204 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
205 wi = pwi; xi = pxi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
206 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
207 while(in < end){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
208 register uint16_t i = inc; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
209 if(wi<level) i++; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
210 |
4789 | 211 xi=updateq(x,in,xi,L); |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
212 in+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
213 while(i--){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
214 // Run the FIR filter |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
215 FIR((&x[xi]),(&w[wi*L]),out); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
216 len++; out+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
217 // Update wi to point at the correct polyphase component |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
218 wi=(wi+dn)%up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
219 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
220 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
221 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
222 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
223 // Save values that needs to be kept for next time |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
224 pwi = wi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
225 pxi = xi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
226 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
227 // Set new data |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
228 ao_plugin_data.len=len*2; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
229 ao_plugin_data.data=pl_resample.data; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
230 return 1; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
231 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
232 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
233 int downsample(){ |
3631 | 234 static uint16_t pwi = 0; // Index for w |
235 static uint16_t pxi = 0; // Index for circular queue | |
236 static uint16_t pi = 1; // Number of new samples to put in x queue | |
237 | |
238 uint16_t ci = pl_resample.channels; // Index for channels | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
239 uint16_t len = 0; // Number of input samples |
3631 | 240 uint16_t nch = pl_resample.channels; // Number of channels |
241 uint16_t inc = pl_resample.dn/pl_resample.up; | |
242 uint16_t level = pl_resample.dn%pl_resample.up; | |
243 uint16_t up = pl_resample.up; | |
244 uint16_t dn = pl_resample.dn; | |
245 | |
246 register uint16_t i,wi,xi; // Temporary indexes | |
247 | |
248 | |
249 // Index current channel | |
250 while(ci--){ | |
251 // Temporary pointers | |
252 register int16_t* x = pl_resample.xs[ci]; | |
253 register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci; | |
254 register int16_t* out = pl_resample.data+ci; | |
255 // Block loop end | |
256 register int16_t* end = in+ao_plugin_data.len/2; | |
257 i = pi; wi = pwi; xi = pxi; | |
258 | |
259 while(in < end){ | |
260 | |
4789 | 261 xi=updateq(x,in,xi,L); |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
262 in+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
263 if(!--i){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
264 // Run the FIR filter |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
265 FIR((&x[xi]),(&pl_resample.w[wi*L]),out); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
266 len++; out+=nch; |
3631 | 267 |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
268 // Update wi to point at the correct polyphase component |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
269 wi=(wi+dn)%up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
270 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
271 // Insert i number of new samples in queue |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
272 i = inc; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
273 if(wi<level) i++; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
274 } |
3631 | 275 } |
276 } | |
277 // Save values that needs to be kept for next time | |
278 pwi = wi; | |
279 pxi = xi; | |
280 pi = i; | |
281 // Set new data | |
282 ao_plugin_data.len=len*2; | |
283 ao_plugin_data.data=pl_resample.data; | |
284 return 1; | |
285 } |