1 /**********************************************************************
5 Real-time library interface by Dominic Mazzoni
8 http://www-ccrma.stanford.edu/~jos/resample/
10 License: LGPL - see the file LICENSE.txt for more information
12 This is the main source file, implementing all of the API
13 functions and handling all of the buffering logic.
15 **********************************************************************/
17 /* External interface */
18 #include "../include/libresample.h"
21 #include "resample_defs.h"
23 #include "filterkit.h"
40 UWORD Xp
; /* Current "now"-sample pointer for input */
41 UWORD Xread
; /* Position to put new samples */
49 void *resample_dup(const void * handle
)
51 const rsdata
*cpy
= (const rsdata
*)handle
;
52 rsdata
*hp
= (rsdata
*)malloc(sizeof(rsdata
));
54 hp
->minFactor
= cpy
->minFactor
;
55 hp
->maxFactor
= cpy
->maxFactor
;
56 hp
->Nmult
= cpy
->Nmult
;
57 hp
->LpScl
= cpy
->LpScl
;
58 hp
->Nwing
= cpy
->Nwing
;
60 hp
->Imp
= (float *)malloc(hp
->Nwing
* sizeof(float));
61 memcpy(hp
->Imp
, cpy
->Imp
, hp
->Nwing
* sizeof(float));
62 hp
->ImpD
= (float *)malloc(hp
->Nwing
* sizeof(float));
63 memcpy(hp
->ImpD
, cpy
->ImpD
, hp
->Nwing
* sizeof(float));
66 hp
->XSize
= cpy
->XSize
;
67 hp
->X
= (float *)malloc((hp
->XSize
+ hp
->Xoff
) * sizeof(float));
68 memcpy(hp
->X
, cpy
->X
, (hp
->XSize
+ hp
->Xoff
) * sizeof(float));
70 hp
->Xread
= cpy
->Xread
;
71 hp
->YSize
= cpy
->YSize
;
72 hp
->Y
= (float *)malloc(hp
->YSize
* sizeof(float));
73 memcpy(hp
->Y
, cpy
->Y
, hp
->YSize
* sizeof(float));
80 void *resample_open(int highQuality
, double minFactor
, double maxFactor
)
85 UWORD Xoff_min
, Xoff_max
;
88 /* Just exit if we get invalid factors */
89 if (minFactor
<= 0.0 || maxFactor
<= 0.0 || maxFactor
< minFactor
) {
93 "minFactor and maxFactor must be positive real numbers,\n"
94 "and maxFactor should be larger than minFactor.\n");
99 hp
= (rsdata
*)malloc(sizeof(rsdata
));
101 hp
->minFactor
= minFactor
;
102 hp
->maxFactor
= maxFactor
;
110 hp
->Nwing
= Npc
*(hp
->Nmult
-1)/2; /* # of filter coeffs in right wing */
115 Imp64
= (double *)malloc(hp
->Nwing
* sizeof(double));
117 lrsLpFilter(Imp64
, hp
->Nwing
, 0.5*Rolloff
, Beta
, Npc
);
119 hp
->Imp
= (float *)malloc(hp
->Nwing
* sizeof(float));
120 hp
->ImpD
= (float *)malloc(hp
->Nwing
* sizeof(float));
121 for(i
=0; i
<hp
->Nwing
; i
++)
122 hp
->Imp
[i
] = Imp64
[i
];
124 /* Storing deltas in ImpD makes linear interpolation
125 of the filter coefficients faster */
126 for (i
=0; i
<hp
->Nwing
-1; i
++)
127 hp
->ImpD
[i
] = hp
->Imp
[i
+1] - hp
->Imp
[i
];
129 /* Last coeff. not interpolated */
130 hp
->ImpD
[hp
->Nwing
-1] = - hp
->Imp
[hp
->Nwing
-1];
134 /* Calc reach of LP filter wing (plus some creeping room) */
135 Xoff_min
= ((hp
->Nmult
+1)/2.0) * MAX(1.0, 1.0/minFactor
) + 10;
136 Xoff_max
= ((hp
->Nmult
+1)/2.0) * MAX(1.0, 1.0/maxFactor
) + 10;
137 hp
->Xoff
= MAX(Xoff_min
, Xoff_max
);
139 /* Make the inBuffer size at least 4096, but larger if necessary
140 in order to store the minimum reach of the LP filter and then some.
141 Then allocate the buffer an extra Xoff larger so that
142 we can zero-pad up to Xoff zeros at the end when we reach the
143 end of the input samples. */
144 hp
->XSize
= MAX(2*hp
->Xoff
+10, 4096);
145 hp
->X
= (float *)malloc((hp
->XSize
+ hp
->Xoff
) * sizeof(float));
147 hp
->Xread
= hp
->Xoff
;
149 /* Need Xoff zeros at begining of X buffer */
150 for(i
=0; i
<hp
->Xoff
; i
++)
153 /* Make the outBuffer long enough to hold the entire processed
154 output of one inBuffer */
155 hp
->YSize
= (int)(((double)hp
->XSize
)*maxFactor
+2.0);
156 hp
->Y
= (float *)malloc(hp
->YSize
* sizeof(float));
159 hp
->Time
= (double)hp
->Xoff
; /* Current-time pointer for converter */
164 int resample_get_filter_width(const void *handle
)
166 const rsdata
*hp
= (const rsdata
*)handle
;
170 int resample_process(void *handle
,
175 int *inBufferUsed
, /* output param */
179 rsdata
*hp
= (rsdata
*)handle
;
180 float *Imp
= hp
->Imp
;
181 float *ImpD
= hp
->ImpD
;
182 float LpScl
= hp
->LpScl
;
183 UWORD Nwing
= hp
->Nwing
;
184 BOOL interpFilt
= FALSE
; /* TRUE means interpolate filter coeffs */
186 UWORD Nout
, Ncreep
, Nreuse
;
191 fprintf(stderr
, "resample_process: in=%d, out=%d lastFlag=%d\n",
192 inBufferLen
, outBufferLen
, lastFlag
);
195 /* Initialize inBufferUsed and outSampleCount to 0 */
199 if (factor
< hp
->minFactor
|| factor
> hp
->maxFactor
) {
202 "libresample: factor %f is not between "
203 "minFactor=%f and maxFactor=%f",
204 factor
, hp
->minFactor
, hp
->maxFactor
);
209 /* Start by copying any samples still in the Y buffer to the output
211 if (hp
->Yp
&& (outBufferLen
-outSampleCount
)>0) {
212 len
= MIN(outBufferLen
-outSampleCount
, hp
->Yp
);
214 outBuffer
[outSampleCount
+i
] = hp
->Y
[i
];
215 outSampleCount
+= len
;
216 for(i
=0; i
<hp
->Yp
-len
; i
++)
217 hp
->Y
[i
] = hp
->Y
[i
+len
];
221 /* If there are still output samples left, return now - we need
222 the full output buffer available to us... */
224 return outSampleCount
;
226 /* Account for increased filter gain when using factors less than 1 */
228 LpScl
= LpScl
*factor
;
232 /* This is the maximum number of samples we can process
233 per loop iteration */
236 printf("XSize: %d Xoff: %d Xread: %d Xp: %d lastFlag: %d\n",
237 hp
->XSize
, hp
->Xoff
, hp
->Xread
, hp
->Xp
, lastFlag
);
240 /* Copy as many samples as we can from the input buffer into X */
241 len
= hp
->XSize
- hp
->Xread
;
243 if (len
>= (inBufferLen
- (*inBufferUsed
)))
244 len
= (inBufferLen
- (*inBufferUsed
));
247 hp
->X
[hp
->Xread
+ i
] = inBuffer
[(*inBufferUsed
) + i
];
249 *inBufferUsed
+= len
;
252 if (lastFlag
&& (*inBufferUsed
== inBufferLen
)) {
253 /* If these are the last samples, zero-pad the
254 end of the input buffer and make sure we process
255 all the way to the end */
256 Nx
= hp
->Xread
- hp
->Xoff
;
257 for(i
=0; i
<hp
->Xoff
; i
++)
258 hp
->X
[hp
->Xread
+ i
] = 0;
261 Nx
= hp
->Xread
- 2 * hp
->Xoff
;
264 fprintf(stderr
, "new len=%d Nx=%d\n", len
, Nx
);
270 /* Resample stuff in input buffer */
271 if (factor
>= 1) { /* SrcUp() is faster if we can use it */
272 Nout
= lrsSrcUp(hp
->X
, hp
->Y
, factor
, &hp
->Time
, Nx
,
273 Nwing
, LpScl
, Imp
, ImpD
, interpFilt
);
276 Nout
= lrsSrcUD(hp
->X
, hp
->Y
, factor
, &hp
->Time
, Nx
,
277 Nwing
, LpScl
, Imp
, ImpD
, interpFilt
);
281 printf("Nout: %d\n", Nout
);
284 hp
->Time
-= Nx
; /* Move converter Nx samples back in time */
285 hp
->Xp
+= Nx
; /* Advance by number of samples processed */
287 /* Calc time accumulation in Time */
288 Ncreep
= (int)(hp
->Time
) - hp
->Xoff
;
290 hp
->Time
-= Ncreep
; /* Remove time accumulation */
291 hp
->Xp
+= Ncreep
; /* and add it to read pointer */
294 /* Copy part of input signal that must be re-used */
295 Nreuse
= hp
->Xread
- (hp
->Xp
- hp
->Xoff
);
297 for (i
=0; i
<Nreuse
; i
++)
298 hp
->X
[i
] = hp
->X
[i
+ (hp
->Xp
- hp
->Xoff
)];
301 printf("New Xread=%d\n", Nreuse
);
304 hp
->Xread
= Nreuse
; /* Pos in input buff to read new data into */
307 /* Check to see if output buff overflowed (shouldn't happen!) */
308 if (Nout
> hp
->YSize
) {
310 printf("Nout: %d YSize: %d\n", Nout
, hp
->YSize
);
312 fprintf(stderr
, "libresample: Output array overflow!\n");
318 /* Copy as many samples as possible to the output buffer */
319 if (hp
->Yp
&& (outBufferLen
-outSampleCount
)>0) {
320 len
= MIN(outBufferLen
-outSampleCount
, hp
->Yp
);
322 outBuffer
[outSampleCount
+i
] = hp
->Y
[i
];
323 outSampleCount
+= len
;
324 for(i
=0; i
<hp
->Yp
-len
; i
++)
325 hp
->Y
[i
] = hp
->Y
[i
+len
];
329 /* If there are still output samples left, return now,
330 since we need the full output buffer available */
335 return outSampleCount
;
338 void resample_close(void *handle
)
340 rsdata
*hp
= (rsdata
*)handle
;