Mercurial > mplayer.hg
annotate libao2/pl_resample.c @ 9593:e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
Syntax is we decided, so you can give the nomes or not with both
vop and vf. vf take precedence over vop.
author | albeu |
---|---|
date | Sat, 15 Mar 2003 18:01: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 } |