File: rate.c

package info (click to toggle)
sox 12.16-6
  • links: PTS
  • area: main
  • in suites: potato
  • size: 1,180 kB
  • ctags: 1,466
  • sloc: ansic: 16,658; sh: 2,071; makefile: 126
file content (319 lines) | stat: -rw-r--r-- 8,197 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#ifndef USE_OLD_RATE
/*
 * August 21, 1998
 * Copyright 1998 Fabrice Bellard.
 *
 * [Rewrote completly the code of Lance Norskog And Sundry
 * Contributors with a more efficient algorithm.]
 *
 * This source code is freely redistributable and may be used for
 * any purpose.  This copyright notice must be maintained. 
 * Lance Norskog And Sundry Contributors are not responsible for 
 * the consequences of using this software.  
 */

/*
 * Sound Tools rate change effect file.
 */

#include <math.h>
#include "st.h"

/*
 * Linear Interpolation.
 *
 * The use of fractional increment allows us to use no buffer. It
 * avoid the problems at the end of the buffer we had with the old
 * method which stored a possibly big buffer of size
 * lcm(in_rate,out_rate).
 *
 * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
 * the input & output frequencies are equal, a delay of one sample is
 * introduced 
 *
 * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
 * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
 */

#define FRAC_BITS 16

/* Private data */
typedef struct ratestuff {
        u_l opos_frac;  /* fractional position of the output stream in input stream unit */
        u_l opos;

        u_l opos_inc_frac;  /* fractional position increment in the output stream */
        u_l opos_inc; 

        u_l ipos;      /* position in the input stream (integer) */

        LONG ilast; /* last sample in the input stream */
} *rate_t;

/*
 * Process options
 */
void rate_getopts(effp, n, argv) 
eff_t effp;
int n;
char **argv;
{
	if (n)
		fail("Rate effect takes no options.");
}

/*
 * Prepare processing.
 */
void rate_start(effp)
eff_t effp;
{
	rate_t rate = (rate_t) effp->priv;
        u_l incr;

        rate->opos_frac=0;
        rate->opos=0;

        /* increment */
        incr=(u_l)((double)effp->ininfo.rate / (double)effp->outinfo.rate * 
                   (double) ((unsigned long) 1 << FRAC_BITS));

        rate->opos_inc_frac = incr & (((unsigned long) 1 << FRAC_BITS)-1);
        rate->opos_inc = incr >> FRAC_BITS;
        
        rate->ipos=0;

	rate->ilast = 0;
}

/*
 * Processed signed long samples from ibuf to obuf.
 * Return number of samples processed.
 */

void rate_flow(effp, ibuf, obuf, isamp, osamp)
eff_t effp;
LONG *ibuf, *obuf;
int *isamp, *osamp;
{
	rate_t rate = (rate_t) effp->priv;
	LONG *istart,*iend;
	LONG *ostart,*oend;
	LONG ilast,icur,out;
        u_l tmp;
        double t;

        ilast=rate->ilast;

        istart = ibuf;
        iend = ibuf + *isamp;
        
        ostart = obuf;
        oend = obuf + *osamp;

        while (obuf < oend) {

                /* read as many input samples so that ipos > opos */
                
                while (rate->ipos <= rate->opos) {
                        if (ibuf >= iend) goto the_end;
                        ilast = *ibuf++;
                        rate->ipos++;
                }
                icur = *ibuf;
        
                /* interpolate */
                t=(double) rate->opos_frac / ((unsigned long) 1 << FRAC_BITS);
                out = (double) ilast * (1.0 - t) + (double) icur * t;

                /* output sample & increment position */
                
                *obuf++=(LONG) out;
                
                tmp = rate->opos_frac + rate->opos_inc_frac;
                rate->opos = rate->opos + rate->opos_inc + (tmp >> FRAC_BITS);
                rate->opos_frac = tmp & (((unsigned long) 1 << FRAC_BITS)-1);
        }
the_end:
	*isamp = ibuf - istart;
	*osamp = obuf - ostart;
	rate->ilast = ilast;
}

/*
 * Do anything required when you stop reading samples.  
 * Don't close input file! 
 */
void rate_stop(effp)
eff_t effp;
{
	/* nothing to do */
}

#else /* USE_OLD_RATE */

/*
 * July 5, 1991
 * Copyright 1991 Lance Norskog And Sundry Contributors
 * This source code is freely redistributable and may be used for
 * any purpose.  This copyright notice must be maintained. 
 * Lance Norskog And Sundry Contributors are not responsible for 
 * the consequences of using this software.
 */

/*
 * Sound Tools rate change effect file.
 */

#include <math.h>
#include "st.h"

/*
 * Least Common Multiple Linear Interpolation 
 *
 * Find least common multiple of the two sample rates.
 * Construct the signal at the LCM by interpolating successive
 * input samples as straight lines.  Pull output samples from
 * this line at output rate.
 *
 * Of course, actually calculate only the output samples.
 *
 * LCM must be 32 bits or less.  Two prime number sample rates
 * between 32768 and 65535 will yield a 32-bit LCM, so this is 
 * stretching it.
 */

/*
 * Algorithm:
 *  
 *  Generate a master sample clock from the LCM of the two rates.
 *  Interpolate linearly along it.  Count up input and output skips.
 *
 *  Input:   |inskip |       |       |       |       |
 *                                                                      
 *                                                                      
 *                                                                      
 *  LCM:     |   |   |   |   |   |   |   |   |   |   |
 *                                                                      
 *                                                                      
 *                                                                      
 *  Output:  |  outskip  |           |           | 
 *
 *                                                                      
 */


/* Private data for Lerp via LCM file */
typedef struct ratestuff {
	u_l	lcmrate;		/* least common multiple of rates */
	u_l	inskip, outskip;	/* LCM increments for I & O rates */
	u_l	total;
	u_l	intot, outtot;		/* total samples in LCM basis */
	LONG	lastsamp;		/* history */
} *rate_t;

/*
 * Process options
 */
void rate_getopts(effp, n, argv) 
eff_t effp;
int n;
char **argv;
{
	if (n)
		fail("Rate effect takes no options.");
}

/*
 * Prepare processing.
 */
void rate_start(effp)
eff_t effp;
{
	rate_t rate = (rate_t) effp->priv;
	IMPORT LONG lcm();
	
	rate->lcmrate = lcm((LONG)effp->ininfo.rate, (LONG)effp->outinfo.rate);
	/* Cursory check for LCM overflow.  
	 * If both rate are below 65k, there should be no problem.
	 * 16 bits x 16 bits = 32 bits, which we can handle.
	 */
	rate->inskip = rate->lcmrate / effp->ininfo.rate;
	rate->outskip = rate->lcmrate / effp->outinfo.rate; 
	rate->total = rate->intot = rate->outtot = 0;
	rate->lastsamp = 0;
}

/*
 * Processed signed long samples from ibuf to obuf.
 * Return number of samples processed.
 */

void rate_flow(effp, ibuf, obuf, isamp, osamp)
eff_t effp;
LONG *ibuf, *obuf;
int *isamp, *osamp;
{
	rate_t rate = (rate_t) effp->priv;
	int len, done;
	LONG *istart = ibuf;
	LONG last;

	done = 0;
	if (rate->total == 0) {
		/* Emit first sample.  We know the fence posts meet. */
		*obuf = *ibuf++;
		rate->lastsamp = *obuf++ / 65536L;
		done = 1;
		rate->total = 1;
		/* advance to second output */
		rate->outtot += rate->outskip;
		/* advance input range to span next output */
		while ((rate->intot + rate->inskip) <= rate->outtot){
			last = *ibuf++ / 65536L;
			rate->intot += rate->inskip;
		}
	} 

	/* start normal flow-through operation */
	last = rate->lastsamp;
		
	/* number of output samples the input can feed */
	len = (*isamp * rate->inskip) / rate->outskip;
	if (len > *osamp)
		len = *osamp;
	for(; done < len; done++) {
		*obuf = last;
		*obuf += ((float)((*ibuf / 65536L)  - last)* ((float)rate->outtot -
				rate->intot))/rate->inskip;
		*obuf *= 65536L;
		obuf++;
		/* advance to next output */
		rate->outtot += rate->outskip;
		/* advance input range to span next output */
		while ((rate->intot + rate->inskip) <= rate->outtot){
			last = *ibuf++ / 65536L;
			rate->intot += rate->inskip;
			if (ibuf - istart == *isamp)
				goto out;
		}
		/* long samples with high LCM's overrun counters! */
		if (rate->outtot == rate->intot)
			rate->outtot = rate->intot = 0;
	}
out:
	*isamp = ibuf - istart;
	*osamp = len;
	rate->lastsamp = last;
}

/*
 * Do anything required when you stop reading samples.  
 * Don't close input file! 
 */
void rate_stop(effp)
eff_t effp;
{
	/* nothing to do */
}
#endif /* USE_OLD_RATE */