summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/dumb/src/core')
-rw-r--r--apps/codecs/dumb/src/core/atexit.c71
-rw-r--r--apps/codecs/dumb/src/core/duhlen.c34
-rw-r--r--apps/codecs/dumb/src/core/dumbfile.c401
-rw-r--r--apps/codecs/dumb/src/core/loadduh.c42
-rw-r--r--apps/codecs/dumb/src/core/makeduh.c92
-rw-r--r--apps/codecs/dumb/src/core/rawsig.c44
-rw-r--r--apps/codecs/dumb/src/core/readduh.c107
-rw-r--r--apps/codecs/dumb/src/core/register.c104
-rw-r--r--apps/codecs/dumb/src/core/rendduh.c202
-rw-r--r--apps/codecs/dumb/src/core/rendsig.c299
-rw-r--r--apps/codecs/dumb/src/core/unload.c58
11 files changed, 1454 insertions, 0 deletions
diff --git a/apps/codecs/dumb/src/core/atexit.c b/apps/codecs/dumb/src/core/atexit.c
new file mode 100644
index 0000000000..16c6abdb2c
--- /dev/null
+++ b/apps/codecs/dumb/src/core/atexit.c
@@ -0,0 +1,71 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * atexit.c - Library Clean-up Management. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27typedef struct DUMB_ATEXIT_PROC
28{
29 struct DUMB_ATEXIT_PROC *next;
30 void (*proc)(void);
31}
32DUMB_ATEXIT_PROC;
33
34
35
36static DUMB_ATEXIT_PROC *dumb_atexit_proc = NULL;
37
38
39
40int dumb_atexit(void (*proc)(void))
41{
42 DUMB_ATEXIT_PROC *dap = dumb_atexit_proc;
43
44 while (dap) {
45 if (dap->proc == proc) return 0;
46 dap = dap->next;
47 }
48
49 dap = malloc(sizeof(*dap));
50
51 if (!dap)
52 return -1;
53
54 dap->next = dumb_atexit_proc;
55 dap->proc = proc;
56 dumb_atexit_proc = dap;
57
58 return 0;
59}
60
61
62
63void dumb_exit(void)
64{
65 while (dumb_atexit_proc) {
66 DUMB_ATEXIT_PROC *next = dumb_atexit_proc->next;
67 (*dumb_atexit_proc->proc)();
68 free(dumb_atexit_proc);
69 dumb_atexit_proc = next;
70 }
71}
diff --git a/apps/codecs/dumb/src/core/duhlen.c b/apps/codecs/dumb/src/core/duhlen.c
new file mode 100644
index 0000000000..4500d0a50f
--- /dev/null
+++ b/apps/codecs/dumb/src/core/duhlen.c
@@ -0,0 +1,34 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * duhlen.c - Function to return the length of / / \ \
12 * a DUH. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * Note that the length of a DUH is a constant | ' /
17 * stored in the DUH struct and in the DUH disk \__/
18 * format. It will be calculated on loading for
19 * other formats in which the length is not explicitly stored. Also note that
20 * it does not necessarily correspond to the length of time for which the DUH
21 * will generate samples. Rather it represents a suitable point for a player
22 * such as Winamp to stop, and in any good DUH it will allow for any final
23 * flourish to fade out and be appreciated.
24 */
25
26#include "dumb.h"
27#include "internal/dumb.h"
28
29
30
31long duh_get_length(DUH *duh)
32{
33 return duh ? duh->length : 0;
34}
diff --git a/apps/codecs/dumb/src/core/dumbfile.c b/apps/codecs/dumb/src/core/dumbfile.c
new file mode 100644
index 0000000000..71108c0c3b
--- /dev/null
+++ b/apps/codecs/dumb/src/core/dumbfile.c
@@ -0,0 +1,401 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * dumbfile.c - Hookable, strictly sequential / / \ \
12 * file input functions. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23
24
25
26static DUMBFILE_SYSTEM *the_dfs = NULL;
27
28
29
30void register_dumbfile_system(DUMBFILE_SYSTEM *dfs)
31{
32 ASSERT(dfs);
33 ASSERT(dfs->open);
34 ASSERT(dfs->getc);
35 ASSERT(dfs->close);
36 the_dfs = dfs;
37}
38
39
40
41struct DUMBFILE
42{
43 DUMBFILE_SYSTEM *dfs;
44 void *file;
45 long pos;
46};
47
48
49
50DUMBFILE *dumbfile_open(const char *filename)
51{
52 DUMBFILE *f;
53
54 ASSERT(the_dfs);
55
56 f = malloc(sizeof(*f));
57
58 if (!f)
59 return NULL;
60
61 f->dfs = the_dfs;
62
63 f->file = (*the_dfs->open)(filename);
64
65 if (!f->file) {
66 free(f);
67 return NULL;
68 }
69
70 f->pos = 0;
71
72 return f;
73}
74
75
76
77DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs)
78{
79 DUMBFILE *f;
80
81 ASSERT(dfs);
82 ASSERT(dfs->getc);
83 ASSERT(file);
84
85 f = malloc(sizeof(*f));
86
87 if (!f) {
88 if (dfs->close)
89 (*dfs->close)(file);
90 return NULL;
91 }
92
93 f->dfs = dfs;
94 f->file = file;
95
96 f->pos = 0;
97
98 return f;
99}
100
101
102
103long dumbfile_pos(DUMBFILE *f)
104{
105 ASSERT(f);
106
107 return f->pos;
108}
109
110
111
112int dumbfile_skip(DUMBFILE *f, long n)
113{
114 int rv;
115
116 ASSERT(f);
117 ASSERT(n >= 0);
118
119 if (f->pos < 0)
120 return -1;
121
122 f->pos += n;
123
124 if (f->dfs->skip) {
125 rv = (*f->dfs->skip)(f->file, n);
126 if (rv) {
127 f->pos = -1;
128 return rv;
129 }
130 } else {
131 while (n) {
132 rv = (*f->dfs->getc)(f->file);
133 if (rv < 0) {
134 f->pos = -1;
135 return rv;
136 }
137 n--;
138 }
139 }
140
141 return 0;
142}
143
144
145
146int dumbfile_getc(DUMBFILE *f)
147{
148 int rv;
149
150 ASSERT(f);
151
152 if (f->pos < 0)
153 return -1;
154
155 rv = (*f->dfs->getc)(f->file);
156
157 if (rv < 0) {
158 f->pos = -1;
159 return rv;
160 }
161
162 f->pos++;
163
164 return rv;
165}
166
167
168
169int dumbfile_igetw(DUMBFILE *f)
170{
171 int l, h;
172
173 ASSERT(f);
174
175 if (f->pos < 0)
176 return -1;
177
178 l = (*f->dfs->getc)(f->file);
179 if (l < 0) {
180 f->pos = -1;
181 return l;
182 }
183
184 h = (*f->dfs->getc)(f->file);
185 if (h < 0) {
186 f->pos = -1;
187 return h;
188 }
189
190 f->pos += 2;
191
192 return l | (h << 8);
193}
194
195
196
197int dumbfile_mgetw(DUMBFILE *f)
198{
199 int l, h;
200
201 ASSERT(f);
202
203 if (f->pos < 0)
204 return -1;
205
206 h = (*f->dfs->getc)(f->file);
207 if (h < 0) {
208 f->pos = -1;
209 return h;
210 }
211
212 l = (*f->dfs->getc)(f->file);
213 if (l < 0) {
214 f->pos = -1;
215 return l;
216 }
217
218 f->pos += 2;
219
220 return l | (h << 8);
221}
222
223
224
225long dumbfile_igetl(DUMBFILE *f)
226{
227 unsigned long rv, b;
228
229 ASSERT(f);
230
231 if (f->pos < 0)
232 return -1;
233
234 rv = (*f->dfs->getc)(f->file);
235 if ((signed long)rv < 0) {
236 f->pos = -1;
237 return rv;
238 }
239
240 b = (*f->dfs->getc)(f->file);
241 if ((signed long)b < 0) {
242 f->pos = -1;
243 return b;
244 }
245 rv |= b << 8;
246
247 b = (*f->dfs->getc)(f->file);
248 if ((signed long)b < 0) {
249 f->pos = -1;
250 return b;
251 }
252 rv |= b << 16;
253
254 b = (*f->dfs->getc)(f->file);
255 if ((signed long)b < 0) {
256 f->pos = -1;
257 return b;
258 }
259 rv |= b << 24;
260
261 f->pos += 4;
262
263 return rv;
264}
265
266
267
268long dumbfile_mgetl(DUMBFILE *f)
269{
270 unsigned long rv, b;
271
272 ASSERT(f);
273
274 if (f->pos < 0)
275 return -1;
276
277 rv = (*f->dfs->getc)(f->file);
278 if ((signed long)rv < 0) {
279 f->pos = -1;
280 return rv;
281 }
282 rv <<= 24;
283
284 b = (*f->dfs->getc)(f->file);
285 if ((signed long)b < 0) {
286 f->pos = -1;
287 return b;
288 }
289 rv |= b << 16;
290
291 b = (*f->dfs->getc)(f->file);
292 if ((signed long)b < 0) {
293 f->pos = -1;
294 return b;
295 }
296 rv |= b << 8;
297
298 b = (*f->dfs->getc)(f->file);
299 if ((signed long)b < 0) {
300 f->pos = -1;
301 return b;
302 }
303 rv |= b;
304
305 f->pos += 4;
306
307 return rv;
308}
309
310
311
312unsigned long dumbfile_cgetul(DUMBFILE *f)
313{
314 unsigned long rv = 0;
315 int v;
316
317 do {
318 v = dumbfile_getc(f);
319
320 if (v < 0)
321 return v;
322
323 rv <<= 7;
324 rv |= v & 0x7F;
325 } while (v & 0x80);
326
327 return rv;
328}
329
330
331
332signed long dumbfile_cgetsl(DUMBFILE *f)
333{
334 unsigned long rv = dumbfile_cgetul(f);
335
336 if (f->pos < 0)
337 return rv;
338
339 return (rv >> 1) | (rv << 31);
340}
341
342
343
344long dumbfile_getnc(char *ptr, long n, DUMBFILE *f)
345{
346 long rv;
347
348 ASSERT(f);
349 ASSERT(n >= 0);
350
351 if (f->pos < 0)
352 return -1;
353
354 if (f->dfs->getnc) {
355 rv = (*f->dfs->getnc)(ptr, n, f->file);
356 if (rv < n) {
357 f->pos = -1;
358 return MAX(rv, 0);
359 }
360 } else {
361 for (rv = 0; rv < n; rv++) {
362 int c = (*f->dfs->getc)(f->file);
363 if (c < 0) {
364 f->pos = -1;
365 return rv;
366 }
367 *ptr++ = c;
368 }
369 }
370
371 f->pos += rv;
372
373 return rv;
374}
375
376
377
378int dumbfile_error(DUMBFILE *f)
379{
380 ASSERT(f);
381
382 return f->pos < 0;
383}
384
385
386
387int dumbfile_close(DUMBFILE *f)
388{
389 int rv;
390
391 ASSERT(f);
392
393 rv = f->pos < 0;
394
395 if (f->dfs->close)
396 (*f->dfs->close)(f->file);
397
398 free(f);
399
400 return rv;
401}
diff --git a/apps/codecs/dumb/src/core/loadduh.c b/apps/codecs/dumb/src/core/loadduh.c
new file mode 100644
index 0000000000..7dfe5cc100
--- /dev/null
+++ b/apps/codecs/dumb/src/core/loadduh.c
@@ -0,0 +1,42 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * loadduh.c - Code to read a DUH from a file, / / \ \
12 * opening and closing the file for | < / \_
13 * you. | \/ /\ /
14 * \_ / > /
15 * By entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/dumb.h"
22
23
24
25/* load_duh(): loads a .duh file, returning a pointer to a DUH struct.
26 * When you have finished with it, you must pass the pointer to unload_duh()
27 * so that the memory can be freed.
28 */
29DUH *load_duh(const char *filename)
30{
31 DUH *duh;
32 DUMBFILE *f = dumbfile_open(filename);
33
34 if (!f)
35 return NULL;
36
37 duh = read_duh(f);
38
39 dumbfile_close(f);
40
41 return duh;
42}
diff --git a/apps/codecs/dumb/src/core/makeduh.c b/apps/codecs/dumb/src/core/makeduh.c
new file mode 100644
index 0000000000..1e422fb502
--- /dev/null
+++ b/apps/codecs/dumb/src/core/makeduh.c
@@ -0,0 +1,92 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * makeduh.c - Function to construct a DUH from / / \ \
12 * its components. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27static DUH_SIGNAL *make_signal(DUH_SIGTYPE_DESC *desc, sigdata_t *sigdata)
28{
29 DUH_SIGNAL *signal;
30
31 ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
32 ASSERT(desc->sigrenderer_get_samples && desc->sigrenderer_get_current_sample);
33
34 signal = malloc(sizeof(*signal));
35
36 if (!signal) {
37 if (desc->unload_sigdata)
38 if (sigdata)
39 (*desc->unload_sigdata)(sigdata);
40 return NULL;
41 }
42
43 signal->desc = desc;
44 signal->sigdata = sigdata;
45
46 return signal;
47}
48
49
50
51DUH *make_duh(long length, int n_signals, DUH_SIGTYPE_DESC *desc[], sigdata_t *sigdata[])
52{
53 DUH *duh = malloc(sizeof(*duh));
54 int i;
55 int fail;
56
57 if (duh) {
58 duh->n_signals = n_signals;
59
60 duh->signal = malloc(n_signals * sizeof(*duh->signal));
61
62 if (!duh->signal) {
63 free(duh);
64 duh = NULL;
65 }
66 }
67
68 if (!duh) {
69 for (i = 0; i < n_signals; i++)
70 if (desc[i]->unload_sigdata)
71 if (sigdata[i])
72 (*desc[i]->unload_sigdata)(sigdata[i]);
73 return NULL;
74 }
75
76 fail = 0;
77
78 for (i = 0; i < n_signals; i++) {
79 duh->signal[i] = make_signal(desc[i], sigdata[i]);
80 if (!duh->signal[i])
81 fail = 1;
82 }
83
84 if (fail) {
85 unload_duh(duh);
86 return NULL;
87 }
88
89 duh->length = length;
90
91 return duh;
92}
diff --git a/apps/codecs/dumb/src/core/rawsig.c b/apps/codecs/dumb/src/core/rawsig.c
new file mode 100644
index 0000000000..926c990655
--- /dev/null
+++ b/apps/codecs/dumb/src/core/rawsig.c
@@ -0,0 +1,44 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * rawsig.c - Function to retrieve raw signal / / \ \
12 * data from a DUH provided you know | < / \_
13 * what type of signal it is. | \/ /\ /
14 * \_ / > /
15 * By entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27/* You have to specify the type of sigdata, proving you know what to do with
28 * the pointer. If you get it wrong, you can expect NULL back.
29 */
30sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type)
31{
32 DUH_SIGNAL *signal;
33
34 if (!duh) return NULL;
35
36 if ((unsigned int)sig >= (unsigned int)duh->n_signals) return NULL;
37
38 signal = duh->signal[sig];
39
40 if (signal && signal->desc->type == type)
41 return signal->sigdata;
42
43 return NULL;
44}
diff --git a/apps/codecs/dumb/src/core/readduh.c b/apps/codecs/dumb/src/core/readduh.c
new file mode 100644
index 0000000000..514b04a077
--- /dev/null
+++ b/apps/codecs/dumb/src/core/readduh.c
@@ -0,0 +1,107 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readduh.c - Code to read a DUH from an open / / \ \
12 * file. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27static DUH_SIGNAL *read_signal(DUH *duh, DUMBFILE *f)
28{
29 DUH_SIGNAL *signal;
30 long type;
31
32 signal = malloc(sizeof(*signal));
33
34 if (!signal)
35 return NULL;
36
37 type = dumbfile_mgetl(f);
38 if (dumbfile_error(f)) {
39 free(signal);
40 return NULL;
41 }
42
43 signal->desc = _dumb_get_sigtype_desc(type);
44 if (!signal->desc) {
45 free(signal);
46 return NULL;
47 }
48
49 if (signal->desc->load_sigdata) {
50 signal->sigdata = (*signal->desc->load_sigdata)(duh, f);
51 if (!signal->sigdata) {
52 free(signal);
53 return NULL;
54 }
55 } else
56 signal->sigdata = NULL;
57
58 return signal;
59}
60
61
62
63/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its
64 * pointer, or null on error. The file is not closed.
65 */
66DUH *read_duh(DUMBFILE *f)
67{
68 DUH *duh;
69 int i;
70
71 if (dumbfile_mgetl(f) != DUH_SIGNATURE)
72 return NULL;
73
74 duh = malloc(sizeof(*duh));
75 if (!duh)
76 return NULL;
77
78 duh->length = dumbfile_igetl(f);
79 if (dumbfile_error(f) || duh->length <= 0) {
80 free(duh);
81 return NULL;
82 }
83
84 duh->n_signals = dumbfile_igetl(f);
85 if (dumbfile_error(f) || duh->n_signals <= 0) {
86 free(duh);
87 return NULL;
88 }
89
90 duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals);
91 if (!duh->signal) {
92 free(duh);
93 return NULL;
94 }
95
96 for (i = 0; i < duh->n_signals; i++)
97 duh->signal[i] = NULL;
98
99 for (i = 0; i < duh->n_signals; i++) {
100 if (!(duh->signal[i] = read_signal(duh, f))) {
101 unload_duh(duh);
102 return NULL;
103 }
104 }
105
106 return duh;
107}
diff --git a/apps/codecs/dumb/src/core/register.c b/apps/codecs/dumb/src/core/register.c
new file mode 100644
index 0000000000..9eed45f796
--- /dev/null
+++ b/apps/codecs/dumb/src/core/register.c
@@ -0,0 +1,104 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * register.c - Signal type registration. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27static DUH_SIGTYPE_DESC_LINK *sigtype_desc = NULL;
28static DUH_SIGTYPE_DESC_LINK **sigtype_desc_tail = &sigtype_desc;
29
30
31
32/* destroy_sigtypes(): frees all memory allocated while registering signal
33 * types. This function is set up to be called by dumb_exit().
34 */
35static void destroy_sigtypes(void)
36{
37 DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc, *next;
38 sigtype_desc = NULL;
39 sigtype_desc_tail = &sigtype_desc;
40
41 while (desc_link) {
42 next = desc_link->next;
43 free(desc_link);
44 desc_link = next;
45 }
46}
47
48
49
50/* dumb_register_sigtype(): registers a new signal type with DUMB. The signal
51 * type is identified by a four-character string (e.g. "WAVE"), which you can
52 * encode using the the DUMB_ID() macro (e.g. DUMB_ID('W','A','V','E')). The
53 * signal's behaviour is defined by four functions, whose pointers you pass
54 * here. See the documentation for details.
55 *
56 * If a DUH tries to use a signal that has not been registered using this
57 * function, then the library will fail to load the DUH.
58 */
59void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc)
60{
61 DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
62
63 ASSERT((desc->load_sigdata && desc->unload_sigdata) || (!desc->load_sigdata && !desc->unload_sigdata));
64 ASSERT((desc->start_sigrenderer && desc->end_sigrenderer) || (!desc->start_sigrenderer && !desc->end_sigrenderer));
65 ASSERT(desc->sigrenderer_get_samples && desc->sigrenderer_get_current_sample);
66
67 if (desc_link) {
68 do {
69 if (desc_link->desc->type == desc->type) {
70 desc_link->desc = desc;
71 return;
72 }
73 desc_link = desc_link->next;
74 } while (desc_link);
75 } else
76 dumb_atexit(&destroy_sigtypes);
77
78 desc_link = *sigtype_desc_tail = malloc(sizeof(DUH_SIGTYPE_DESC_LINK));
79
80 if (!desc_link)
81 return;
82
83 desc_link->next = NULL;
84 sigtype_desc_tail = &desc_link->next;
85
86 desc_link->desc = desc;
87}
88
89
90
91/* _dumb_get_sigtype_desc(): searches the registered functions for a signal
92 * type matching the parameter. If such a sigtype is found, it returns a
93 * pointer to a sigtype descriptor containing the necessary functions to
94 * manage the signal. If none is found, it returns NULL.
95 */
96DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type)
97{
98 DUH_SIGTYPE_DESC_LINK *desc_link = sigtype_desc;
99
100 while (desc_link && desc_link->desc->type != type)
101 desc_link = desc_link->next;
102
103 return desc_link->desc;
104}
diff --git a/apps/codecs/dumb/src/core/rendduh.c b/apps/codecs/dumb/src/core/rendduh.c
new file mode 100644
index 0000000000..39db8ab8a3
--- /dev/null
+++ b/apps/codecs/dumb/src/core/rendduh.c
@@ -0,0 +1,202 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * rendduh.c - Functions for rendering a DUH into / / \ \
12 * an end-user sample format. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <limits.h>
22
23#include "dumb.h"
24#include "internal/dumb.h"
25
26
27
28/* On the x86, we can use some tricks to speed stuff up */
29#if (defined _MSC_VER) || (defined __DJGPP__) || (defined __MINGW__)
30// Can't we detect Linux and other x86 platforms here? :/
31
32#define FAST_MID(var, min, max) { \
33 var -= (min); \
34 var &= (~var) >> (sizeof(var) * CHAR_BIT - 1); \
35 var += (min); \
36 var -= (max); \
37 var &= var >> (sizeof(var) * CHAR_BIT - 1); \
38 var += (max); \
39}
40
41#define CONVERT8(src, pos, signconv) { \
42 signed int f = (src + 0x8000) >> 16; \
43 FAST_MID(f, -128, 127); \
44 ((char*)sptr)[pos] = (char)f ^ signconv; \
45}
46
47#define CONVERT16(src, pos, signconv) { \
48 signed int f = (src + 0x80) >> 8; \
49 FAST_MID(f, -32768, 32767); \
50 ((short*)sptr)[pos] = (short)(f ^ signconv); \
51}
52
53#else
54
55#define CONVERT8(src, pos, signconv) \
56{ \
57 signed int f = (src + 0x8000) >> 16; \
58 f = MID(-128, f, 127); \
59 ((char *)sptr)[pos] = (char)f ^ signconv; \
60}
61
62
63
64#define CONVERT16(src, pos, signconv) \
65{ \
66 signed int f = (src + 0x80) >> 8; \
67 f = MID(-32768, f, 32767); \
68 ((short *)sptr)[pos] = (short)(f ^ signconv); \
69}
70
71#endif
72
73
74
75/* DEPRECATED */
76DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos)
77{
78 return duh_start_sigrenderer(duh, 0, n_channels, pos);
79}
80
81
82
83long duh_render(
84 DUH_SIGRENDERER *sigrenderer,
85 int bits, int unsign,
86 float volume, float delta,
87 long size, void *sptr
88)
89{
90 long n;
91
92 sample_t **sampptr;
93
94 int n_channels;
95
96 ASSERT(bits == 8 || bits == 16);
97 ASSERT(sptr);
98
99 if (!sigrenderer)
100 return 0;
101
102 n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
103
104 ASSERT(n_channels > 0);
105 /* This restriction will be removed when need be. At the moment, tightly
106 * optimised loops exist for exactly one or two channels.
107 */
108 ASSERT(n_channels <= 2);
109
110 sampptr = create_sample_buffer(n_channels, size);
111
112 if (!sampptr)
113 return 0;
114
115 dumb_silence(sampptr[0], n_channels * size);
116
117 size = duh_sigrenderer_get_samples(sigrenderer, volume, delta, size, sampptr);
118
119 if (bits == 16) {
120 int signconv = unsign ? 0x8000 : 0x0000;
121
122 if (n_channels == 2) {
123 for (n = 0; n < size; n++) {
124 CONVERT16(sampptr[0][n], n << 1, signconv);
125 }
126 for (n = 0; n < size; n++) {
127 CONVERT16(sampptr[1][n], (n << 1) + 1, signconv);
128 }
129 } else {
130 for (n = 0; n < size; n++) {
131 CONVERT16(sampptr[0][n], n, signconv);
132 }
133 }
134 } else {
135 char signconv = unsign ? 0x80 : 0x00;
136
137 if (n_channels == 2) {
138 for (n = 0; n < size; n++) {
139 CONVERT8(sampptr[0][n], n << 1, signconv);
140 }
141 for (n = 0; n < size; n++) {
142 CONVERT8(sampptr[1][n], (n << 1) + 1, signconv);
143 }
144 } else {
145 for (n = 0; n < size; n++) {
146 CONVERT8(sampptr[0][n], n, signconv);
147 }
148 }
149 }
150
151 destroy_sample_buffer(sampptr);
152
153 return size;
154}
155
156
157
158/* DEPRECATED */
159int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr)
160{
161 return duh_sigrenderer_get_n_channels(dr);
162}
163
164
165
166/* DEPRECATED */
167long duh_renderer_get_position(DUH_SIGRENDERER *dr)
168{
169 return duh_sigrenderer_get_position(dr);
170}
171
172
173
174/* DEPRECATED */
175void duh_end_renderer(DUH_SIGRENDERER *dr)
176{
177 duh_end_sigrenderer(dr);
178}
179
180
181
182/* DEPRECATED */
183DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer)
184{
185 return sigrenderer;
186}
187
188
189
190/* DEPRECATED */
191DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr)
192{
193 return dr;
194}
195
196
197
198/* DEPRECATED */
199DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr)
200{
201 return dr;
202}
diff --git a/apps/codecs/dumb/src/core/rendsig.c b/apps/codecs/dumb/src/core/rendsig.c
new file mode 100644
index 0000000000..a36ceb41cf
--- /dev/null
+++ b/apps/codecs/dumb/src/core/rendsig.c
@@ -0,0 +1,299 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * rendsig.c - Wrappers to render samples from / / \ \
12 * the signals in a DUH. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27struct DUH_SIGRENDERER
28{
29 DUH_SIGTYPE_DESC *desc;
30
31 sigrenderer_t *sigrenderer;
32
33 int n_channels;
34
35 long pos;
36 int subpos;
37
38 DUH_SIGRENDERER_ANALYSER_CALLBACK callback;
39 void *callback_data;
40};
41
42
43
44DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos)
45{
46 DUH_SIGRENDERER *sigrenderer;
47
48 DUH_SIGNAL *signal;
49 DUH_START_SIGRENDERER proc;
50
51 if ((unsigned int)sig >= (unsigned int)duh->n_signals)
52 return NULL;
53
54 signal = duh->signal[sig];
55 if (!signal)
56 return NULL;
57
58 sigrenderer = malloc(sizeof(*sigrenderer));
59 if (!sigrenderer)
60 return NULL;
61
62 sigrenderer->desc = signal->desc;
63
64 proc = sigrenderer->desc->start_sigrenderer;
65
66 if (proc) {
67 duh->signal[sig] = NULL;
68 sigrenderer->sigrenderer = (*proc)(duh, signal->sigdata, n_channels, pos);
69 duh->signal[sig] = signal;
70
71 if (!sigrenderer->sigrenderer) {
72 free(sigrenderer);
73 return NULL;
74 }
75 } else
76 sigrenderer->sigrenderer = NULL;
77
78 sigrenderer->n_channels = n_channels;
79
80 sigrenderer->pos = pos;
81 sigrenderer->subpos = 0;
82
83 sigrenderer->callback = NULL;
84
85 return sigrenderer;
86}
87
88
89
90#include <stdio.h>
91void duh_sigrenderer_set_callback(
92 DUH_SIGRENDERER *sigrenderer,
93 DUH_SIGRENDERER_CALLBACK callback, void *data
94)
95{
96 (void)sigrenderer;
97 (void)callback;
98 (void)data;
99/* FIXME
100 fprintf(stderr,
101 "Call to deprecated function duh_sigrenderer_set_callback(). The callback\n"
102 "was not installed. See dumb/docs/deprec.txt for how to fix this.\n");*/
103}
104
105
106
107void duh_sigrenderer_set_analyser_callback(
108 DUH_SIGRENDERER *sigrenderer,
109 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data
110)
111{
112 if (sigrenderer) {
113 sigrenderer->callback = callback;
114 sigrenderer->callback_data = data;
115 }
116}
117
118
119
120int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer)
121{
122 return sigrenderer ? sigrenderer->n_channels : 0;
123}
124
125
126
127long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer)
128{
129 return sigrenderer ? sigrenderer->pos : -1;
130}
131
132
133
134void duh_sigrenderer_set_sigparam(
135 DUH_SIGRENDERER *sigrenderer,
136 unsigned char id, long value
137)
138{
139 DUH_SIGRENDERER_SET_SIGPARAM proc;
140
141 if (!sigrenderer) return;
142
143 proc = sigrenderer->desc->sigrenderer_set_sigparam;
144 if (proc)
145 (*proc)(sigrenderer->sigrenderer, id, value);
146 else
147 TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n",
148 (int)id,
149 value,
150 (int)(sigrenderer->desc->type >> 24),
151 (int)(sigrenderer->desc->type >> 16),
152 (int)(sigrenderer->desc->type >> 8),
153 (int)(sigrenderer->desc->type));
154}
155
156
157
158long duh_sigrenderer_get_samples(
159 DUH_SIGRENDERER *sigrenderer,
160 float volume, float delta,
161 long size, sample_t **samples
162)
163{
164 long rendered;
165 LONG_LONG t;
166
167 if (!sigrenderer) return 0;
168
169 rendered = (*sigrenderer->desc->sigrenderer_get_samples)
170 (sigrenderer->sigrenderer, volume, delta, size, samples);
171
172 if (rendered) {
173 if (sigrenderer->callback)
174 (*sigrenderer->callback)(sigrenderer->callback_data,
175 (const sample_t *const *)samples, sigrenderer->n_channels, rendered);
176
177 t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
178
179 sigrenderer->pos += (long)(t >> 16);
180 sigrenderer->subpos = (int)t & 65535;
181 }
182
183 return rendered;
184}
185
186
187
188/* DEPRECATED */
189long duh_render_signal(
190 DUH_SIGRENDERER *sigrenderer,
191 float volume, float delta,
192 long size, sample_t **samples
193)
194{
195 sample_t **s = create_sample_buffer(sigrenderer->n_channels, size);
196 long rendered;
197 long i;
198 int j;
199 if (!s) return 0;
200 rendered = duh_sigrenderer_get_samples(sigrenderer, volume, delta, size, s);
201 for (j = 0; j < sigrenderer->n_channels; j++)
202 for (i = 0; i < rendered; i++)
203 samples[j][i] += s[j][i] >> 8;
204 destroy_sample_buffer(s);
205 return rendered;
206}
207
208
209
210void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
211{
212 if (sigrenderer)
213 (*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
214}
215
216
217
218void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
219{
220 if (sigrenderer) {
221 if (sigrenderer->desc->end_sigrenderer)
222 if (sigrenderer->sigrenderer)
223 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
224
225 free(sigrenderer);
226 }
227}
228
229
230
231DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
232{
233 DUH_SIGRENDERER *sigrenderer;
234
235 if (desc->start_sigrenderer && !vsigrenderer) return NULL;
236
237 sigrenderer = malloc(sizeof(*sigrenderer));
238 if (!sigrenderer) {
239 if (desc->end_sigrenderer)
240 if (vsigrenderer)
241 (*desc->end_sigrenderer)(vsigrenderer);
242 return NULL;
243 }
244
245 sigrenderer->desc = desc;
246 sigrenderer->sigrenderer = vsigrenderer;
247
248 sigrenderer->n_channels = n_channels;
249
250 sigrenderer->pos = pos;
251 sigrenderer->subpos = 0;
252
253 sigrenderer->callback = NULL;
254
255 return sigrenderer;
256}
257
258
259
260sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
261{
262 if (sigrenderer && sigrenderer->desc->type == type)
263 return sigrenderer->sigrenderer;
264
265 return NULL;
266}
267
268
269
270#if 0
271// This function is disabled because we don't know whether we want to destroy
272// the sigrenderer if the type doesn't match. We don't even know if we need
273// the function at all. Who would want to keep an IT_SIGRENDERER (for
274// instance) without keeping the DUH_SIGRENDERER?
275sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
276{
277 if (sigrenderer && sigrenderer->desc->type == type) {
278
279
280
281 if (sigrenderer) {
282 if (sigrenderer->desc->end_sigrenderer)
283 if (sigrenderer->sigrenderer)
284 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
285
286 free(sigrenderer);
287 }
288
289
290
291
292
293
294 return sigrenderer->sigrenderer;
295 }
296
297 return NULL;
298}
299#endif
diff --git a/apps/codecs/dumb/src/core/unload.c b/apps/codecs/dumb/src/core/unload.c
new file mode 100644
index 0000000000..3bf0285cd1
--- /dev/null
+++ b/apps/codecs/dumb/src/core/unload.c
@@ -0,0 +1,58 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * unload.c - Code to free a DUH from memory. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/dumb.h"
24
25
26
27static void destroy_signal(DUH_SIGNAL *signal)
28{
29 if (signal) {
30 if (signal->desc)
31 if (signal->desc->unload_sigdata)
32 if (signal->sigdata)
33 (*signal->desc->unload_sigdata)(signal->sigdata);
34
35 free(signal);
36 }
37}
38
39
40
41/* unload_duh(): destroys a DUH struct. You must call this for every DUH
42 * struct created, when you've finished with it.
43 */
44void unload_duh(DUH *duh)
45{
46 int i;
47
48 if (duh) {
49 if (duh->signal) {
50 for (i = 0; i < duh->n_signals; i++)
51 destroy_signal(duh->signal[i]);
52
53 free(duh->signal);
54 }
55
56 free(duh);
57 }
58}