Mercurial > mplayer.hg
annotate libao2/pl_resample.c @ 4363:98178c055016
preinit moved to right place
author | alex |
---|---|
date | Sat, 26 Jan 2002 19:42:21 +0000 |
parents | 585f0c77d8f5 |
children | 0a95c5074c50 |
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" | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
27 // #include "../config.h" |
3631 | 28 |
29 static ao_info_t info = | |
30 { | |
31 "Sample frequency conversion audio plugin", | |
32 "resample", | |
33 "Anders", | |
34 "" | |
35 }; | |
36 | |
37 LIBAO_PLUGIN_EXTERN(resample) | |
38 | |
39 #define min(a,b) (((a) < (b)) ? (a) : (b)) | |
40 #define max(a,b) (((a) > (b)) ? (a) : (b)) | |
41 | |
42 /* Below definition selects the length of each poly phase component. | |
43 Valid definitions are L4 and L8, where the number denotes the | |
44 length of the filter. This definition affects the computational | |
45 complexity (see play()), the performance (see filter.h) and the | |
46 memory usage. For now the filterlenght is choosen to 4 and without | |
47 assembly optimization if no SSE is present. | |
48 */ | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
49 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
50 // #ifdef HAVE_SSE |
3631 | 51 #define L8 1 // Filter bank type |
52 #define W W8 // Filter bank parameters | |
53 #define L 8 // Filter length | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
54 // #else |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
55 // #define L4 1 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
56 // #define W W4 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
57 // #define L 4 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
58 // #endif |
3631 | 59 |
60 #define CH 6 // Max number of channels | |
61 #define UP 128 /* Up sampling factor. Increasing this value will | |
62 improve frequency accuracy. Think about the L1 | |
63 cashing of filter parameters - how big can it be? */ | |
64 | |
65 #include "fir.h" | |
66 #include "filter.h" | |
67 | |
68 // local data | |
69 typedef struct pl_resample_s | |
70 { | |
71 int16_t* data; // Data buffer | |
72 int16_t* w; // Current filter weights | |
73 uint16_t dn; // Down sampling factor | |
74 uint16_t up; // Up sampling factor | |
75 int channels; // Number of channels | |
76 int len; // Lenght of buffer | |
77 int16_t ws[UP*L]; // List of all available filters | |
78 int16_t xs[CH][L*2]; // Circular buffers | |
79 } pl_resample_t; | |
80 | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
81 static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,W}; |
3631 | 82 |
83 // to set/get/query special features/parameters | |
84 static int control(int cmd,int arg){ | |
85 switch(cmd){ | |
86 case AOCONTROL_PLUGIN_SET_LEN: | |
87 if(pl_resample.data) | |
88 free(pl_resample.data); | |
89 pl_resample.len = ao_plugin_data.len; | |
90 pl_resample.data=(int16_t*)malloc(pl_resample.len); | |
91 if(!pl_resample.data) | |
92 return CONTROL_ERROR; | |
93 ao_plugin_data.len = (int)((double)ao_plugin_data.len * | |
94 ((double)pl_resample.up)/ | |
95 ((double)pl_resample.dn)); | |
96 return CONTROL_OK; | |
97 } | |
98 return -1; | |
99 } | |
100 | |
101 // open & setup audio device | |
102 // return: 1=success 0=fail | |
103 static int init(){ | |
104 int fin=ao_plugin_data.rate; | |
105 int fout=ao_plugin_cfg.pl_resample_fout; | |
106 pl_resample.w=pl_resample.ws; | |
107 pl_resample.up=UP; | |
108 | |
109 // Sheck input format | |
110 if(ao_plugin_data.format != AFMT_S16_LE){ | |
111 fprintf(stderr,"[pl_resample] Input audio format not yet suported. \n"); | |
112 return 0; | |
113 } | |
114 // Sanity check and calculate down sampling factor | |
115 if((float)max(fin,fout)/(float)min(fin,fout) > 10){ | |
116 fprintf(stderr,"[pl_resample] The difference between fin and fout is too large.\n"); | |
117 return 0; | |
118 } | |
119 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
|
120 |
3631 | 121 pl_resample.channels=ao_plugin_data.channels; |
122 if(ao_plugin_data.channels>CH){ | |
123 fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n"); | |
124 return 0; | |
125 } | |
126 | |
127 // Tell the world what we are up to | |
128 printf("[pl_resample] Up=%i, Down=%i, True fout=%f\n", | |
129 pl_resample.up,pl_resample.dn, | |
130 ((float)fin*pl_resample.up)/((float)pl_resample.dn)); | |
131 | |
132 // This plugin changes buffersize and adds some delay | |
133 ao_plugin_data.sz_mult/=((float)pl_resample.up)/((float)pl_resample.dn); | |
134 ao_plugin_data.delay_fix-= ((float)L/2) * (1/fout); | |
135 ao_plugin_data.rate=fout; | |
136 return 1; | |
137 } | |
138 | |
139 // close plugin | |
140 static void uninit(){ | |
141 if(pl_resample.data) | |
142 free(pl_resample.data); | |
143 pl_resample.data=NULL; | |
144 } | |
145 | |
146 // empty buffers | |
147 static void reset(){ | |
148 } | |
149 | |
150 // processes 'ao_plugin_data.len' bytes of 'data' | |
151 // called for every block of data | |
152 // FIXME: this routine needs to be optimized (it is probably possible to do a lot here) | |
153 static int play(){ | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
154 if(pl_resample.up==pl_resample.dn){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
155 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
|
156 register int16_t* end = in+ao_plugin_data.len/2; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
157 while(in < end) *in=(*in++)>>1; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
158 return 1; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
159 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
160 if(pl_resample.up>pl_resample.dn) |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
161 return upsample(); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
162 if(pl_resample.up<pl_resample.dn) |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
163 return downsample(); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
164 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
165 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
166 int upsample(){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
167 static uint16_t pwi = 0; // Index for w |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
168 static uint16_t pxi = 0; // Index for circular queue |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
169 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
170 uint16_t ci = pl_resample.channels; // Index for channels |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
171 uint16_t nch = pl_resample.channels; // Number of channels |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
172 uint16_t len = 0; // Number of input samples |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
173 uint16_t inc = pl_resample.up/pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
174 uint16_t level = pl_resample.up%pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
175 uint16_t up = pl_resample.up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
176 uint16_t dn = pl_resample.dn; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
177 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
178 register int16_t* w = pl_resample.w; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
179 register uint16_t wi,xi; // Temporary indexes |
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 // Index current channel |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
182 while(ci--){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
183 // Temporary pointers |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
184 register int16_t* x = pl_resample.xs[ci]; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
185 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
|
186 register int16_t* out = pl_resample.data+ci; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
187 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
|
188 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
189 wi = pwi; xi = pxi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
190 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
191 LOAD_QUE(x); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
192 while(in < end){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
193 register uint16_t i = inc; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
194 if(wi<level) i++; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
195 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
196 UPDATE_QUE(in); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
197 in+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
198 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
199 while(i--){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
200 // Run the FIR filter |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
201 FIR((&x[xi]),(&w[wi*L]),out); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
202 len++; out+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
203 // Update wi to point at the correct polyphase component |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
204 wi=(wi+dn)%up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
205 } |
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 SAVE_QUE(x); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
208 } |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
209 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
210 // 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
|
211 pwi = wi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
212 pxi = xi; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
213 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
214 // Set new data |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
215 ao_plugin_data.len=len*2; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
216 ao_plugin_data.data=pl_resample.data; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
217 return 1; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
218 } |
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 int downsample(){ |
3631 | 221 static uint16_t pwi = 0; // Index for w |
222 static uint16_t pxi = 0; // Index for circular queue | |
223 static uint16_t pi = 1; // Number of new samples to put in x queue | |
224 | |
225 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
|
226 uint16_t len = 0; // Number of input samples |
3631 | 227 uint16_t nch = pl_resample.channels; // Number of channels |
228 uint16_t inc = pl_resample.dn/pl_resample.up; | |
229 uint16_t level = pl_resample.dn%pl_resample.up; | |
230 uint16_t up = pl_resample.up; | |
231 uint16_t dn = pl_resample.dn; | |
232 | |
233 register uint16_t i,wi,xi; // Temporary indexes | |
234 | |
235 | |
236 // Index current channel | |
237 while(ci--){ | |
238 // Temporary pointers | |
239 register int16_t* x = pl_resample.xs[ci]; | |
240 register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci; | |
241 register int16_t* out = pl_resample.data+ci; | |
242 // Block loop end | |
243 register int16_t* end = in+ao_plugin_data.len/2; | |
244 i = pi; wi = pwi; xi = pxi; | |
245 | |
246 LOAD_QUE(x); | |
247 while(in < end){ | |
248 | |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
249 UPDATE_QUE(in); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
250 in+=nch; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
251 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
252 if(!--i){ |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
253 // Run the FIR filter |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
254 FIR((&x[xi]),(&pl_resample.w[wi*L]),out); |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
255 len++; out+=nch; |
3631 | 256 |
4171
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
257 // Update wi to point at the correct polyphase component |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
258 wi=(wi+dn)%up; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
259 |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
260 // Insert i number of new samples in queue |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
261 i = inc; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
262 if(wi<level) i++; |
585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
anders
parents:
4049
diff
changeset
|
263 } |
3631 | 264 } |
265 SAVE_QUE(x); | |
266 } | |
267 // Save values that needs to be kept for next time | |
268 pwi = wi; | |
269 pxi = xi; | |
270 pi = i; | |
271 // Set new data | |
272 ao_plugin_data.len=len*2; | |
273 ao_plugin_data.data=pl_resample.data; | |
274 return 1; | |
275 } |