summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/src/helpers
diff options
context:
space:
mode:
authorMartin Arver <martin.arver@gmail.com>2006-12-11 21:01:14 +0000
committerMartin Arver <martin.arver@gmail.com>2006-12-11 21:01:14 +0000
commit7d820556e95ce8837eaa5baf2f6b5215a4b129ce (patch)
tree686899f7652fcd3c43c321ca53d99bbdfca42847 /apps/codecs/dumb/src/helpers
parent440513ab6a51c5cc311ce8671180970279e4eaf9 (diff)
downloadrockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.tar.gz
rockbox-7d820556e95ce8837eaa5baf2f6b5215a4b129ce.zip
Remove the files
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11719 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/dumb/src/helpers')
-rw-r--r--apps/codecs/dumb/src/helpers/clickrem.c270
-rw-r--r--apps/codecs/dumb/src/helpers/memfile.c96
-rw-r--r--apps/codecs/dumb/src/helpers/resample.c1177
-rw-r--r--apps/codecs/dumb/src/helpers/sampbuf.c47
-rw-r--r--apps/codecs/dumb/src/helpers/silence.c29
-rw-r--r--apps/codecs/dumb/src/helpers/stdfile.c93
6 files changed, 0 insertions, 1712 deletions
diff --git a/apps/codecs/dumb/src/helpers/clickrem.c b/apps/codecs/dumb/src/helpers/clickrem.c
deleted file mode 100644
index ddc861d931..0000000000
--- a/apps/codecs/dumb/src/helpers/clickrem.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * clickrem.c - Click removal helpers. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <math.h>
22#include "dumb.h"
23
24
25
26typedef struct DUMB_CLICK DUMB_CLICK;
27
28
29struct DUMB_CLICK_REMOVER
30{
31 DUMB_CLICK *click;
32 int n_clicks;
33
34 int offset;
35};
36
37
38struct DUMB_CLICK
39{
40 DUMB_CLICK *next;
41 long pos;
42 sample_t step;
43};
44
45
46
47DUMB_CLICK_REMOVER *dumb_create_click_remover(void)
48{
49 DUMB_CLICK_REMOVER *cr = malloc(sizeof(*cr));
50 if (!cr) return NULL;
51
52 cr->click = NULL;
53 cr->n_clicks = 0;
54
55 cr->offset = 0;
56
57 return cr;
58}
59
60
61
62void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step)
63{
64 DUMB_CLICK *click;
65
66 ASSERT(pos >= 0);
67
68 if (!cr || !step) return;
69
70 if (pos == 0) {
71 cr->offset -= step;
72 return;
73 }
74
75 click = malloc(sizeof(*click));
76 if (!click) return;
77
78 click->pos = pos;
79 click->step = step;
80
81 click->next = cr->click;
82 cr->click = click;
83 cr->n_clicks++;
84}
85
86
87
88static DUMB_CLICK *dumb_click_mergesort(DUMB_CLICK *click, int n_clicks)
89{
90 int i;
91 DUMB_CLICK *c1, *c2, **cp;
92
93 if (n_clicks <= 1) return click;
94
95 /* Split the list into two */
96 c1 = click;
97 cp = &c1;
98 for (i = 0; i < n_clicks; i += 2) cp = &(*cp)->next;
99 c2 = *cp;
100 *cp = NULL;
101
102 /* Sort the sublists */
103 c1 = dumb_click_mergesort(c1, (n_clicks + 1) >> 1);
104 c2 = dumb_click_mergesort(c2, n_clicks >> 1);
105
106 /* Merge them */
107 cp = &click;
108 while (c1 && c2) {
109 if (c1->pos > c2->pos) {
110 *cp = c2;
111 c2 = c2->next;
112 } else {
113 *cp = c1;
114 c1 = c1->next;
115 }
116 cp = &(*cp)->next;
117 }
118 if (c2)
119 *cp = c2;
120 else
121 *cp = c1;
122
123 return click;
124}
125
126
127
128void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, float halflife)
129{
130 DUMB_CLICK *click;
131 long pos = 0;
132 int offset;
133 int factor;
134
135 if (!cr) return;
136
137 factor = (int)floor(pow(0.5, 1.0/halflife) * (1U << 31));
138
139 click = dumb_click_mergesort(cr->click, cr->n_clicks);
140 cr->click = NULL;
141 cr->n_clicks = 0;
142
143 while (click) {
144 DUMB_CLICK *next = click->next;
145 ASSERT(click->pos <= length);
146 offset = cr->offset;
147 if (offset < 0) {
148 offset = -offset;
149 while (pos < click->pos) {
150 samples[pos++] -= offset;
151 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
152 }
153 offset = -offset;
154 } else {
155 while (pos < click->pos) {
156 samples[pos++] += offset;
157 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
158 }
159 }
160 cr->offset = offset - click->step;
161 free(click);
162 click = next;
163 }
164
165 offset = cr->offset;
166 if (offset < 0) {
167 offset = -offset;
168 while (pos < length) {
169 samples[pos++] -= offset;
170 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
171 }
172 offset = -offset;
173 } else {
174 while (pos < length) {
175 samples[pos++] += offset;
176 offset = (int)((LONG_LONG)(offset << 1) * factor >> 32);
177 }
178 }
179 cr->offset = offset;
180}
181
182
183
184sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr)
185{
186 return cr ? cr->offset : 0;
187}
188
189
190
191void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr)
192{
193 if (cr) {
194 DUMB_CLICK *click = cr->click;
195 while (click) {
196 DUMB_CLICK *next = click->next;
197 free(click);
198 click = next;
199 }
200 free(cr);
201 }
202}
203
204
205
206DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n)
207{
208 int i;
209 DUMB_CLICK_REMOVER **cr;
210 if (n <= 0) return NULL;
211 cr = malloc(n * sizeof(*cr));
212 if (!cr) return NULL;
213 for (i = 0; i < n; i++) cr[i] = dumb_create_click_remover();
214 return cr;
215}
216
217
218
219void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
220{
221 if (cr) {
222 int i;
223 for (i = 0; i < n; i++)
224 dumb_record_click(cr[i], pos, step[i]);
225 }
226}
227
228
229
230void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step)
231{
232 if (cr) {
233 int i;
234 for (i = 0; i < n; i++)
235 dumb_record_click(cr[i], pos, -step[i]);
236 }
237}
238
239
240
241void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife)
242{
243 if (cr) {
244 int i;
245 for (i = 0; i < n; i++)
246 dumb_remove_clicks(cr[i], samples[i], length, halflife);
247 }
248}
249
250
251
252void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset)
253{
254 if (cr) {
255 int i;
256 for (i = 0; i < n; i++)
257 if (cr[i]) offset[i] += cr[i]->offset;
258 }
259}
260
261
262
263void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr)
264{
265 if (cr) {
266 int i;
267 for (i = 0; i < n; i++) dumb_destroy_click_remover(cr[i]);
268 free(cr);
269 }
270}
diff --git a/apps/codecs/dumb/src/helpers/memfile.c b/apps/codecs/dumb/src/helpers/memfile.c
deleted file mode 100644
index b65ab5f78d..0000000000
--- a/apps/codecs/dumb/src/helpers/memfile.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * memfile.c - Module for reading data from / / \ \
12 * memory using a DUMBFILE. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22
23#include "dumb.h"
24
25
26
27typedef struct MEMFILE MEMFILE;
28
29struct MEMFILE
30{
31 const char *ptr;
32 long left;
33};
34
35
36
37static int dumb_memfile_skip(void *f, long n)
38{
39 MEMFILE *m = f;
40 if (n > m->left) return -1;
41 m->ptr += n;
42 m->left -= n;
43 return 0;
44}
45
46
47
48static int dumb_memfile_getc(void *f)
49{
50 MEMFILE *m = f;
51 if (m->left <= 0) return -1;
52 m->left--;
53 return *(const unsigned char *)m->ptr++;
54}
55
56
57
58static long dumb_memfile_getnc(char *ptr, long n, void *f)
59{
60 MEMFILE *m = f;
61 if (n > m->left) n = m->left;
62 memcpy(ptr, m->ptr, n);
63 m->ptr += n;
64 m->left -= n;
65 return n;
66}
67
68
69
70static void dumb_memfile_close(void *f)
71{
72 free(f);
73}
74
75
76
77static DUMBFILE_SYSTEM memfile_dfs = {
78 NULL,
79 &dumb_memfile_skip,
80 &dumb_memfile_getc,
81 &dumb_memfile_getnc,
82 &dumb_memfile_close
83};
84
85
86
87DUMBFILE *dumbfile_open_memory(const char *data, long size)
88{
89 MEMFILE *m = malloc(sizeof(*m));
90 if (!m) return NULL;
91
92 m->ptr = data;
93 m->left = size;
94
95 return dumbfile_open_ex(m, &memfile_dfs);
96}
diff --git a/apps/codecs/dumb/src/helpers/resample.c b/apps/codecs/dumb/src/helpers/resample.c
deleted file mode 100644
index d8b238fc71..0000000000
--- a/apps/codecs/dumb/src/helpers/resample.c
+++ /dev/null
@@ -1,1177 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * resample.c - Resampling helper. / / \ \
12 * | < / \_
13 * By Bob and entheh. | \/ /\ /
14 * \_ / > /
15 * In order to find a good trade-off between | \ / /
16 * speed and accuracy in this code, some tests | ' /
17 * were carried out regarding the behaviour of \__/
18 * long long ints with gcc. The following code
19 * was tested:
20 *
21 * int a, b, c;
22 * c = ((long long)a * b) >> 16;
23 *
24 * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25 * the multiplication and scaling, leaving the 32-bit result in EAX.
26 *
27 * movl -8(%ebp), %eax ; read one int into EAX
28 * imull -4(%ebp) ; multiply by the other; result goes in EDX:EAX
29 * shrdl $16, %edx, %eax ; shift EAX right 16, shifting bits in from EDX
30 *
31 * Note that a 32*32->64 multiplication is performed, allowing for high
32 * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33 * so it is a minor concern when four multiplications are being performed
34 * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35 * more cycles, so this method is unsuitable for use in the low-quality
36 * resamplers.
37 *
38 * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39 * defined in dumb.h. We may investigate later what code MSVC generates, but
40 * if it seems too slow then we suggest you use a good compiler.
41 *
42 * FIXME: these comments are somewhat out of date now.
43 */
44
45#include <math.h>
46#include "dumb.h"
47
48
49
50/* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
51 * called when it should be. There will be a considerable performance hit,
52 * since at least one condition has to be tested for every sample generated.
53 */
54#ifdef HEAVYDEBUG
55#define HEAVYASSERT(cond) ASSERT(cond)
56#else
57#define HEAVYASSERT(cond)
58#endif
59
60
61
62//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
63//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
64#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
65
66
67
68/* A global variable for controlling resampling quality wherever a local
69 * specification doesn't override it. The following values are valid:
70 *
71 * 0 - DUMB_RQ_ALIASING - fastest
72 * 1 - DUMB_RQ_LINEAR
73 * 2 - DUMB_RQ_CUBIC - nicest
74 *
75 * Values outside the range 0-2 will behave the same as the nearest
76 * value within the range.
77 */
78int dumb_resampling_quality = 2;
79
80
81
82void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, long pos, long start, long end)
83{
84 resampler->src = src;
85 resampler->pos = pos;
86 resampler->subpos = 0;
87 resampler->start = start;
88 resampler->end = end;
89 resampler->dir = 1;
90 resampler->pickup = NULL;
91 resampler->pickup_data = NULL;
92 resampler->min_quality = 0;
93 resampler->max_quality = DUMB_RQ_N_LEVELS - 1;
94 resampler->x[2] = resampler->x[1] = resampler->x[0] = 0;
95 resampler->overshot = -1;
96}
97
98
99
100DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, long pos, long start, long end)
101{
102 DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
103 if (!resampler) return NULL;
104 dumb_reset_resampler(resampler, src, pos, start, end);
105 return resampler;
106}
107
108
109
110/* For convenience, returns nonzero on stop. */
111static int process_pickup(DUMB_RESAMPLER *resampler)
112{
113 if (resampler->overshot < 0) {
114 resampler->overshot = 0;
115 dumb_resample(resampler, NULL, 2, 0, 1.0f);
116 resampler->x[0] = resampler->x[1];
117 }
118
119 for (;;) {
120 if (resampler->dir < 0) {
121 if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) resampler->x[0] = resampler->src[resampler->pos+3];
122 if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) resampler->x[1] = resampler->src[resampler->pos+2];
123 if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) resampler->x[2] = resampler->src[resampler->pos+1];
124 resampler->overshot = resampler->start - resampler->pos - 1;
125 } else {
126 if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) resampler->x[0] = resampler->src[resampler->pos-3];
127 if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) resampler->x[1] = resampler->src[resampler->pos-2];
128 if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) resampler->x[2] = resampler->src[resampler->pos-1];
129 resampler->overshot = resampler->pos - resampler->end;
130 }
131
132 if (resampler->overshot < 0) {
133 resampler->overshot = 0;
134 return 0;
135 }
136
137 if (!resampler->pickup) {
138 resampler->dir = 0;
139 return 1;
140 }
141 (*resampler->pickup)(resampler, resampler->pickup_data);
142 if (resampler->dir == 0) return 1;
143 ASSERT(resampler->dir == -1 || resampler->dir == 1);
144 }
145}
146
147
148
149/* Executes the content 'iterator' times.
150 * Clobbers the 'iterator' variable.
151 * The loop is unrolled by four.
152 */
153#define LOOP4(iterator, CONTENT) \
154{ \
155 if ((iterator) & 2) { \
156 CONTENT; \
157 CONTENT; \
158 } \
159 if ((iterator) & 1) { \
160 CONTENT; \
161 } \
162 (iterator) >>= 2; \
163 while (iterator) { \
164 CONTENT; \
165 CONTENT; \
166 CONTENT; \
167 CONTENT; \
168 (iterator)--; \
169 } \
170}
171
172
173
174long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta)
175{
176 int dt;
177 int vol;
178 long done;
179 long todo;
180 int quality;
181
182 if (!resampler || resampler->dir == 0) return 0;
183 ASSERT(resampler->dir == -1 || resampler->dir == 1);
184
185 done = 0;
186 dt = (int)(delta * 65536.0 + 0.5);
187 vol = (int)floor(volume * 65536.0 + 0.5);
188
189 if (vol == 0) dst = NULL;
190
191 quality = dumb_resampling_quality;
192 if (quality > resampler->max_quality) quality = resampler->max_quality;
193 else if (quality < resampler->min_quality) quality = resampler->min_quality;
194
195 while (done < dst_size) {
196 if (process_pickup(resampler)) return done;
197
198 if ((resampler->dir ^ dt) < 0)
199 dt = -dt;
200
201 if (resampler->dir < 0)
202 todo = (long)((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
203 else
204 todo = (long)((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
205
206 if (todo < 0)
207 todo = 0;
208 else if (todo > dst_size - done)
209 todo = dst_size - done;
210
211 done += todo;
212
213 {
214 sample_t *src = resampler->src;
215 long pos = resampler->pos;
216 int subpos = resampler->subpos;
217 long diff = pos;
218 long overshot;
219 if (resampler->dir < 0) {
220 if (!dst) {
221 /* Silence or simulation */
222 LONG_LONG new_subpos = subpos + dt * todo;
223 pos += (long)(new_subpos >> 16);
224 subpos = (long)new_subpos & 65535;
225 } else if (quality <= DUMB_RQ_ALIASING) {
226 /* Aliasing, backwards */
227 sample_t xbuf[2];
228 sample_t *x = &xbuf[0];
229 sample_t *xstart;
230 xbuf[0] = resampler->x[1];
231 xbuf[1] = resampler->x[2];
232 while (todo && x < &xbuf[2]) {
233 HEAVYASSERT(pos >= resampler->start);
234 *dst++ += MULSC(x[0], vol);
235 subpos += dt;
236 pos += subpos >> 16;
237 x -= subpos >> 16;
238 subpos &= 65535;
239 todo--;
240 }
241 x = xstart = &src[pos];
242 LOOP4(todo,
243 *dst++ += MULSC(x[2], vol);
244 subpos += dt;
245 x += subpos >> 16;
246 subpos &= 65535;
247 );
248 pos += x - xstart;
249 } else if (quality <= DUMB_RQ_LINEAR) {
250 /* Linear interpolation, backwards */
251 sample_t xbuf[3];
252 sample_t *x = &xbuf[1];
253 xbuf[0] = resampler->x[1];
254 xbuf[1] = resampler->x[2];
255 xbuf[2] = src[pos];
256 while (todo && x < &xbuf[3]) {
257 HEAVYASSERT(pos >= resampler->start);
258 *dst++ += MULSC(x[0] + MULSC(x[-1] - x[0], subpos), vol);
259 subpos += dt;
260 pos += subpos >> 16;
261 x -= subpos >> 16;
262 subpos &= 65535;
263 todo--;
264 }
265 x = &src[pos];
266 LOOP4(todo,
267 HEAVYASSERT(pos >= resampler->start);
268 *dst++ += MULSC(x[1] + MULSC(x[2] - x[1], subpos), vol);
269 subpos += dt;
270 pos += subpos >> 16;
271 x += subpos >> 16;
272 subpos &= 65535;
273 );
274 } else {
275 /* Cubic interpolation, backwards */
276 sample_t xbuf[6];
277 sample_t *x = &xbuf[3];
278 sample_t *lastx = NULL;
279 int a = 0, b = 0, c = 0;
280 xbuf[0] = resampler->x[0];
281 xbuf[1] = resampler->x[1];
282 xbuf[2] = resampler->x[2];
283 xbuf[3] = src[pos];
284 if (pos-1 >= resampler->start) xbuf[4] = src[pos-1];
285 if (pos-2 >= resampler->start) xbuf[5] = src[pos-2];
286 while (todo && x < &xbuf[6]) {
287 HEAVYASSERT(pos >= resampler->start);
288 if (lastx != x) {
289 lastx = x;
290 a = (((x[-1] - x[-2]) << 1) + (x[-1] - x[-2]) + (x[-3] - x[0])) >> 1;
291 b = (x[-2] << 1) + x[0] - ((5 * x[-1] + x[-3]) >> 1);
292 c = (x[-2] - x[0]) >> 1;
293 }
294 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-1], vol);
295 subpos += dt;
296 pos += subpos >> 16;
297 x -= subpos >> 16;
298 subpos &= 65535;
299 todo--;
300 }
301 x = &src[pos];
302 lastx = NULL;
303 LOOP4(todo,
304 HEAVYASSERT(pos >= resampler->start);
305 if (lastx != x) {
306 lastx = x;
307 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
308 b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
309 c = (x[2] - x[0]) >> 1;
310 }
311 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol);
312 subpos += dt;
313 pos += subpos >> 16;
314 x += subpos >> 16;
315 subpos &= 65535;
316 );
317 }
318 diff = diff - pos;
319 overshot = resampler->start - pos - 1;
320 if (diff >= 3) {
321 resampler->x[0] = overshot >= 3 ? 0 : src[pos+3];
322 resampler->x[1] = overshot >= 2 ? 0 : src[pos+2];
323 resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
324 } else if (diff >= 2) {
325 resampler->x[0] = resampler->x[2];
326 resampler->x[1] = overshot >= 2 ? 0 : src[pos+2];
327 resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
328 } else if (diff >= 1) {
329 resampler->x[0] = resampler->x[1];
330 resampler->x[1] = resampler->x[2];
331 resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
332 }
333 } else {
334 if (!dst) {
335 /* Silence or simulation */
336 LONG_LONG new_subpos = subpos + dt * todo;
337 pos += (long)(new_subpos >> 16);
338 subpos = (long)new_subpos & 65535;
339 } else if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
340 /* Aliasing, forwards */
341 sample_t xbuf[2];
342 sample_t *x = &xbuf[0];
343 sample_t *xstart;
344 xbuf[0] = resampler->x[1];
345 xbuf[1] = resampler->x[2];
346 while (todo && x < &xbuf[2]) {
347 HEAVYASSERT(pos < resampler->end);
348 *dst++ += MULSC(x[0], vol);
349 subpos += dt;
350 pos += subpos >> 16;
351 x += subpos >> 16;
352 subpos &= 65535;
353 todo--;
354 }
355 x = xstart = &src[pos];
356 LOOP4(todo,
357 *dst++ += MULSC(x[-2], vol);
358 subpos += dt;
359 x += subpos >> 16;
360 subpos &= 65535;
361 );
362 pos += x - xstart;
363 } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
364 /* Linear interpolation, forwards */
365 sample_t xbuf[3];
366 sample_t *x = &xbuf[1];
367 xbuf[0] = resampler->x[1];
368 xbuf[1] = resampler->x[2];
369 xbuf[2] = src[pos];
370 while (todo && x < &xbuf[3]) {
371 HEAVYASSERT(pos < resampler->end);
372 *dst++ += MULSC(x[-1] + MULSC(x[0] - x[-1], subpos), vol);
373 subpos += dt;
374 pos += subpos >> 16;
375 x += subpos >> 16;
376 subpos &= 65535;
377 todo--;
378 }
379 x = &src[pos];
380 LOOP4(todo,
381 HEAVYASSERT(pos < resampler->end);
382 *dst++ += MULSC(x[-2] + MULSC(x[-1] - x[-2], subpos), vol);
383 subpos += dt;
384 pos += subpos >> 16;
385 x += subpos >> 16;
386 subpos &= 65535;
387 );
388 } else {
389 /* Cubic interpolation, forwards */
390 sample_t xbuf[6];
391 sample_t *x = &xbuf[3];
392 sample_t *lastx = NULL;
393 int a = 0, b = 0, c = 0;
394 xbuf[0] = resampler->x[0];
395 xbuf[1] = resampler->x[1];
396 xbuf[2] = resampler->x[2];
397 xbuf[3] = src[pos];
398 if (pos+1 < resampler->end) xbuf[4] = src[pos+1];
399 if (pos+2 < resampler->end) xbuf[5] = src[pos+2];
400 while (todo && x < &xbuf[6]) {
401 HEAVYASSERT(pos < resampler->end);
402 if (lastx != x) {
403 lastx = x;
404 a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1;
405 b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1);
406 c = (x[-1] - x[-3]) >> 1;
407 }
408 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol);
409 subpos += dt;
410 pos += subpos >> 16;
411 x += subpos >> 16;
412 subpos &= 65535;
413 todo--;
414 }
415 x = &src[pos];
416 lastx = NULL;
417 LOOP4(todo,
418 HEAVYASSERT(pos < resampler->end);
419 if (lastx != x) {
420 lastx = x;
421 a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1;
422 b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1);
423 c = (x[-1] - x[-3]) >> 1;
424 }
425 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol);
426 subpos += dt;
427 pos += subpos >> 16;
428 x += subpos >> 16;
429 subpos &= 65535;
430 );
431 }
432 diff = pos - diff;
433 overshot = pos - resampler->end;
434 if (diff >= 3) {
435 resampler->x[0] = overshot >= 3 ? 0 : src[pos-3];
436 resampler->x[1] = overshot >= 2 ? 0 : src[pos-2];
437 resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
438 } else if (diff >= 2) {
439 resampler->x[0] = resampler->x[2];
440 resampler->x[1] = overshot >= 2 ? 0 : src[pos-2];
441 resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
442 } else if (diff >= 1) {
443 resampler->x[0] = resampler->x[1];
444 resampler->x[1] = resampler->x[2];
445 resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
446 }
447 }
448 resampler->pos = pos;
449 resampler->subpos = subpos;
450 }
451 }
452
453 return done;
454}
455
456
457
458sample_t dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, float volume)
459{
460 int vol;
461 sample_t *src;
462 long pos;
463 int subpos;
464 int quality;
465
466 if (!resampler || resampler->dir == 0) return 0;
467 ASSERT(resampler->dir == -1 || resampler->dir == 1);
468
469 if (process_pickup(resampler)) return 0;
470
471 vol = (int)floor(volume * 65536.0 + 0.5);
472 if (vol == 0) return 0;
473
474 quality = dumb_resampling_quality;
475 if (quality > resampler->max_quality) quality = resampler->max_quality;
476 else if (quality < resampler->min_quality) quality = resampler->min_quality;
477
478 src = resampler->src;
479 pos = resampler->pos;
480 subpos = resampler->subpos;
481
482 if (resampler->dir < 0) {
483 HEAVYASSERT(pos >= resampler->start);
484 if (dumb_resampling_quality <= 0) {
485 /* Aliasing, backwards */
486 return MULSC(src[pos], vol);
487 } else if (quality <= DUMB_RQ_LINEAR) {
488 /* Linear interpolation, backwards */
489 return MULSC(resampler->x[2] + MULSC(resampler->x[1] - resampler->x[2], subpos), vol);
490 } else {
491 /* Cubic interpolation, backwards */
492 sample_t *x = resampler->x;
493 int a, b, c;
494 a = (((x[2] - x[1]) << 1) + (x[2] - x[1]) + (x[0] - src[pos])) >> 1;
495 b = (x[1] << 1) + src[pos] - ((5 * x[2] + x[0]) >> 1);
496 c = (x[1] - src[pos]) >> 1;
497 return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[2], vol);
498 }
499 } else {
500 HEAVYASSERT(pos < resampler->end);
501 if (dumb_resampling_quality <= 0) {
502 /* Aliasing */
503 return MULSC(src[pos], vol);
504 } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
505 /* Linear interpolation, forwards */
506 return MULSC(resampler->x[1] + MULSC(resampler->x[2] - resampler->x[1], subpos), vol);
507 } else {
508 /* Cubic interpolation, forwards */
509 sample_t *x = resampler->x;
510 int a, b, c;
511 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (src[pos] - x[0])) >> 1;
512 b = (x[2] << 1) + x[0] - ((5 * x[1] + src[pos]) >> 1);
513 c = (x[2] - x[0]) >> 1;
514 return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol);
515 }
516 }
517}
518
519
520
521void dumb_end_resampler(DUMB_RESAMPLER *resampler)
522{
523 if (resampler)
524 free(resampler);
525}
526
527
528
529#if 0
530/* The following macro is used to overcome the fact that most C
531 * compilers (including gcc and MSVC) can't correctly multiply signed
532 * integers outside the range -32768 to 32767. i86 assembler versions
533 * don't need to use this method, since the processor does in fact
534 * have instructions to multiply large numbers correctly - which
535 * means using assembly language could make a significant difference
536 * to the speed.
537 *
538 * The basic method is as follows. We halve the subposition (how far
539 * we are between samples), so it never exceeds 32767. We also halve
540 * the delta, which is the amount to be added to the subposition each
541 * time. Then we unroll the loop twofold, so that we can add the lost
542 * one every other time if necessary (since the halving may have
543 * resulted in rounding down).
544 *
545 * This method doesn't incur any cumulative inaccuracies. There is a
546 * very slight loss of quality, which I challenge anyone to notice -
547 * but the position will advance at *exactly* the same rate as it
548 * would if we didn't use this method. This also means the pitch is
549 * exactly the same, which may even make a difference to trained
550 * musicians when resampling down a lot :)
551 *
552 * Each time this macro is invoked, DO_RESAMPLE(inc) must be defined
553 * to calculate the samples by the appropriate equation (linear,
554 * cubic, etc.). See the individual cases for examples of how this is
555 * done.
556 */
557#define MAKE_RESAMPLER() \
558{ \
559 if (dt & 1) { \
560 long todo2; \
561 \
562 dt >>= 1; \
563 \
564 if (src_subpos & 1) { \
565 src_subpos >>= 1; \
566 DO_RESAMPLE(1); \
567 todo--; \
568 } else \
569 src_subpos >>= 1; \
570 \
571 todo2 = todo >> 1; \
572 \
573 while (todo2) { \
574 DO_RESAMPLE(0); \
575 DO_RESAMPLE(1); \
576 todo2--; \
577 } \
578 \
579 if (todo & 1) { \
580 DO_RESAMPLE(0); \
581 src_subpos = (src_subpos << 1) | 1; \
582 } else \
583 src_subpos <<= 1; \
584 \
585 todo = 0; \
586 dt = (dt << 1) | 1; \
587 } else { \
588 long subposbit = src_subpos & 1; \
589 dt >>= 1; \
590 src_subpos >>= 1; \
591 \
592 if (todo & 1) { \
593 DO_RESAMPLE(0); \
594 } \
595 \
596 todo >>= 1; \
597 \
598 while (todo) { \
599 DO_RESAMPLE(0); \
600 DO_RESAMPLE(0); \
601 todo--; \
602 } \
603 \
604 src_subpos = (src_subpos << 1) | subposbit; \
605 dt <<= 1; \
606 } \
607}
608
609
610
611sample_t dumb_resample_get_current_sample(
612 sample_t *src, long *_src_pos, int *_src_subpos,
613 long src_start, long src_end,
614 float volume, int *_dir,
615 DUMB_RESAMPLE_PICKUP pickup, void *pickup_data
616)
617{
618 long src_pos = *_src_pos;
619 int src_subpos = *_src_subpos;
620 int dir = _dir ? *_dir : 1;
621
622 sample_t value = 0;
623
624 if (dir == 0)
625 return 0;
626
627 ASSERT(dir == 1 || dir == -1);
628
629 if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) {
630
631 /* If there's no pick-up function, we stop. */
632 if (!pickup) {
633 dir = 0;
634 goto end;
635 }
636
637 /* Process the pick-up. It may need invoking more than once. */
638 do {
639 dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
640
641 if (dir == 0)
642 goto end;
643
644 ASSERT(dir == 1 || dir == -1);
645 } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end));
646 }
647
648 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end));
649
650 if (dumb_resampling_quality == 0) {
651 /* Aliasing (coarse) */
652 int volume_fact = (int)(volume * 16384.0);
653 value = (src[src_pos] * volume_fact) >> 14;
654 } else if (dumb_resampling_quality <= 2) {
655 /* Linear interpolation */
656 int volume_fact = (int)(volume * 16384.0);
657 int subpos = src_subpos >> 1;
658 value = ((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * subpos) >> 14)) * volume_fact) >> 14;
659 } else if (dumb_resampling_quality == 3) {
660 /* Quadratic interpolation */
661 int volume_fact = (int)(volume * 16384.0);
662 int a, b;
663 sample_t *x;
664 int subpos = src_subpos >> 1;
665 x = &src[src_pos];
666 a = ((x[0] + x[2]) >> 1) - x[1];
667 b = ((x[2] - x[0]) >> 1) - (a << 1);
668 value = (((((((a * subpos) >> 15) + b) * subpos) >> 15) + x[0]) * volume_fact) >> 14;
669 } else {
670 /* Cubic interpolation */
671 int volume_fact = (int)(volume * 16384.0);
672 int a, b, c;
673 sample_t *x;
674 int subpos = src_subpos >> 1;
675 x = &src[src_pos];
676 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
677 b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
678 c = (x[2] - x[0]) >> 1;
679 value = (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * subpos) >> 15) + b) * subpos) >> 15) + c) * subpos) >> 15) + x[1]) * volume_fact) >> 14;
680 }
681
682 end:
683
684 *_src_pos = src_pos;
685 *_src_subpos = src_subpos;
686 if (_dir) *_dir = dir;
687
688 return value;
689}
690
691
692
693long dumb_resample(
694 sample_t *src, long *_src_pos, int *_src_subpos,
695 long src_start, long src_end,
696 sample_t *dst, long dst_size,
697 float volume, float delta, int *_dir,
698 DUMB_RESAMPLE_PICKUP pickup, void *pickup_data
699)
700{
701 int dt = (int)(delta * 65536.0 + 0.5);
702 long s = 0; /* Current position in the destination buffer */
703
704 long src_pos = *_src_pos;
705 int src_subpos = *_src_subpos;
706 int dir = _dir ? *_dir : 1;
707
708 int linear_average;
709
710 if (dir == 0)
711 return 0;
712
713 ASSERT(dir == 1 || dir == -1);
714
715 linear_average = dst && dumb_resampling_quality >= 2 && dt > 65536;
716
717 if (dir < 0) dt = -dt;
718
719 if (linear_average)
720 volume /= delta;
721
722 while (s < dst_size) {
723
724 long todo;
725
726 /* Process pick-ups first, just in case. */
727
728 if (linear_average) {
729
730 /* For linear average, the pick-up point could split a sum into
731 * two parts. We handle this by putting the pick-up code inside
732 * the summing loop. Note that this code is only executed when we
733 * know that a pick-up is necessary somewhere during this sum
734 * (although it is always executed once for the first sample).
735 * We use a separate loop further down when we know we won't have
736 * to do a pick-up, so the condition does not need testing inside
737 * the loop.
738 */
739
740 float sum;
741 long i;
742 int advance;
743 int x[3];
744
745 advance = src_subpos + dt;
746
747 /* Make these negative. Then they stay within the necessary
748 * range for integer multiplication, -32768 to 32767 ;)
749 */
750 x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */
751 x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */
752
753 sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15));
754
755 i = src_pos + (advance >> 16);
756 src_pos += dir;
757 src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */
758
759 advance &= 65535;
760
761 /* i is the index of the first sample NOT to sum fully,
762 * regardless of the direction of resampling.
763 */
764
765 while (dir < 0 ? (i < src_start) : (i >= src_end)) {
766 if (dir < 0) {
767 while (src_pos >= src_start)
768 sum += src[src_pos--];
769 } else {
770 while (src_pos < src_end)
771 sum += src[src_pos++];
772 }
773
774 i -= src_pos;
775 /* i is now the number of samples left to sum fully, except
776 * it's negative if we're going backwards.
777 */
778
779 if (!pickup) {
780 dir = 0;
781 goto endsum;
782 }
783
784 dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
785
786 if (dir == 0)
787 goto endsum;
788
789 ASSERT(dir == 1 || dir == -1);
790
791 if ((dir ^ dt) < 0) {
792 dt = -dt;
793 advance ^= 65535;
794 i = -i;
795 }
796
797 i += src_pos;
798 /* There, i is back to normal. */
799 }
800
801 for (; src_pos != i; src_pos += dir)
802 sum += src[src_pos];
803
804 src_subpos = advance;
805
806 x[2] = src_subpos >> 1;
807 x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */
808
809 sum += (src[src_pos] * (x+1)[dir]) >> 15;
810
811 endsum:
812
813 sum *= volume;
814 dst[s] += (int)sum;
815
816 s++;
817
818 if (dir == 0)
819 break;
820
821 } else if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) {
822
823 /* If there's no pick-up function, we stop. */
824 if (!pickup) {
825 dir = 0;
826 break;
827 }
828
829 /* Process the pick-up. It may need invoking more than once. */
830 do {
831 dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
832
833 if (dir == 0)
834 goto end;
835
836 ASSERT(dir == 1 || dir == -1);
837 } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end));
838
839 /* Update sign of dt to match that of dir. */
840 if ((dir ^ dt) < 0)
841 dt = -dt;
842 }
843
844 /* Work out how many contiguous samples we can now render. */
845 if (dir < 0)
846 todo = (long)((((LONG_LONG)(src_pos - src_start) << 16) + src_subpos) / -dt);
847 else
848 todo = (long)((((LONG_LONG)(src_end - src_pos) << 16) - src_subpos - 1) / dt);
849
850 /* The above equations work out how many complete dt-sized
851 * intervals there are between the current position and the loop
852 * point (provided there is a little fractional extra). The linear
853 * average function needs complete intervals - but the other
854 * resamplers only read a sample from the beginning of each interval,
855 * so they can process one extra sample in their main loops (so we
856 * increment todo in a moment).
857 *
858 * The linear average function makes up the extra sample using the
859 * specialised pick-up code above.
860 *
861 * Note that our above pick-up process should have absolutely ensured
862 * that the result of this function will be nonnegative.
863 */
864
865 ASSERT(todo >= 0);
866
867 if (!linear_average)
868 todo++;
869
870 /* Of course we don't want to overrun the output buffer! */
871 if (todo > dst_size - s)
872 todo = dst_size - s;
873
874 if (!dst) {
875
876 LONG_LONG t = src_subpos + (LONG_LONG)dt * todo;
877 src_pos += (long)(t >> 16);
878 src_subpos = (int)t & 0xFFFFl;
879
880 s += todo;
881
882 } else if (linear_average) {
883
884 float sum;
885 long i;
886 int advance;
887 int x[3];
888
889 while (todo) {
890
891 advance = src_subpos + dt;
892
893 /* Make these negative. Then they stay within the necessary
894 * range for integer multiplication, -32768 to 32767 ;)
895 */
896 x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */
897 x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */
898
899 sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15));
900
901 i = src_pos + (advance >> 16);
902 src_pos += dir;
903 src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */
904
905 advance &= 65535;
906
907 /* i is the index of the first sample NOT to sum fully,
908 * regardless of the direction of resampling.
909 */
910
911 HEAVYASSERT(dir < 0 ? (i >= src_start) : (i < src_end));
912
913 for (; src_pos != i; src_pos += dir)
914 sum += src[src_pos];
915
916 src_subpos = advance;
917
918 x[2] = src_subpos >> 1;
919 x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */
920
921 sum += (src[src_pos] * (x+1)[dir]) >> 15;
922
923 sum *= volume;
924 dst[s] += (int)sum;
925
926 s++;
927 todo--;
928 }
929
930 } else if (dumb_resampling_quality == 0 || (dumb_resampling_quality == 1 && delta >= 1.0)) {
931
932 /* Aliasing (coarse) */
933 int volume_fact = (int)(volume * 16384.0);
934
935 do {
936 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end));
937 dst[s] += ((src[src_pos] * volume_fact) >> 14);
938 src_subpos += dt;
939 src_pos += src_subpos >> 16;
940 src_subpos &= 0xFFFFl;
941 s++;
942 } while (--todo);
943
944 } else if (dumb_resampling_quality <= 2) {
945
946 /* Linear interpolation */
947 int volume_fact = (int)(volume * 16384.0);
948
949 #define DO_RESAMPLE(inc) \
950 { \
951 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
952 \
953 dst[s] += (((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * src_subpos) >> 14)) * volume_fact) >> 14); \
954 \
955 src_subpos += dt + inc; \
956 src_pos += src_subpos >> 15; \
957 src_subpos &= 0x7FFFl; \
958 s++; \
959 }
960
961 MAKE_RESAMPLER();
962
963 #undef DO_RESAMPLE
964
965 } else if (dumb_resampling_quality == 3) {
966
967 /* Quadratic interpolation */
968
969 int volume_fact = (int)(volume * 16384.0);
970 int a = 0, b = 0;
971 sample_t *x = NULL;
972 int last_src_pos = -1;
973
974 /* AIM: no integer multiplicands must transcend the range -32768 to 32767.
975 * This limitation is imposed by most compilers, including gcc and MSVC.
976 *
977 * a = 0.5 * (s0 + s2) - s1
978 * b = -1.5 * s0 + 2 * s1 - 0.5 * s2
979 * c = s0
980 *
981 * s = (a * t + b) * t + c
982 *
983 * In fixed-point:
984 *
985 * a = ((s0 + s2) >> 1) - s1
986 * b = ((-3 * s0 - s2) >> 1) + (s1 << 1)
987 *
988 * s = (((((a * t) >> 16) + b) * t) >> 16) + s0
989 *
990 * With t halved (since t can reach 65535):
991 *
992 * s = (((((a * t) >> 15) + b) * t) >> 15) + s0
993 *
994 * a currently reaches 65536
995 * b currently reaches 131072
996 *
997 * So we must use aon2
998 *
999 * s = (((((aon2 * t) >> 14) + b) * t) >> 15) + s0
1000 *
1001 * ((aon2 * t) >> 14) + b is 5 times too big
1002 * so we must divide by 8
1003 *
1004 * s = (((((aon2 * t) >> 17) + bon8) * t) >> 12) + s0
1005 *
1006 * aon2 = ((s0 + s2) >> 2) - (s1 >> 1)
1007 * bon8 = ((-3 * s0 - s2) >> 4) + (s1 >> 2)
1008 * or:
1009 * bon8 = ((s2 - s0) >> 4) - (aon2 >> 1)
1010 */
1011
1012 /* Unh4x0r3d version:
1013 #define DO_RESAMPLE(inc) \
1014 { \
1015 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
1016 \
1017 if (src_pos != last_src_pos) { \
1018 last_src_pos = src_pos; \
1019 x = &src[src_pos]; \
1020 a = ((x[0] + x[2]) >> 2) - (x[1] >> 1); \
1021 b = ((x[2] - x[0]) >> 4) - (a >> 1); \
1022 } \
1023 \
1024 dst[s] += ((((((((a * src_subpos) >> 17) + b) * src_subpos) >> 12) + x[0]) * volume_fact) >> 14); \
1025 \
1026 src_subpos += dt + inc; \
1027 src_pos += src_subpos >> 15; \
1028 src_subpos &= 0x7FFFl; \
1029 s++; \
1030 }
1031 */
1032
1033 /* H4x0r3d version: */
1034 #define DO_RESAMPLE(inc) \
1035 { \
1036 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
1037 \
1038 if (src_pos != last_src_pos) { \
1039 last_src_pos = src_pos; \
1040 x = &src[src_pos]; \
1041 a = ((x[0] + x[2]) >> 1) - x[1]; \
1042 b = ((x[2] - x[0]) >> 1) - (a << 1); \
1043 } \
1044 \
1045 dst[s] += ((((((((a * src_subpos) >> 15) + b) * src_subpos) >> 15) + x[0]) * volume_fact) >> 14); \
1046 \
1047 src_subpos += dt + inc; \
1048 src_pos += src_subpos >> 15; \
1049 src_subpos &= 0x7FFFl; \
1050 s++; \
1051 }
1052
1053 MAKE_RESAMPLER();
1054
1055 #undef DO_RESAMPLE
1056
1057 } else {
1058
1059 /* Cubic interpolation */
1060
1061 int volume_fact = (int)(volume * 16384.0);
1062 int a = 0, b = 0, c = 0;
1063 sample_t *x = NULL;
1064 int last_src_pos = -1;
1065
1066 /* AIM: never multiply integers outside the range -32768 to 32767.
1067 *
1068 * a = 1.5f * (x[1] - x[2]) + (x[3] - x[0]) * 0.5f;
1069 * b = 2.0f * x[2] + x[0] - 2.5f * x[1] - x[3] * 0.5f;
1070 * c = (x[2] - x[0]) * 0.5f;
1071 *
1072 * s = ((a * t + b) * t + c) * t + x[1];
1073 *
1074 * Fixed-point version:
1075 *
1076 * a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
1077 * b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
1078 * c = (x[2] - x[0]) >> 1;
1079 *
1080 * s = ((((((((a * t) >> 15) + b) * t) >> 15) + c) * t) >> 15) + x[1];
1081 * (with t already halved, maximum 32767)
1082 *
1083 * a is in (((1+1)*2)+(1+1)+(1+1))/2 = 8 times the required range
1084 * b is in (1*2)+1+((5*1+1)/2) = 6 times
1085 * c is in the required range
1086 *
1087 * We must use aon8
1088 *
1089 * s = ((((((((aon8 * t) >> 12) + b) * t) >> 15) + c) * t) >> 15) + x[1];
1090 *
1091 * But ((aon8 * t) >> 12) is in 2^(15+15-12) = 2^18 = 8 times
1092 * b is in 6 times
1093 * so we divide both ((aon8 * t) >> 12) and b by 16
1094 *
1095 * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 11) + c) * t) >> 15) + x[1];
1096 *
1097 * ((... + bon16) * t) >> 11 is 16 times too big
1098 * c is in the correct range
1099 * we must divide both by 32
1100 *
1101 * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 16) + con32) * t) >> 10) + x[1];
1102 *
1103 * aon8 = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4;
1104 * bon16 = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5;
1105 * con32 = (x[2] - x[0]) >> 6;
1106 *
1107 * A lot of accuracy is lost here. It is quite likely that some
1108 * of the above would cancel anyway, so the scaling down wouldn't
1109 * have to be so severe. However, I'm not in the mood to work it
1110 * out now :P
1111 *
1112 * It may also be worth investigating whether doing this stuff
1113 * in floats would be faster.
1114 */
1115
1116 /* Unh4x0r3d version:
1117 #define DO_RESAMPLE(inc) \
1118 { \
1119 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
1120 \
1121 if (src_pos != last_src_pos) { \
1122 last_src_pos = src_pos; \
1123 x = &src[src_pos]; \
1124 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4; \
1125 b = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5; \
1126 c = (x[2] - x[0]) >> 6; \
1127 } \
1128 \
1129 dst[s] += ((((((((((a * src_subpos) >> 16) + b) * src_subpos) >> 16) + c) * src_subpos) >> 10) + x[1]) * volume_fact) >> 14; \
1130 \
1131 src_subpos += dt + inc; \
1132 src_pos += src_subpos >> 15; \
1133 src_subpos &= 0x7FFFl; \
1134 s++; \
1135 }
1136 */
1137
1138 /* H4x0r3d version: */
1139 #define DO_RESAMPLE(inc) \
1140 { \
1141 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
1142 \
1143 if (src_pos != last_src_pos) { \
1144 last_src_pos = src_pos; \
1145 x = &src[src_pos]; \
1146 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; \
1147 b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); \
1148 c = (x[2] - x[0]) >> 1; \
1149 } \
1150 \
1151 dst[s] += (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * src_subpos) >> 15) + b) * src_subpos) >> 15) + c) * src_subpos) >> 15) + x[1]) * volume_fact) >> 14; \
1152 \
1153 src_subpos += dt + inc; \
1154 src_pos += src_subpos >> 15; \
1155 src_subpos &= 0x7FFFl; \
1156 s++; \
1157 }
1158
1159 MAKE_RESAMPLER();
1160
1161 #undef DO_RESAMPLE
1162
1163 }
1164
1165 }
1166
1167 end:
1168
1169 ASSERT(s <= dst_size);
1170
1171 *_src_pos = src_pos;
1172 *_src_subpos = src_subpos;
1173 if (_dir) *_dir = dir;
1174
1175 return s;
1176}
1177#endif
diff --git a/apps/codecs/dumb/src/helpers/sampbuf.c b/apps/codecs/dumb/src/helpers/sampbuf.c
deleted file mode 100644
index 75510c729a..0000000000
--- a/apps/codecs/dumb/src/helpers/sampbuf.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * sampbuf.c - Helper for allocating sample / / \ \
12 * buffers. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include "dumb.h"
22
23
24
25sample_t **create_sample_buffer(int n_channels, long length)
26{
27 int i;
28 sample_t **samples = malloc(n_channels * sizeof(*samples));
29 if (!samples) return NULL;
30 samples[0] = malloc(n_channels * length * sizeof(*samples[0]));
31 if (!samples[0]) {
32 free(samples);
33 return NULL;
34 }
35 for (i = 1; i < n_channels; i++) samples[i] = samples[i-1] + length;
36 return samples;
37}
38
39
40
41void destroy_sample_buffer(sample_t **samples)
42{
43 if (samples) {
44 free(samples[0]);
45 free(samples);
46 }
47}
diff --git a/apps/codecs/dumb/src/helpers/silence.c b/apps/codecs/dumb/src/helpers/silence.c
deleted file mode 100644
index 4d5fdcf4da..0000000000
--- a/apps/codecs/dumb/src/helpers/silence.c
+++ /dev/null
@@ -1,29 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * silence.c - Silencing helper. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <string.h>
21#include "dumb.h"
22
23
24
25void dumb_silence(sample_t *samples, long length)
26{
27 memset(samples, 0, length * sizeof(*samples));
28}
29
diff --git a/apps/codecs/dumb/src/helpers/stdfile.c b/apps/codecs/dumb/src/helpers/stdfile.c
deleted file mode 100644
index 2f02539a92..0000000000
--- a/apps/codecs/dumb/src/helpers/stdfile.c
+++ /dev/null
@@ -1,93 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * stdfile.c - stdio file input module. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdio.h>
21
22#include "dumb.h"
23
24
25
26static void *dumb_stdfile_open(const char *filename)
27{
28 return fopen(filename, "rb");
29}
30
31
32
33static int dumb_stdfile_skip(void *f, long n)
34{
35 return fseek(f, n, SEEK_CUR);
36}
37
38
39
40static int dumb_stdfile_getc(void *f)
41{
42 return fgetc(f);
43}
44
45
46
47static long dumb_stdfile_getnc(char *ptr, long n, void *f)
48{
49 return fread(ptr, 1, n, f);
50}
51
52
53
54static void dumb_stdfile_close(void *f)
55{
56 fclose(f);
57}
58
59
60
61static DUMBFILE_SYSTEM stdfile_dfs = {
62 &dumb_stdfile_open,
63 &dumb_stdfile_skip,
64 &dumb_stdfile_getc,
65 &dumb_stdfile_getnc,
66 &dumb_stdfile_close
67};
68
69
70
71void dumb_register_stdfiles(void)
72{
73 register_dumbfile_system(&stdfile_dfs);
74}
75
76
77
78static DUMBFILE_SYSTEM stdfile_dfs_leave_open = {
79 NULL,
80 &dumb_stdfile_skip,
81 &dumb_stdfile_getc,
82 &dumb_stdfile_getnc,
83 NULL
84};
85
86
87
88DUMBFILE *dumbfile_open_stdfile(FILE *p)
89{
90 DUMBFILE *d = dumbfile_open_ex(p, &stdfile_dfs_leave_open);
91
92 return d;
93}