summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/src
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/dumb/src')
-rw-r--r--apps/codecs/dumb/src/allegro/alplay.c270
-rw-r--r--apps/codecs/dumb/src/allegro/datduh.c60
-rw-r--r--apps/codecs/dumb/src/allegro/datit.c62
-rw-r--r--apps/codecs/dumb/src/allegro/datmod.c61
-rw-r--r--apps/codecs/dumb/src/allegro/dats3m.c61
-rw-r--r--apps/codecs/dumb/src/allegro/datunld.c31
-rw-r--r--apps/codecs/dumb/src/allegro/datxm.c62
-rw-r--r--apps/codecs/dumb/src/allegro/packfile.c98
-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.c301
-rw-r--r--apps/codecs/dumb/src/core/unload.c58
-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
-rw-r--r--apps/codecs/dumb/src/it/itload.c43
-rw-r--r--apps/codecs/dumb/src/it/itmisc.c175
-rw-r--r--apps/codecs/dumb/src/it/itorder.c63
-rw-r--r--apps/codecs/dumb/src/it/itread.c1181
-rw-r--r--apps/codecs/dumb/src/it/itrender.c3512
-rw-r--r--apps/codecs/dumb/src/it/itunload.c71
-rw-r--r--apps/codecs/dumb/src/it/loadmod.c42
-rw-r--r--apps/codecs/dumb/src/it/loads3m.c42
-rw-r--r--apps/codecs/dumb/src/it/loadxm.c42
-rw-r--r--apps/codecs/dumb/src/it/readmod.c594
-rw-r--r--apps/codecs/dumb/src/it/reads3m.c668
-rw-r--r--apps/codecs/dumb/src/it/readxm.c998
-rw-r--r--apps/codecs/dumb/src/it/xmeffect.c255
38 files changed, 0 insertions, 11559 deletions
diff --git a/apps/codecs/dumb/src/allegro/alplay.c b/apps/codecs/dumb/src/allegro/alplay.c
deleted file mode 100644
index 983bde105b..0000000000
--- a/apps/codecs/dumb/src/allegro/alplay.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * alplay.c - Functions to play a DUH through / / \ \
12 * an Allegro audio stream. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include <allegro.h>
23
24#include "aldumb.h"
25
26
27
28#define ADP_PLAYING 1
29
30struct AL_DUH_PLAYER
31{
32 int flags;
33 long bufsize;
34 int freq;
35 AUDIOSTREAM *stream;
36 DUH_SIGRENDERER *sigrenderer; /* If this is NULL, stream is invalid. */
37 float volume;
38 int silentcount;
39};
40
41
42
43AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq)
44{
45 AL_DUH_PLAYER *dp;
46
47 /* This restriction is imposed by Allegro. */
48 ASSERT(n_channels > 0);
49 ASSERT(n_channels <= 2);
50
51 if (!duh)
52 return NULL;
53
54 dp = malloc(sizeof(*dp));
55 if (!dp)
56 return NULL;
57
58 dp->flags = ADP_PLAYING;
59 dp->bufsize = bufsize;
60 dp->freq = freq;
61
62 dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
63
64 if (!dp->stream) {
65 free(dp);
66 return NULL;
67 }
68
69 voice_set_priority(dp->stream->voice, 255);
70
71 dp->sigrenderer = duh_start_sigrenderer(duh, 0, n_channels, pos);
72
73 if (!dp->sigrenderer) {
74 stop_audio_stream(dp->stream);
75 free(dp);
76 return NULL;
77 }
78
79 dp->volume = volume;
80 dp->silentcount = 0;
81
82 return dp;
83}
84
85
86
87void al_stop_duh(AL_DUH_PLAYER *dp)
88{
89 if (dp) {
90 if (dp->sigrenderer) {
91 duh_end_sigrenderer(dp->sigrenderer);
92 stop_audio_stream(dp->stream);
93 }
94 free(dp);
95 }
96}
97
98
99
100void al_pause_duh(AL_DUH_PLAYER *dp)
101{
102 if (dp && dp->sigrenderer && (dp->flags & ADP_PLAYING)) {
103 voice_stop(dp->stream->voice);
104 dp->flags &= ~ADP_PLAYING;
105 }
106}
107
108
109
110void al_resume_duh(AL_DUH_PLAYER *dp)
111{
112 if (dp && dp->sigrenderer && !(dp->flags & ADP_PLAYING)) {
113 voice_start(dp->stream->voice);
114 dp->flags |= ADP_PLAYING;
115 }
116}
117
118
119
120void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority)
121{
122 if (dp && dp->sigrenderer)
123 voice_set_priority(dp->stream->voice, priority);
124}
125
126
127
128void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume)
129{
130 if (dp)
131 dp->volume = volume;
132}
133
134
135
136int al_poll_duh(AL_DUH_PLAYER *dp)
137{
138 unsigned short *sptr;
139 long n;
140 long size;
141 int n_channels;
142
143 if (!dp || !dp->sigrenderer)
144 return 1;
145
146 if (!(dp->flags & ADP_PLAYING))
147 return 0;
148
149 sptr = get_audio_stream_buffer(dp->stream);
150
151 if (!sptr)
152 return 0;
153
154 n = duh_render(dp->sigrenderer, 16, 1, dp->volume, 65536.0 / dp->freq, dp->bufsize, sptr);
155
156 if (n == 0) {
157 if (++dp->silentcount >= 2) {
158 duh_end_sigrenderer(dp->sigrenderer);
159 free_audio_stream_buffer(dp->stream);
160 stop_audio_stream(dp->stream);
161 dp->sigrenderer = NULL;
162 return 1;
163 }
164 }
165
166 n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer);
167 n *= n_channels;
168 size = dp->bufsize * n_channels;
169 for (; n < size; n++)
170 sptr[n] = 0x8000;
171
172 free_audio_stream_buffer(dp->stream);
173
174 return 0;
175}
176
177
178
179long al_duh_get_position(AL_DUH_PLAYER *dp)
180{
181 return dp ? duh_sigrenderer_get_position(dp->sigrenderer) : -1;
182}
183
184
185
186AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq)
187{
188 AL_DUH_PLAYER *dp;
189 int n_channels;
190
191 if (!sigrenderer)
192 return NULL;
193
194 dp = malloc(sizeof(*dp));
195 if (!dp)
196 return NULL;
197
198 n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
199
200 /* This restriction is imposed by Allegro. */
201 ASSERT(n_channels > 0);
202 ASSERT(n_channels <= 2);
203
204 dp->flags = ADP_PLAYING;
205 dp->bufsize = bufsize;
206 dp->freq = freq;
207
208 dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
209
210 if (!dp->stream) {
211 free(dp);
212 return NULL;
213 }
214
215 voice_set_priority(dp->stream->voice, 255);
216
217 dp->sigrenderer = sigrenderer;
218
219 dp->volume = volume;
220 dp->silentcount = 0;
221
222 return dp;
223}
224
225
226
227DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp)
228{
229 return dp ? dp->sigrenderer : NULL;
230}
231
232
233
234/* IMPORTANT: This function will return NULL if the music has ended. */
235// Should this be changed? User might want to hack the underlying SIGRENDERER
236// and resurrect it (e.g. change pattern number), before it gets destroyed...
237DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp)
238{
239 if (dp) {
240 DUH_SIGRENDERER *sigrenderer = dp->sigrenderer;
241 if (sigrenderer) stop_audio_stream(dp->stream);
242 free(dp);
243 return sigrenderer;
244 }
245 return NULL;
246}
247
248
249
250/* DEPRECATED */
251AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq)
252{
253 return al_duh_encapsulate_sigrenderer(dr, volume, bufsize, freq);
254}
255
256
257
258/* DEPRECATED */
259DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp)
260{
261 return al_duh_get_sigrenderer(dp);
262}
263
264
265
266/* DEPRECATED */
267DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp)
268{
269 return al_duh_decompose_to_sigrenderer(dp);
270}
diff --git a/apps/codecs/dumb/src/allegro/datduh.c b/apps/codecs/dumb/src/allegro/datduh.c
deleted file mode 100644
index 672e3c820c..0000000000
--- a/apps/codecs/dumb/src/allegro/datduh.c
+++ /dev/null
@@ -1,60 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * datduh.c - Integration with Allegro's / / \ \
12 * datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27static void *dat_read_duh(PACKFILE *f, long size)
28{
29 DUMBFILE *df;
30 DUH *duh;
31
32 (void)size;
33
34 df = dumbfile_open_packfile(f);
35
36 if (!df)
37 return NULL;
38
39 duh = read_duh(df);
40
41 dumbfile_close(df);
42
43 return duh;
44}
45
46
47
48/* dumb_register_dat_duh(): tells Allegro about the DUH datafile object. If
49 * you intend to load a datafile containing a DUH object, you must call this
50 * function first. It is recommended you pass DAT_DUH, but you may have a
51 * reason to use a different type (apart from pride, that doesn't count).
52 */
53void dumb_register_dat_duh(long type)
54{
55 register_datafile_object(
56 type,
57 &dat_read_duh,
58 &_dat_unload_duh
59 );
60}
diff --git a/apps/codecs/dumb/src/allegro/datit.c b/apps/codecs/dumb/src/allegro/datit.c
deleted file mode 100644
index 8f58f14234..0000000000
--- a/apps/codecs/dumb/src/allegro/datit.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * datit.c - Integration of IT files with / / \ \
12 * Allegro's datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27static void *dat_read_it(PACKFILE *f, long size)
28{
29 DUMBFILE *df;
30 DUH *duh;
31
32 (void)size;
33
34 df = dumbfile_open_packfile(f);
35
36 if (!df)
37 return NULL;
38
39 duh = dumb_read_it(df);
40
41 dumbfile_close(df);
42
43 return duh;
44}
45
46
47
48/* dumb_register_dat_it(): tells Allegro about the IT datafile object. If you
49 * intend to load a datafile containing an IT object, you must call this
50 * function first. It is recommended you pass DUMB_DAT_IT, but you may have a
51 * reason to use a different type (perhaps you already have a datafile with
52 * IT files in and they use a different type).
53 */
54void dumb_register_dat_it(long type)
55{
56 register_datafile_object(
57 type,
58 &dat_read_it,
59 &_dat_unload_duh
60 );
61}
62
diff --git a/apps/codecs/dumb/src/allegro/datmod.c b/apps/codecs/dumb/src/allegro/datmod.c
deleted file mode 100644
index 850b17b444..0000000000
--- a/apps/codecs/dumb/src/allegro/datmod.c
+++ /dev/null
@@ -1,61 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * datmod.c - Integration of MOD files with / / \ \
12 * Allegro's datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27static void *dat_read_mod(PACKFILE *f, long size)
28{
29 DUMBFILE *df;
30 DUH *duh;
31
32 (void)size;
33
34 df = dumbfile_open_packfile(f);
35
36 if (!df)
37 return NULL;
38
39 duh = dumb_read_mod(df);
40
41 dumbfile_close(df);
42
43 return duh;
44}
45
46
47
48/* dumb_register_dat_mod(): tells Allegro about the MOD datafile object. If
49 * you intend to load a datafile containing a MOD object, you must call this
50 * function first. It is recommended you pass DUMB_DAT_MOD, but you may have
51 * a reason to use a different type (perhaps you already have a datafile with
52 * MOD files in and they use a different type).
53 */
54void dumb_register_dat_mod(long type)
55{
56 register_datafile_object(
57 type,
58 &dat_read_mod,
59 &_dat_unload_duh
60 );
61}
diff --git a/apps/codecs/dumb/src/allegro/dats3m.c b/apps/codecs/dumb/src/allegro/dats3m.c
deleted file mode 100644
index a0fc74420e..0000000000
--- a/apps/codecs/dumb/src/allegro/dats3m.c
+++ /dev/null
@@ -1,61 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * dats3m.c - Integration of S3M files with / / \ \
12 * Allegro's datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27static void *dat_read_s3m(PACKFILE *f, long size)
28{
29 DUMBFILE *df;
30 DUH *duh;
31
32 (void)size;
33
34 df = dumbfile_open_packfile(f);
35
36 if (!df)
37 return NULL;
38
39 duh = dumb_read_s3m(df);
40
41 dumbfile_close(df);
42
43 return duh;
44}
45
46
47
48/* dumb_register_dat_s3m(): tells Allegro about the S3M datafile object. If
49 * you intend to load a datafile containing an S3M object, you must call this
50 * function first. It is recommended you pass DUMB_DAT_S3M, but you may have
51 * a reason to use a different type (perhaps you already have a datafile with
52 * S3M files in and they use a different type).
53 */
54void dumb_register_dat_s3m(long type)
55{
56 register_datafile_object(
57 type,
58 &dat_read_s3m,
59 &_dat_unload_duh
60 );
61}
diff --git a/apps/codecs/dumb/src/allegro/datunld.c b/apps/codecs/dumb/src/allegro/datunld.c
deleted file mode 100644
index 71906445e0..0000000000
--- a/apps/codecs/dumb/src/allegro/datunld.c
+++ /dev/null
@@ -1,31 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * datunld.c - Unload function for integration / / \ \
12 * with Allegro's datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27void _dat_unload_duh(void *duh)
28{
29 unload_duh(duh);
30}
31
diff --git a/apps/codecs/dumb/src/allegro/datxm.c b/apps/codecs/dumb/src/allegro/datxm.c
deleted file mode 100644
index 6cb98d87c1..0000000000
--- a/apps/codecs/dumb/src/allegro/datxm.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * datxm.c - Integration of XM files with / / \ \
12 * Allegro's datafiles. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23#include "internal/aldumb.h"
24
25
26
27static void *dat_read_xm(PACKFILE *f, long size)
28{
29 DUMBFILE *df;
30 DUH *duh;
31
32 (void)size;
33
34 df = dumbfile_open_packfile(f);
35
36 if (!df)
37 return NULL;
38
39 duh = dumb_read_xm(df);
40
41 dumbfile_close(df);
42
43 return duh;
44}
45
46
47
48/* dumb_register_dat_xm(): tells Allegro about the XM datafile object. If you
49 * intend to load a datafile containing an XM object, you must call this
50 * function first. It is recommended you pass DUMB_DAT_XM, but you may have a
51 * reason to use a different type (perhaps you already have a datafile with
52 * XM files in and they use a different type).
53 */
54void dumb_register_dat_xm(long type)
55{
56 register_datafile_object(
57 type,
58 &dat_read_xm,
59 &_dat_unload_duh
60 );
61}
62
diff --git a/apps/codecs/dumb/src/allegro/packfile.c b/apps/codecs/dumb/src/allegro/packfile.c
deleted file mode 100644
index 525baebd4e..0000000000
--- a/apps/codecs/dumb/src/allegro/packfile.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * packfile.c - Packfile input module. / / \ \
12 * | < / \_
13 * By entheh. | \/ /\ /
14 * \_ / > /
15 * Note that this does not use file compression; | \ / /
16 * for that you must open the file yourself and | ' /
17 * then use dumbfile_open_packfile(). \__/
18 */
19
20#include <allegro.h>
21
22#include "aldumb.h"
23
24
25
26static void *dumb_packfile_open(const char *filename)
27{
28 return pack_fopen(filename, F_READ);
29}
30
31
32
33static int dumb_packfile_skip(void *f, long n)
34{
35 return pack_fseek(f, n);
36}
37
38
39
40static int dumb_packfile_getc(void *f)
41{
42 return pack_getc(f);
43}
44
45
46
47static long dumb_packfile_getnc(char *ptr, long n, void *f)
48{
49 return pack_fread(ptr, n, f);
50}
51
52
53
54static void dumb_packfile_close(void *f)
55{
56 pack_fclose(f);
57}
58
59
60
61static DUMBFILE_SYSTEM packfile_dfs = {
62 &dumb_packfile_open,
63 &dumb_packfile_skip,
64 &dumb_packfile_getc,
65 &dumb_packfile_getnc,
66 &dumb_packfile_close
67};
68
69
70
71void dumb_register_packfiles(void)
72{
73 register_dumbfile_system(&packfile_dfs);
74}
75
76
77
78static DUMBFILE_SYSTEM packfile_dfs_leave_open = {
79 NULL,
80 &dumb_packfile_skip,
81 &dumb_packfile_getc,
82 &dumb_packfile_getnc,
83 NULL
84};
85
86
87
88DUMBFILE *dumbfile_open_packfile(PACKFILE *p)
89{
90 return dumbfile_open_ex(p, &packfile_dfs_leave_open);
91}
92
93
94
95DUMBFILE *dumbfile_from_packfile(PACKFILE *p)
96{
97 return p ? dumbfile_open_ex(p, &packfile_dfs) : NULL;
98}
diff --git a/apps/codecs/dumb/src/core/atexit.c b/apps/codecs/dumb/src/core/atexit.c
deleted file mode 100644
index 16c6abdb2c..0000000000
--- a/apps/codecs/dumb/src/core/atexit.c
+++ /dev/null
@@ -1,71 +0,0 @@
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
deleted file mode 100644
index 4500d0a50f..0000000000
--- a/apps/codecs/dumb/src/core/duhlen.c
+++ /dev/null
@@ -1,34 +0,0 @@
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
deleted file mode 100644
index 71108c0c3b..0000000000
--- a/apps/codecs/dumb/src/core/dumbfile.c
+++ /dev/null
@@ -1,401 +0,0 @@
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
deleted file mode 100644
index 7dfe5cc100..0000000000
--- a/apps/codecs/dumb/src/core/loadduh.c
+++ /dev/null
@@ -1,42 +0,0 @@
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
deleted file mode 100644
index 1e422fb502..0000000000
--- a/apps/codecs/dumb/src/core/makeduh.c
+++ /dev/null
@@ -1,92 +0,0 @@
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
deleted file mode 100644
index 926c990655..0000000000
--- a/apps/codecs/dumb/src/core/rawsig.c
+++ /dev/null
@@ -1,44 +0,0 @@
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
deleted file mode 100644
index 514b04a077..0000000000
--- a/apps/codecs/dumb/src/core/readduh.c
+++ /dev/null
@@ -1,107 +0,0 @@
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
deleted file mode 100644
index 9eed45f796..0000000000
--- a/apps/codecs/dumb/src/core/register.c
+++ /dev/null
@@ -1,104 +0,0 @@
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
deleted file mode 100644
index 39db8ab8a3..0000000000
--- a/apps/codecs/dumb/src/core/rendduh.c
+++ /dev/null
@@ -1,202 +0,0 @@
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
deleted file mode 100644
index 6b39ce7de9..0000000000
--- a/apps/codecs/dumb/src/core/rendsig.c
+++ /dev/null
@@ -1,301 +0,0 @@
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 return;
147 }
148
149 TRACE("Parameter #%d = %ld for signal %c%c%c%c, which does not take parameters.\n",
150 (int)id,
151 value,
152 (int)(sigrenderer->desc->type >> 24),
153 (int)(sigrenderer->desc->type >> 16),
154 (int)(sigrenderer->desc->type >> 8),
155 (int)(sigrenderer->desc->type));
156}
157
158
159
160long duh_sigrenderer_get_samples(
161 DUH_SIGRENDERER *sigrenderer,
162 float volume, float delta,
163 long size, sample_t **samples
164)
165{
166 long rendered;
167 LONG_LONG t;
168
169 if (!sigrenderer) return 0;
170
171 rendered = (*sigrenderer->desc->sigrenderer_get_samples)
172 (sigrenderer->sigrenderer, volume, delta, size, samples);
173
174 if (rendered) {
175 if (sigrenderer->callback)
176 (*sigrenderer->callback)(sigrenderer->callback_data,
177 (const sample_t *const *)samples, sigrenderer->n_channels, rendered);
178
179 t = sigrenderer->subpos + (LONG_LONG)(delta * 65536.0 + 0.5) * rendered;
180
181 sigrenderer->pos += (long)(t >> 16);
182 sigrenderer->subpos = (int)t & 65535;
183 }
184
185 return rendered;
186}
187
188
189
190/* DEPRECATED */
191long duh_render_signal(
192 DUH_SIGRENDERER *sigrenderer,
193 float volume, float delta,
194 long size, sample_t **samples
195)
196{
197 sample_t **s = create_sample_buffer(sigrenderer->n_channels, size);
198 long rendered;
199 long i;
200 int j;
201 if (!s) return 0;
202 rendered = duh_sigrenderer_get_samples(sigrenderer, volume, delta, size, s);
203 for (j = 0; j < sigrenderer->n_channels; j++)
204 for (i = 0; i < rendered; i++)
205 samples[j][i] += s[j][i] >> 8;
206 destroy_sample_buffer(s);
207 return rendered;
208}
209
210
211
212void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples)
213{
214 if (sigrenderer)
215 (*sigrenderer->desc->sigrenderer_get_current_sample)(sigrenderer->sigrenderer, volume, samples);
216}
217
218
219
220void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer)
221{
222 if (sigrenderer) {
223 if (sigrenderer->desc->end_sigrenderer)
224 if (sigrenderer->sigrenderer)
225 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
226
227 free(sigrenderer);
228 }
229}
230
231
232
233DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos)
234{
235 DUH_SIGRENDERER *sigrenderer;
236
237 if (desc->start_sigrenderer && !vsigrenderer) return NULL;
238
239 sigrenderer = malloc(sizeof(*sigrenderer));
240 if (!sigrenderer) {
241 if (desc->end_sigrenderer)
242 if (vsigrenderer)
243 (*desc->end_sigrenderer)(vsigrenderer);
244 return NULL;
245 }
246
247 sigrenderer->desc = desc;
248 sigrenderer->sigrenderer = vsigrenderer;
249
250 sigrenderer->n_channels = n_channels;
251
252 sigrenderer->pos = pos;
253 sigrenderer->subpos = 0;
254
255 sigrenderer->callback = NULL;
256
257 return sigrenderer;
258}
259
260
261
262sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
263{
264 if (sigrenderer && sigrenderer->desc->type == type)
265 return sigrenderer->sigrenderer;
266
267 return NULL;
268}
269
270
271
272#if 0
273// This function is disabled because we don't know whether we want to destroy
274// the sigrenderer if the type doesn't match. We don't even know if we need
275// the function at all. Who would want to keep an IT_SIGRENDERER (for
276// instance) without keeping the DUH_SIGRENDERER?
277sigrenderer_t *duh_decompose_to_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type)
278{
279 if (sigrenderer && sigrenderer->desc->type == type) {
280
281
282
283 if (sigrenderer) {
284 if (sigrenderer->desc->end_sigrenderer)
285 if (sigrenderer->sigrenderer)
286 (*sigrenderer->desc->end_sigrenderer)(sigrenderer->sigrenderer);
287
288 free(sigrenderer);
289 }
290
291
292
293
294
295
296 return sigrenderer->sigrenderer;
297 }
298
299 return NULL;
300}
301#endif
diff --git a/apps/codecs/dumb/src/core/unload.c b/apps/codecs/dumb/src/core/unload.c
deleted file mode 100644
index 3bf0285cd1..0000000000
--- a/apps/codecs/dumb/src/core/unload.c
+++ /dev/null
@@ -1,58 +0,0 @@
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}
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}
diff --git a/apps/codecs/dumb/src/it/itload.c b/apps/codecs/dumb/src/it/itload.c
deleted file mode 100644
index a377619a88..0000000000
--- a/apps/codecs/dumb/src/it/itload.c
+++ /dev/null
@@ -1,43 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itload.c - Code to read an Impulse Tracker / / \ \
12 * file, opening and closing it for | < / \_
13 * you. | \/ /\ /
14 * \_ / > /
15 * By entheh. Don't worry Bob, you're credited | \ / /
16 * in itread.c! | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24
25/* dumb_load_it(): loads an IT file into a DUH struct, returning a pointer to
26 * the DUH struct. When you have finished with it, you must pass the pointer
27 * to unload_duh() so that the memory can be freed.
28 */
29DUH *dumb_load_it(const char *filename)
30{
31 DUH *duh;
32 DUMBFILE *f = dumbfile_open(filename);
33
34 if (!f)
35 return NULL;
36
37 duh = dumb_read_it(f);
38
39 dumbfile_close(f);
40
41 return duh;
42}
43
diff --git a/apps/codecs/dumb/src/it/itmisc.c b/apps/codecs/dumb/src/it/itmisc.c
deleted file mode 100644
index b69a64df10..0000000000
--- a/apps/codecs/dumb/src/it/itmisc.c
+++ /dev/null
@@ -1,175 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itmisc.c - Miscellaneous functions relating / / \ \
12 * to module files. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24
25DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
26{
27 return duh_get_raw_sigdata(duh, 0, SIGTYPE_IT);
28}
29
30
31
32int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd)
33{
34 return sd ? sd->n_orders : 0;
35}
36
37
38
39int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd)
40{
41 return sd ? sd->global_volume : 0;
42}
43
44
45
46void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv)
47{
48 if (sd) sd->global_volume = gv;
49}
50
51
52
53int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd)
54{
55 return sd ? sd->mixing_volume : 0;
56}
57
58
59
60void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv)
61{
62 if (sd) sd->mixing_volume = mv;
63}
64
65
66
67int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd)
68{
69 return sd ? sd->speed : 0;
70}
71
72
73
74void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed)
75{
76 if (sd) sd->speed = speed;
77}
78
79
80
81int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd)
82{
83 return sd ? sd->tempo : 0;
84}
85
86
87
88void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo)
89{
90 if (sd) sd->tempo = tempo;
91}
92
93
94
95int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel)
96{
97 ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
98 return sd ? sd->channel_volume[channel] : 0;
99}
100
101void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume)
102{
103 ASSERT(channel >= 0 && channel < DUMB_IT_N_CHANNELS);
104 if (sd) sd->channel_volume[channel] = volume;
105}
106
107
108
109int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr)
110{
111 return sr ? sr->order : -1;
112}
113
114
115
116int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr)
117{
118 return sr ? sr->row : -1;
119}
120
121
122
123int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr)
124{
125 return sr ? sr->globalvolume : 0;
126}
127
128
129
130void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv)
131{
132 if (sr) sr->globalvolume = gv;
133}
134
135
136
137int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr)
138{
139 return sr ? sr->tempo : 0;
140}
141
142
143
144void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo)
145{
146 if (sr) sr->tempo = tempo;
147}
148
149
150
151int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr)
152{
153 return sr ? sr->speed : 0;
154}
155
156
157
158void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed)
159{
160 if (sr) sr->speed = speed;
161}
162
163
164
165int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel)
166{
167 return sr ? sr->channel[channel].channelvolume : 0;
168}
169
170
171
172void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume)
173{
174 if (sr) sr->channel[channel].channelvolume = volume;
175}
diff --git a/apps/codecs/dumb/src/it/itorder.c b/apps/codecs/dumb/src/it/itorder.c
deleted file mode 100644
index 6959f05443..0000000000
--- a/apps/codecs/dumb/src/it/itorder.c
+++ /dev/null
@@ -1,63 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itorder.c - Code to fix invalid patterns in / / \ \
12 * the pattern table. | < / \_
13 * | \/ /\ /
14 * By Julien Cugniere. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21
22#include <stdlib.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29/* This function ensures that any pattern mentioned in the order table but
30 * not present in the pattern table is treated as an empty 64 rows pattern.
31 * This is done by adding such a dummy pattern at the end of the pattern
32 * table, and redirect invalid orders to it.
33 * Patterns 254 and 255 are left untouched, unless the signal is an XM.
34 */
35int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata)
36{
37 int i;
38 int found_some = 0;
39
40 int first_invalid = sigdata->n_patterns;
41 int last_invalid = (sigdata->flags & IT_WAS_AN_XM) ? 255 : 253;
42
43 for (i = 0; i < sigdata->n_orders; i++) {
44 if (sigdata->order[i] >= first_invalid && sigdata->order[i] <= last_invalid) {
45 sigdata->order[i] = sigdata->n_patterns;
46 found_some = 1;
47 }
48 }
49
50 if (found_some) {
51 IT_PATTERN *new_pattern = realloc(sigdata->pattern, sizeof(*sigdata->pattern) * (sigdata->n_patterns + 1));
52 if (!new_pattern)
53 return -1;
54
55 new_pattern[sigdata->n_patterns].n_rows = 64;
56 new_pattern[sigdata->n_patterns].n_entries = 0;
57 new_pattern[sigdata->n_patterns].entry = NULL;
58 sigdata->pattern = new_pattern;
59 sigdata->n_patterns++;
60 }
61
62 return 0;
63}
diff --git a/apps/codecs/dumb/src/it/itread.c b/apps/codecs/dumb/src/it/itread.c
deleted file mode 100644
index 0e789436d2..0000000000
--- a/apps/codecs/dumb/src/it/itread.c
+++ /dev/null
@@ -1,1181 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itread.c - Code to read an Impulse Tracker / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * Based on the loader from an IT player by Bob. \_ / > /
15 * Adapted for DUMB by entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>//might not be necessary later; required for memset
22
23#include "dumb.h"
24#include "internal/it.h"
25
26
27
28#define INVESTIGATE_OLD_INSTRUMENTS
29
30
31
32static int it_seek(DUMBFILE *f, long offset)
33{
34 long pos = dumbfile_pos(f);
35
36 if (pos > offset)
37 return -1;
38
39 if (pos < offset)
40 if (dumbfile_skip(f, offset - pos))
41 return -1;
42
43 return 0;
44}
45
46
47
48typedef unsigned char byte;
49typedef unsigned short word;
50typedef unsigned long dword;
51
52
53
54static unsigned char *sourcebuf = NULL;
55static unsigned char *sourcepos = NULL;
56static unsigned char *sourceend;
57static int rembits = 0;
58
59
60
61static int readblock(DUMBFILE *f)
62{
63 long size;
64 int c;
65
66 size = dumbfile_igetw(f);
67 if (size < 0)
68 return size;
69
70 sourcebuf = malloc(size);
71 if (!sourcebuf)
72 return -1;
73
74 c = dumbfile_getnc((char *)sourcebuf, size, f);
75 if (c < size) {
76 free(sourcebuf);
77 sourcebuf = NULL;
78 return -1;
79 }
80
81 sourcepos = sourcebuf;
82 sourceend = sourcebuf + size;
83 rembits = 8;
84 return 0;
85}
86
87
88
89static void freeblock(void)
90{
91 free(sourcebuf);
92 sourcebuf = NULL;
93}
94
95
96
97static int readbits(int bitwidth)
98{
99 int val = 0;
100 int b = 0;
101
102 if (sourcepos >= sourceend) return val;
103
104 while (bitwidth > rembits) {
105 val |= *sourcepos++ << b;
106 if (sourcepos >= sourceend) return val;
107 b += rembits;
108 bitwidth -= rembits;
109 rembits = 8;
110 }
111
112 val |= (*sourcepos & ((1 << bitwidth) - 1)) << b;
113 *sourcepos >>= bitwidth;
114 rembits -= bitwidth;
115
116 return val;
117}
118
119
120
121/** WARNING - do we even need to pass `right`? */
122/** WARNING - why bother memsetting at all? The whole array is written... */
123// if we do memset, dumb_silence() would be neater...
124static int decompress8(DUMBFILE *f, sample_t *left, sample_t *right, int len, int cmwt)
125{
126 int blocklen, blockpos;
127 byte bitwidth;
128 word val;
129 char d1, d2;
130
131 memset(left, 0, len * sizeof(*left));
132 if (right) {
133 memset(right, 0, len * sizeof(*right));
134 len <<= 1;
135 }
136
137 while (len > 0) {
138 //Read a block of compressed data:
139 if (readblock(f))
140 return -1;
141 //Set up a few variables
142 blocklen = (len < 0x8000) ? len : 0x8000; //Max block length is 0x8000 bytes
143 blockpos = 0;
144 bitwidth = 9;
145 d1 = d2 = 0;
146 //Start the decompression:
147 while (blockpos < blocklen) {
148 //Read a value:
149 val = (word)readbits(bitwidth);
150 //Check for bit width change:
151
152 if (bitwidth < 7) { //Method 1:
153 if (val == (1 << (bitwidth - 1))) {
154 val = (word)readbits(3) + 1;
155 bitwidth = (val < bitwidth) ? val : val + 1;
156 continue;
157 }
158 }
159 else if (bitwidth < 9) { //Method 2
160 byte border = (0xFF >> (9 - bitwidth)) - 4;
161
162 if (val > border && val <= (border + 8)) {
163 val -= border;
164 bitwidth = (val < bitwidth) ? val : val + 1;
165 continue;
166 }
167 }
168 else if (bitwidth == 9) { //Method 3
169 if (val & 0x100) {
170 bitwidth = (val + 1) & 0xFF;
171 continue;
172 }
173 }
174 else { //Illegal width, abort ?
175 freeblock();
176 return -1;
177 }
178
179 //Expand the value to signed byte:
180 {
181 char v; //The sample value:
182 if (bitwidth < 8) {
183 byte shift = 8 - bitwidth;
184 v = (val << shift);
185 v >>= shift;
186 }
187 else
188 v = (char)val;
189
190 //And integrate the sample value
191 //(It always has to end with integration doesn't it ? ;-)
192 d1 += v;
193 d2 += d1;
194 }
195
196 //Store !
197 /* Version 2.15 was an unofficial version with hacked compression
198 * code. Yay, better compression :D
199 */
200 if (right && (len & 1))
201 *right++ = (int)(signed char)(cmwt == 0x215 ? d2 : d1) << 16;
202 else
203 *left++ = (int)(signed char)(cmwt == 0x215 ? d2 : d1) << 16;
204 len--;
205 blockpos++;
206 }
207 freeblock();
208 }
209 return 0;
210}
211
212
213
214static int decompress16(DUMBFILE *f, sample_t *left, sample_t *right, int len, int cmwt)
215{
216 int blocklen, blockpos;
217 byte bitwidth;
218 long val;
219 short d1, d2;
220
221 memset(left, 0, len * sizeof(*left));
222 if (right) {
223 memset(right, 0, len * sizeof(*right));
224 len <<= 1;
225 }
226
227 while (len > 0) {
228 //Read a block of compressed data:
229 if (readblock(f))
230 return -1;
231 //Set up a few variables
232 blocklen = (len < 0x4000) ? len : 0x4000; // Max block length is 0x4000 bytes
233 blockpos = 0;
234 bitwidth = 17;
235 d1 = d2 = 0;
236 //Start the decompression:
237 while (blockpos < blocklen) {
238 val = readbits(bitwidth);
239 //Check for bit width change:
240
241 if (bitwidth < 7) { //Method 1:
242 if (val == (1 << (bitwidth - 1))) {
243 val = readbits(4) + 1;
244 bitwidth = (val < bitwidth) ? val : val + 1;
245 continue;
246 }
247 }
248 else if (bitwidth < 17) { //Method 2
249 word border = (0xFFFF >> (17 - bitwidth)) - 8;
250
251 if (val > border && val <= (border + 16)) {
252 val -= border;
253 bitwidth = val < bitwidth ? val : val + 1;
254 continue;
255 }
256 }
257 else if (bitwidth == 17) { //Method 3
258 if (val & 0x10000) {
259 bitwidth = (val + 1) & 0xFF;
260 continue;
261 }
262 }
263 else { //Illegal width, abort ?
264 freeblock();
265 return -1;
266 }
267
268 //Expand the value to signed byte:
269 {
270 short v; //The sample value:
271 if (bitwidth < 16) {
272 byte shift = 16 - bitwidth;
273 v = (short)(val << shift);
274 v >>= shift;
275 }
276 else
277 v = (short)val;
278
279 //And integrate the sample value
280 //(It always has to end with integration doesn't it ? ;-)
281 d1 += v;
282 d2 += d1;
283 }
284
285 //Store !
286 /* Version 2.15 was an unofficial version with hacked compression
287 * code. Yay, better compression :D
288 */
289 if (right && (len & 1))
290 *right++ = (int)(signed short)(cmwt == 0x215 ? d2 : d1) << 8;
291 else
292 *left++ = (int)(signed short)(cmwt == 0x215 ? d2 : d1) << 8;
293 len--;
294 blockpos++;
295 }
296 freeblock();
297 }
298 return 0;
299}
300
301
302
303static int it_read_envelope(IT_ENVELOPE *envelope, DUMBFILE *f)
304{
305 int n;
306
307 envelope->flags = dumbfile_getc(f);
308 envelope->n_nodes = dumbfile_getc(f);
309 envelope->loop_start = dumbfile_getc(f);
310 envelope->loop_end = dumbfile_getc(f);
311 envelope->sus_loop_start = dumbfile_getc(f);
312 envelope->sus_loop_end = dumbfile_getc(f);
313 for (n = 0; n < envelope->n_nodes; n++) {
314 envelope->node_y[n] = dumbfile_getc(f);
315 envelope->node_t[n] = dumbfile_igetw(f);
316 }
317 dumbfile_skip(f, 75 - envelope->n_nodes * 3 + 1);
318
319 return dumbfile_error(f);
320}
321
322
323
324static int it_read_old_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f)
325{
326 int n;
327
328 if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE)
329 return -1;
330
331 /* Skip DOS Filename. */
332 dumbfile_skip(f, 13);
333
334 instrument->volume_envelope.flags = dumbfile_getc(f);
335 instrument->volume_envelope.loop_start = dumbfile_getc(f);
336 instrument->volume_envelope.loop_end = dumbfile_getc(f);
337 instrument->volume_envelope.sus_loop_start = dumbfile_getc(f);
338 instrument->volume_envelope.sus_loop_end = dumbfile_getc(f);
339
340 /* Skip two unused bytes. */
341 dumbfile_skip(f, 2);
342
343 /* In the old instrument format, fadeout ranges from 0 to 64, and is
344 * subtracted at intervals from a value starting at 512. In the new
345 * format, all these values are doubled. Therefore we double when loading
346 * from the old instrument format - that way we don't have to think about
347 * it later.
348 */
349 instrument->fadeout = dumbfile_igetw(f) << 1;
350 instrument->new_note_action = dumbfile_getc(f);
351 instrument->dup_check_type = dumbfile_getc(f);
352 instrument->dup_check_action = DCA_NOTE_CUT; // This might be wrong!
353 /** WARNING - what is the duplicate check action for old-style instruments? */
354
355 /* Skip Tracker Version and Number of Samples. These are only used in
356 * separate instrument files. Also skip unused bytes and Instrument Name.
357 */
358 dumbfile_skip(f, 36);
359
360 instrument->pp_separation = 0;
361 instrument->pp_centre = 60;
362 instrument->global_volume = 128;
363 /** WARNING - should global_volume be 64 or something? */
364 instrument->default_pan = 32;
365 /** WARNING - should default_pan be 128, meaning don`t use? */
366 instrument->random_volume = 0;
367 instrument->random_pan = 0;
368
369 for (n = 0; n < 120; n++) {
370 instrument->map_note[n] = dumbfile_getc(f);
371 instrument->map_sample[n] = dumbfile_getc(f);
372 }
373
374 /* Skip "Volume envelope (200 bytes)". */
375 // - need to know better what this is for though.
376 dumbfile_skip(f, 200);
377
378#if defined(INVESTIGATE_OLD_INSTRUMENTS) && 0
379 fprintf(stderr, "Inst %02d Env:", n);
380#endif
381
382 for (n = 0; n < 25; n++)
383 {
384 instrument->volume_envelope.node_t[n] = dumbfile_getc(f);
385 instrument->volume_envelope.node_y[n] = dumbfile_getc(f);
386
387#if defined(INVESTIGATE_OLD_INSTRUMENTS) && 0
388 fprintf(stderr, " %d,%d",
389 instrument->volume_envelope.node_t[n],
390 instrument->volume_envelope.node_y[n]);
391#endif
392
393 // This loop is unfinished, as we can probably escape from it before
394 // the end if we want to. Hence the otherwise useless dumbfile_skip()
395 // call below.
396 }
397 dumbfile_skip(f, 50 - (n << 1));
398 instrument->volume_envelope.n_nodes = n;
399
400#if defined(INVESTIGATE_OLD_INSTRUMENTS) && 0
401 fprintf(stderr, "\n");
402#endif
403
404 if (dumbfile_error(f))
405 return -1;
406
407 instrument->filter_cutoff = 127;
408 instrument->filter_resonance = 0;
409
410 instrument->pan_envelope.flags = 0;
411 instrument->pitch_envelope.flags = 0;
412
413 return 0;
414}
415
416
417
418static int it_read_instrument(IT_INSTRUMENT *instrument, DUMBFILE *f)
419{
420 int n;
421
422 if (dumbfile_mgetl(f) != IT_INSTRUMENT_SIGNATURE)
423 return -1;
424
425 /* Skip DOS Filename. */
426 dumbfile_skip(f, 13);
427
428 instrument->new_note_action = dumbfile_getc(f);
429 instrument->dup_check_type = dumbfile_getc(f);
430 instrument->dup_check_action = dumbfile_getc(f);
431 instrument->fadeout = dumbfile_igetw(f);
432 instrument->pp_separation = dumbfile_getc(f);
433 instrument->pp_centre = dumbfile_getc(f);
434 instrument->global_volume = dumbfile_getc(f);
435 instrument->default_pan = dumbfile_getc(f);
436 instrument->random_volume = dumbfile_getc(f);
437 instrument->random_pan = dumbfile_getc(f);
438
439 /* Skip Tracker Version and Number of Samples. These are only used in
440 * separate instrument files. Also skip unused byte and Instrument Name.
441 */
442 dumbfile_skip(f, 30);
443
444 instrument->filter_cutoff = dumbfile_getc(f);
445 instrument->filter_resonance = dumbfile_getc(f);
446
447 /* Skip MIDI Channel, Program and Bank. */
448 dumbfile_skip(f, 4);
449
450 for (n = 0; n < 120; n++) {
451 instrument->map_note[n] = dumbfile_getc(f);
452 instrument->map_sample[n] = dumbfile_getc(f);
453 }
454
455 if (dumbfile_error(f))
456 return -1;
457
458 if (it_read_envelope(&instrument->volume_envelope, f)) return -1;
459 if (it_read_envelope(&instrument->pan_envelope, f)) return -1;
460 if (it_read_envelope(&instrument->pitch_envelope, f)) return -1;
461
462 return 0;
463}
464
465
466
467static int it_read_sample_header(IT_SAMPLE *sample, unsigned char *convert, long *offset, DUMBFILE *f)
468{
469 if (dumbfile_mgetl(f) != IT_SAMPLE_SIGNATURE)
470 return -1;
471
472 /* Skip DOS Filename. */
473 dumbfile_skip(f, 13);
474
475 sample->global_volume = dumbfile_getc(f);
476 sample->flags = dumbfile_getc(f);
477 sample->default_volume = dumbfile_getc(f);
478
479 /* Skip Sample Name. */
480 dumbfile_skip(f, 26);
481
482 *convert = dumbfile_getc(f);
483 sample->default_pan = dumbfile_getc(f);
484 sample->length = dumbfile_igetl(f);
485 sample->loop_start = dumbfile_igetl(f);
486 sample->loop_end = dumbfile_igetl(f);
487 sample->C5_speed = dumbfile_igetl(f);
488 sample->sus_loop_start = dumbfile_igetl(f);
489 sample->sus_loop_end = dumbfile_igetl(f);
490
491#ifdef STEREO_SAMPLES_COUNT_AS_TWO
492 if (sample->flags & IT_SAMPLE_STEREO) {
493 sample->length >>= 1;
494 sample->loop_start >>= 1;
495 sample->loop_end >>= 1;
496 sample->C5_speed >>= 1;
497 sample->sus_loop_start >>= 1;
498 sample->sus_loop_end >>= 1;
499 }
500#endif
501
502 if (sample->flags & IT_SAMPLE_EXISTS) {
503 if (sample->length <= 0)
504 sample->flags &= ~IT_SAMPLE_EXISTS;
505 else {
506 if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
507 sample->flags &= ~IT_SAMPLE_LOOP;
508 else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end)
509 sample->flags &= ~IT_SAMPLE_LOOP;
510
511 if ((unsigned int)sample->sus_loop_end > (unsigned int)sample->length)
512 sample->flags &= ~IT_SAMPLE_SUS_LOOP;
513 else if ((unsigned int)sample->sus_loop_start >= (unsigned int)sample->sus_loop_end)
514 sample->flags &= ~IT_SAMPLE_SUS_LOOP;
515
516 /* We may be able to truncate the sample to save memory. */
517 if (sample->flags & IT_SAMPLE_LOOP) {
518 if ((sample->flags & IT_SAMPLE_SUS_LOOP) && sample->sus_loop_end >= sample->loop_end)
519 sample->length = sample->sus_loop_end;
520 else
521 sample->length = sample->loop_end;
522 }
523 }
524 }
525
526 *offset = dumbfile_igetl(f);
527
528 sample->vibrato_speed = dumbfile_getc(f);
529 sample->vibrato_depth = dumbfile_getc(f);
530 sample->vibrato_rate = dumbfile_getc(f);
531 sample->vibrato_waveform = dumbfile_getc(f);
532
533 return dumbfile_error(f);
534}
535
536
537
538static long it_read_sample_data(int cmwt, IT_SAMPLE *sample, unsigned char convert, DUMBFILE *f)
539{
540 long n;
541
542 sample->left = malloc(sample->length * sizeof(*sample->left));
543 if (!sample->left)
544 return -1;
545
546 if (sample->flags & IT_SAMPLE_STEREO) {
547 sample->right = malloc(sample->length * sizeof(*sample->right));
548 if (!sample->right)
549 return -1;
550 }
551
552 if (sample->flags & 8) {
553 /* If the sample is packed, then we must unpack it. */
554
555 /** WARNING - unresolved business here... test with ModPlug? */
556
557 if (sample->flags & IT_SAMPLE_STEREO)
558 return -1;
559
560/*
561//#ifndef STEREO_SAMPLES_COUNT_AS_TWO
562 ASSERT(!(sample->flags & IT_SAMPLE_STEREO));
563//#endif
564*/
565 if (sample->flags & IT_SAMPLE_16BIT)
566 decompress16(f, sample->left, sample->right, sample->length, cmwt);
567 else
568 decompress8(f, sample->left, sample->right, sample->length, cmwt);
569 } else if (sample->flags & IT_SAMPLE_STEREO) {
570 if (sample->flags & IT_SAMPLE_16BIT) {
571 if (convert & 2) {
572 for (n = 0; n < sample->length; n++) {
573 sample->left[n] = (int)(signed short)dumbfile_mgetw(f) << 8;
574 sample->right[n] = (int)(signed short)dumbfile_mgetw(f) << 8;
575 }
576 } else {
577 for (n = 0; n < sample->length; n++) {
578 sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
579 sample->right[n] = (int)(signed short)dumbfile_igetw(f) << 8;
580 }
581 }
582 } else {
583 for (n = 0; n < sample->length; n++) {
584 sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
585 sample->right[n] = (int)(signed char)dumbfile_getc(f) << 16;
586 }
587 }
588 } else if (sample->flags & IT_SAMPLE_16BIT) {
589 if (convert & 2)
590 for (n = 0; n < sample->length; n++)
591 sample->left[n] = (int)(signed short)dumbfile_mgetw(f) << 8;
592 else
593 for (n = 0; n < sample->length; n++)
594 sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
595 } else
596 for (n = 0; n < sample->length; n++)
597 sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
598
599 if (dumbfile_error(f))
600 return -1;
601
602 if (!(convert & 1)) {
603 /* Convert to signed. */
604 for (n = 0; n < sample->length; n++)
605 sample->left[n] ^= 0xFF800000;
606
607 if (sample->right)
608 for (n = 0; n < sample->length; n++)
609 sample->right[n] ^= 0xFF800000;
610 }
611
612 /* NOT SUPPORTED:
613 *
614 * convert & 4 - Samples stored as delta values
615 * convert & 16 - Samples stored as TX-Wave 12-bit values
616 * convert & 32 - Left/Right/All Stereo prompt
617 */
618
619 return 0;
620}
621
622
623
624#define DETECT_DUPLICATE_CHANNELS
625#ifdef DETECT_DUPLICATE_CHANNELS
626#include <stdio.h>
627#endif
628static int it_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
629{
630 unsigned char cmask[DUMB_IT_N_CHANNELS];
631 unsigned char cnote[DUMB_IT_N_CHANNELS];
632 unsigned char cinstrument[DUMB_IT_N_CHANNELS];
633 unsigned char cvolpan[DUMB_IT_N_CHANNELS];
634 unsigned char ceffect[DUMB_IT_N_CHANNELS];
635 unsigned char ceffectvalue[DUMB_IT_N_CHANNELS];
636#ifdef DETECT_DUPLICATE_CHANNELS
637 IT_ENTRY *dupentry[DUMB_IT_N_CHANNELS];
638#endif
639
640 int n_entries = 0;
641 int buflen;
642 int bufpos = 0;
643
644 IT_ENTRY *entry;
645
646 unsigned char channel;
647 unsigned char mask;
648
649 memset(cmask, 0, sizeof(cmask));
650 memset(cnote, 0, sizeof(cnote));
651 memset(cinstrument, 0, sizeof(cinstrument));
652 memset(cvolpan, 0, sizeof(cvolpan));
653 memset(ceffect, 0, sizeof(ceffect));
654 memset(ceffectvalue, 0, sizeof(ceffectvalue));
655#ifdef DETECT_DUPLICATE_CHANNELS
656 {
657 int i;
658 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL;
659 }
660#endif
661
662 buflen = dumbfile_igetw(f);
663 pattern->n_rows = dumbfile_igetw(f);
664
665 /* Skip four unused bytes. */
666 dumbfile_skip(f, 4);
667
668 if (dumbfile_error(f))
669 return -1;
670
671 /* Read in the pattern data. */
672 dumbfile_getnc((char *)buffer, buflen, f);
673
674 if (dumbfile_error(f))
675 return -1;
676
677 /* Scan the pattern data, and work out how many entries we need room for. */
678 while (bufpos < buflen) {
679 unsigned char b = buffer[bufpos++];
680
681 if (b == 0) {
682 /* End of row */
683 n_entries++;
684 continue;
685 }
686
687 channel = (b - 1) & 63;
688
689 if (b & 128)
690 cmask[channel] = mask = buffer[bufpos++];
691 else
692 mask = cmask[channel];
693
694 {
695 static const unsigned char used[16] = {0, 1, 1, 2, 1, 2, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5};
696 n_entries += (mask != 0);
697 bufpos += used[mask & 15];
698 }
699 }
700
701 pattern->n_entries = n_entries;
702
703 pattern->entry = malloc(n_entries * sizeof(*pattern->entry));
704
705 if (!pattern->entry)
706 return -1;
707
708 bufpos = 0;
709 memset(cmask, 0, sizeof(cmask));
710
711 entry = pattern->entry;
712
713 while (bufpos < buflen) {
714 unsigned char b = buffer[bufpos++];
715
716 if (b == 0) {
717 /* End of row */
718 IT_SET_END_ROW(entry);
719 entry++;
720#ifdef DETECT_DUPLICATE_CHANNELS
721 {
722 int i;
723 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) dupentry[i] = NULL;
724 }
725#endif
726 continue;
727 }
728
729 channel = (b - 1) & 63;
730
731 if (b & 128)
732 cmask[channel] = mask = buffer[bufpos++];
733 else
734 mask = cmask[channel];
735
736 if (mask) {
737 entry->mask = (mask & 15) | (mask >> 4);
738 entry->channel = channel;
739
740 if (mask & IT_ENTRY_NOTE)
741 cnote[channel] = entry->note = buffer[bufpos++];
742 else if (mask & (IT_ENTRY_NOTE << 4))
743 entry->note = cnote[channel];
744
745 if (mask & IT_ENTRY_INSTRUMENT)
746 cinstrument[channel] = entry->instrument = buffer[bufpos++];
747 else if (mask & (IT_ENTRY_INSTRUMENT << 4))
748 entry->instrument = cinstrument[channel];
749
750 if (mask & IT_ENTRY_VOLPAN)
751 cvolpan[channel] = entry->volpan = buffer[bufpos++];
752 else if (mask & (IT_ENTRY_VOLPAN << 4))
753 entry->volpan = cvolpan[channel];
754
755 if (mask & IT_ENTRY_EFFECT) {
756 ceffect[channel] = entry->effect = buffer[bufpos++];
757 ceffectvalue[channel] = entry->effectvalue = buffer[bufpos++];
758 } else {
759 entry->effect = ceffect[channel];
760 entry->effectvalue = ceffectvalue[channel];
761 }
762
763#if defined( DETECT_DUPLICATE_CHANNELS) && 0
764 if (dupentry[channel]) {
765 FILE *f = fopen("dupentry.txt", "a");
766 if (!f) abort();
767 fprintf(f, "Two events on channel %d:", channel);
768 fprintf(f, " Event #1:");
769 if (dupentry[channel]->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", dupentry[channel]->note ); else fprintf(f, " ...");
770 if (dupentry[channel]->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", dupentry[channel]->instrument); else fprintf(f, " ...");
771 if (dupentry[channel]->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", dupentry[channel]->volpan ); else fprintf(f, " ...");
772 if (dupentry[channel]->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + dupentry[channel]->effect, dupentry[channel]->effectvalue); else fprintf(f, " ...\n");
773 fprintf(f, " Event #2:");
774 if (entry->mask & IT_ENTRY_NOTE ) fprintf(f, " %03d", entry->note ); else fprintf(f, " ...");
775 if (entry->mask & IT_ENTRY_INSTRUMENT) fprintf(f, " %03d", entry->instrument); else fprintf(f, " ...");
776 if (entry->mask & IT_ENTRY_VOLPAN ) fprintf(f, " %03d", entry->volpan ); else fprintf(f, " ...");
777 if (entry->mask & IT_ENTRY_EFFECT) fprintf(f, " %c%02X\n", 'A' - 1 + entry->effect, entry->effectvalue); else fprintf(f, " ...\n");
778 fclose(f);
779 }
780 dupentry[channel] = entry;
781#endif
782
783 entry++;
784 }
785 }
786
787 ASSERT(entry == pattern->entry + n_entries);
788
789 return 0;
790}
791
792
793
794/* Currently we assume the sample data are stored after the sample headers in
795 * module files. This assumption may be unjustified; let me know if you have
796 * trouble.
797 */
798
799#define IT_COMPONENT_INSTRUMENT 1
800#define IT_COMPONENT_PATTERN 2
801#define IT_COMPONENT_SAMPLE 3
802
803typedef struct IT_COMPONENT
804{
805 unsigned char type;
806 unsigned char n;
807 long offset;
808 short sampfirst; /* component[sampfirst] = first sample data after this */
809 short sampnext; /* sampnext is used to create linked lists of sample data */
810}
811IT_COMPONENT;
812
813
814
815static int it_component_compare(const void *e1, const void *e2)
816{
817 return ((const IT_COMPONENT *)e1)->offset -
818 ((const IT_COMPONENT *)e2)->offset;
819}
820
821
822
823static sigdata_t *it_load_sigdata(DUMBFILE *f)
824{
825 DUMB_IT_SIGDATA *sigdata;
826
827 int cwt, cmwt;
828 int special;
829
830 IT_COMPONENT *component;
831 int n_components = 0;
832
833 unsigned char sample_convert[256];
834
835 int n;
836
837 unsigned char *buffer;
838
839 if (dumbfile_mgetl(f) != IT_SIGNATURE)
840 return NULL;
841
842 sigdata = malloc(sizeof(*sigdata));
843
844 if (!sigdata)
845 return NULL;
846
847 sigdata->order = NULL;
848 sigdata->instrument = NULL;
849 sigdata->sample = NULL;
850 sigdata->pattern = NULL;
851 sigdata->midi = NULL;
852 sigdata->checkpoint = NULL;
853
854 /* Skip song name and pattern row highlight info. */
855 dumbfile_skip(f, 28);
856
857 sigdata->n_orders = dumbfile_igetw(f);
858 sigdata->n_instruments = dumbfile_igetw(f);
859 sigdata->n_samples = dumbfile_igetw(f);
860 sigdata->n_patterns = dumbfile_igetw(f);
861
862 cwt = dumbfile_igetw(f);
863 cmwt = dumbfile_igetw(f);
864
865 sigdata->flags = dumbfile_igetw(f);
866 special = dumbfile_igetw(f);
867
868 sigdata->global_volume = dumbfile_getc(f);
869 sigdata->mixing_volume = dumbfile_getc(f);
870 sigdata->speed = dumbfile_getc(f);
871 if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
872 sigdata->tempo = dumbfile_getc(f);
873 sigdata->pan_separation = dumbfile_getc(f); /** WARNING: use this */
874
875 /* Skip Pitch Wheel Depth, Message Length, Message Offset and Reserved. */
876 dumbfile_skip(f, 11);
877
878 dumbfile_getnc((char *)sigdata->channel_pan, DUMB_IT_N_CHANNELS, f);
879 dumbfile_getnc((char *)sigdata->channel_volume, DUMB_IT_N_CHANNELS, f);
880
881 if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) {
882 _dumb_it_unload_sigdata(sigdata);
883 return NULL;
884 }
885
886 sigdata->order = malloc(sigdata->n_orders);
887 if (!sigdata->order) {
888 _dumb_it_unload_sigdata(sigdata);
889 return NULL;
890 }
891
892 if (sigdata->n_instruments) {
893 sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
894 if (!sigdata->instrument) {
895 _dumb_it_unload_sigdata(sigdata);
896 return NULL;
897 }
898 }
899
900 if (sigdata->n_samples) {
901 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
902 if (!sigdata->sample) {
903 _dumb_it_unload_sigdata(sigdata);
904 return NULL;
905 }
906 for (n = 0; n < sigdata->n_samples; n++)
907 sigdata->sample[n].right = sigdata->sample[n].left = NULL;
908 }
909
910 if (sigdata->n_patterns) {
911 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
912 if (!sigdata->pattern) {
913 _dumb_it_unload_sigdata(sigdata);
914 return NULL;
915 }
916 for (n = 0; n < sigdata->n_patterns; n++)
917 sigdata->pattern[n].entry = NULL;
918 }
919
920 dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
921 sigdata->restart_position = 0;
922
923 component = malloc(768 * sizeof(*component));
924 if (!component) {
925 _dumb_it_unload_sigdata(sigdata);
926 return NULL;
927 }
928
929 for (n = 0; n < sigdata->n_instruments; n++) {
930 component[n_components].type = IT_COMPONENT_INSTRUMENT;
931 component[n_components].n = n;
932 component[n_components].offset = dumbfile_igetl(f);
933 component[n_components].sampfirst = -1;
934 n_components++;
935 }
936
937 for (n = 0; n < sigdata->n_samples; n++) {
938 component[n_components].type = IT_COMPONENT_SAMPLE;
939 component[n_components].n = n;
940 component[n_components].offset = dumbfile_igetl(f);
941 component[n_components].sampfirst = -1;
942 n_components++;
943 }
944
945 for (n = 0; n < sigdata->n_patterns; n++) {
946 long offset = dumbfile_igetl(f);
947 if (offset) {
948 component[n_components].type = IT_COMPONENT_PATTERN;
949 component[n_components].n = n;
950 component[n_components].offset = offset;
951 component[n_components].sampfirst = -1;
952 n_components++;
953 } else {
954 /* Empty 64-row pattern */
955 sigdata->pattern[n].n_rows = 64;
956 sigdata->pattern[n].n_entries = 0;
957 }
958 }
959
960 if (dumbfile_error(f)) {
961 free(component);
962 _dumb_it_unload_sigdata(sigdata);
963 return NULL;
964 }
965
966 if (!(sigdata->flags & 128) != !(special & 8)) {
967#if 0
968 fprintf(stderr, "Flags Bit 7 (\"Request embedded MIDI configuration\"): %s\n", sigdata->flags & 128 ? "=SET=" : "clear");
969 fprintf(stderr, "Special Bit 3 (\"MIDI configuration embedded\") : %s\n", special & 8 ? "=SET=" : "clear");
970 fprintf(stderr, "entheh would like to investigate this IT file.\n");
971 fprintf(stderr, "Please contact him! entheh@users.sf.net\n");
972#endif
973 }
974
975 if (special & 8) {
976 /* MIDI configuration is embedded. */
977 unsigned char mididata[32];
978 int i;
979 sigdata->midi = malloc(sizeof(*sigdata->midi));
980 if (!sigdata->midi) {
981 free(component);
982 _dumb_it_unload_sigdata(sigdata);
983 return NULL;
984 // Should we be happy with this outcome in some situations?
985 }
986 // What are we skipping?
987 i = dumbfile_igetw(f);
988 if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) {
989 free(component);
990 _dumb_it_unload_sigdata(sigdata);
991 return NULL;
992 }
993 /* Read embedded MIDI configuration */
994 // What are the first 9 commands for?
995 if (dumbfile_skip(f, 32*9)) {
996 free(component);
997 _dumb_it_unload_sigdata(sigdata);
998 return NULL;
999 }
1000 for (i = 0; i < 16; i++) {
1001 unsigned char len = 0;
1002 int j, leftdigit = -1;
1003 if (dumbfile_getnc((char *)mididata, 32, f) < 32) {
1004 free(component);
1005 _dumb_it_unload_sigdata(sigdata);
1006 return NULL;
1007 }
1008 sigdata->midi->SFmacroz[i] = 0;
1009 for (j = 0; j < 32; j++) {
1010 if (leftdigit >= 0) {
1011 if (mididata[j] == 0) {
1012 sigdata->midi->SFmacro[i][len++] = leftdigit;
1013 break;
1014 } else if (mididata[j] == ' ')
1015 sigdata->midi->SFmacro[i][len++] = leftdigit;
1016 else if (mididata[j] >= '0' && mididata[j] <= '9')
1017 sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0');
1018 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1019 sigdata->midi->SFmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA);
1020 leftdigit = -1;
1021 } else if (mididata[j] == 0)
1022 break;
1023 else if (mididata[j] == 'z')
1024 sigdata->midi->SFmacroz[i] |= 1 << len++;
1025 else if (mididata[j] >= '0' && mididata[j] <= '9')
1026 leftdigit = mididata[j] - '0';
1027 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1028 leftdigit = mididata[j] - 'A' + 0xA;
1029 }
1030 sigdata->midi->SFmacrolen[i] = len;
1031 }
1032 for (i = 0; i < 128; i++) {
1033 unsigned char len = 0;
1034 int j, leftdigit = -1;
1035 dumbfile_getnc((char *)mididata, 32, f);
1036 for (j = 0; j < 32; j++) {
1037 if (leftdigit >= 0) {
1038 if (mididata[j] == 0) {
1039 sigdata->midi->Zmacro[i][len++] = leftdigit;
1040 break;
1041 } else if (mididata[j] == ' ')
1042 sigdata->midi->Zmacro[i][len++] = leftdigit;
1043 else if (mididata[j] >= '0' && mididata[j] <= '9')
1044 sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - '0');
1045 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1046 sigdata->midi->Zmacro[i][len++] = (leftdigit << 4) | (mididata[j] - 'A' + 0xA);
1047 leftdigit = -1;
1048 } else if (mididata[j] == 0)
1049 break;
1050 else if (mididata[j] >= '0' && mididata[j] <= '9')
1051 leftdigit = mididata[j] - '0';
1052 else if (mididata[j] >= 'A' && mididata[j] <= 'F')
1053 leftdigit = mididata[j] - 'A' + 0xA;
1054 }
1055 sigdata->midi->Zmacrolen[i] = len;
1056 }
1057 }
1058
1059 sigdata->flags &= IT_REAL_FLAGS;
1060
1061 qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare);
1062
1063 buffer = malloc(65536);
1064 if (!buffer) {
1065 free(component);
1066 _dumb_it_unload_sigdata(sigdata);
1067 return NULL;
1068 }
1069
1070 for (n = 0; n < n_components; n++) {
1071 long offset;
1072 int m;
1073
1074 if (it_seek(f, component[n].offset)) {
1075 free(buffer);
1076 free(component);
1077 _dumb_it_unload_sigdata(sigdata);
1078 return NULL;
1079 }
1080
1081 switch (component[n].type) {
1082
1083 case IT_COMPONENT_INSTRUMENT:
1084 if (cmwt < 0x200)
1085 m = it_read_old_instrument(&sigdata->instrument[component[n].n], f);
1086 else
1087 m = it_read_instrument(&sigdata->instrument[component[n].n], f);
1088
1089 if (m) {
1090 free(buffer);
1091 free(component);
1092 _dumb_it_unload_sigdata(sigdata);
1093 return NULL;
1094 }
1095 break;
1096
1097 case IT_COMPONENT_PATTERN:
1098 if (it_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) {
1099 free(buffer);
1100 free(component);
1101 _dumb_it_unload_sigdata(sigdata);
1102 return NULL;
1103 }
1104 break;
1105
1106 case IT_COMPONENT_SAMPLE:
1107 if (it_read_sample_header(&sigdata->sample[component[n].n], &sample_convert[component[n].n], &offset, f)) {
1108 free(buffer);
1109 free(component);
1110 _dumb_it_unload_sigdata(sigdata);
1111 return NULL;
1112 }
1113
1114 if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) {
1115 short *sample;
1116
1117 for (m = n + 1; m < n_components; m++)
1118 if (component[m].offset > offset)
1119 break;
1120 m--;
1121
1122 sample = &component[m].sampfirst;
1123
1124 while (*sample >= 0 && component[*sample].offset <= offset)
1125 sample = &component[*sample].sampnext;
1126
1127 component[n].sampnext = *sample;
1128 *sample = n;
1129
1130 component[n].offset = offset;
1131 }
1132 }
1133
1134 m = component[n].sampfirst;
1135
1136 while (m >= 0) {
1137 if (it_seek(f, component[m].offset)) {
1138 free(buffer);
1139 free(component);
1140 _dumb_it_unload_sigdata(sigdata);
1141 return NULL;
1142 }
1143
1144 if (it_read_sample_data(cmwt, &sigdata->sample[component[m].n], sample_convert[component[m].n], f)) {
1145 free(buffer);
1146 free(component);
1147 _dumb_it_unload_sigdata(sigdata);
1148 return NULL;
1149 }
1150
1151 m = component[m].sampnext;
1152 }
1153 }
1154
1155 free(buffer);
1156 free(component);
1157
1158 _dumb_it_fix_invalid_orders(sigdata);
1159
1160 return sigdata;
1161}
1162
1163
1164
1165DUH *dumb_read_it(DUMBFILE *f)
1166{
1167 sigdata_t *sigdata;
1168 long length;
1169
1170 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
1171
1172 sigdata = it_load_sigdata(f);
1173
1174 if (!sigdata)
1175 return NULL;
1176
1177 length = _dumb_it_build_checkpoints(sigdata);
1178
1179 return make_duh(length, 1, &descptr, &sigdata);
1180}
1181
diff --git a/apps/codecs/dumb/src/it/itrender.c b/apps/codecs/dumb/src/it/itrender.c
deleted file mode 100644
index 103654fd77..0000000000
--- a/apps/codecs/dumb/src/it/itrender.c
+++ /dev/null
@@ -1,3512 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itrender.c - Code to render an Impulse Tracker / / \ \
12 * module. | < / \_
13 * | \/ /\ /
14 * Written - painstakingly - by entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <math.h>
21#include <stdlib.h>
22
23#include "dumb.h"
24#include "internal/it.h"
25
26
27
28static IT_PLAYING *dup_playing(IT_PLAYING *src, IT_CHANNEL *dstchannel, IT_CHANNEL *srcchannel)
29{
30 IT_PLAYING *dst;
31
32 if (!src) return NULL;
33
34 dst = malloc(sizeof(*dst));
35 if (!dst) return NULL;
36
37 dst->flags = src->flags;
38
39 ASSERT(src->channel);
40 dst->channel = &dstchannel[src->channel - srcchannel];
41 dst->sample = src->sample;
42 dst->instrument = src->instrument;
43 dst->env_instrument = src->env_instrument;
44
45 dst->sampnum = src->sampnum;
46 dst->instnum = src->instnum;
47
48 dst->channel_volume = src->channel_volume;
49
50 dst->volume = src->volume;
51 dst->pan = src->pan;
52
53 dst->note = src->note;
54
55 dst->filter_cutoff = src->filter_cutoff;
56 dst->filter_resonance = src->filter_resonance;
57
58 dst->true_filter_cutoff = src->true_filter_cutoff;
59 dst->true_filter_resonance = src->true_filter_resonance;
60
61 dst->vibrato_speed = src->vibrato_speed;
62 dst->vibrato_depth = src->vibrato_depth;
63 dst->vibrato_n = src->vibrato_n;
64 dst->vibrato_time = src->vibrato_time;
65
66 dst->tremolo_speed = src->tremolo_speed;
67 dst->tremolo_depth = src->tremolo_depth;
68 dst->tremolo_time = src->tremolo_time;
69
70 dst->sample_vibrato_time = src->sample_vibrato_time;
71 dst->sample_vibrato_depth = src->sample_vibrato_depth;
72
73 dst->slide = src->slide;
74 dst->delta = src->delta;
75
76 dst->volume_envelope = src->volume_envelope;
77 dst->pan_envelope = src->pan_envelope;
78 dst->pitch_envelope = src->pitch_envelope;
79
80 dst->fadeoutcount = src->fadeoutcount;
81
82 dst->filter_state[0] = src->filter_state[0];
83 dst->filter_state[1] = src->filter_state[1];
84
85 dst->resampler[0] = src->resampler[0];
86 dst->resampler[1] = src->resampler[1];
87 dst->resampler[1].pickup_data = dst->resampler[0].pickup_data = dst;
88 dst->time_lost = src->time_lost;
89
90 return dst;
91}
92
93
94
95static void dup_channel(IT_CHANNEL *dst, IT_CHANNEL *src)
96{
97 dst->flags = src->flags;
98
99 dst->volume = src->volume;
100 dst->volslide = src->volslide;
101 dst->xm_volslide = src->xm_volslide;
102
103 dst->pan = src->pan;
104 dst->truepan = src->truepan;
105
106 dst->channelvolume = src->channelvolume;
107 dst->channelvolslide = src->channelvolslide;
108
109 dst->instrument = src->instrument;
110 dst->note = src->note;
111
112 dst->SFmacro = src->SFmacro;
113
114 dst->filter_cutoff = src->filter_cutoff;
115 dst->filter_resonance = src->filter_resonance;
116
117 dst->note_cut_count = src->note_cut_count;
118 dst->note_delay_count = src->note_delay_count;
119 dst->note_delay_entry = src->note_delay_entry;
120
121 dst->arpeggio = src->arpeggio;
122 dst->retrig = src->retrig;
123 dst->xm_retrig = src->xm_retrig;
124 dst->retrig_tick = src->retrig_tick;
125
126 dst->tremor_time = src->tremor_time;
127
128 dst->portamento = src->portamento;
129 dst->toneporta = src->toneporta;
130 dst->destnote = src->destnote;
131
132 dst->sample = src->sample;
133 dst->truenote = src->truenote;
134
135 dst->midi_state = src->midi_state;
136
137 dst->lastvolslide = src->lastvolslide;
138 dst->lastDKL = src->lastDKL;
139 dst->lastEF = src->lastEF;
140 dst->lastG = src->lastG;
141 dst->lastHspeed = src->lastHspeed;
142 dst->lastHdepth = src->lastHdepth;
143 dst->lastRspeed = src->lastRspeed;
144 dst->lastRdepth = src->lastRdepth;
145 dst->lastI = src->lastI;
146 dst->lastJ = src->lastJ;
147 dst->lastN = src->lastN;
148 dst->lastO = src->lastO;
149 dst->high_offset = src->high_offset;
150 dst->lastQ = src->lastQ;
151 dst->lastS = src->lastS;
152 dst->pat_loop_row = src->pat_loop_row;
153 dst->pat_loop_count = src->pat_loop_count;
154 dst->lastW = src->lastW;
155
156 dst->xm_lastE1 = src->xm_lastE1;
157 dst->xm_lastE2 = src->xm_lastE2;
158 dst->xm_lastEA = src->xm_lastEA;
159 dst->xm_lastEB = src->xm_lastEB;
160 dst->xm_lastX1 = src->xm_lastX1;
161 dst->xm_lastX2 = src->xm_lastX2;
162
163 dst->playing = dup_playing(src->playing, dst, src);
164}
165
166
167
168/* Allocate the new callbacks first, then pass them to this function!
169 * It will free them on failure.
170 */
171static DUMB_IT_SIGRENDERER *dup_sigrenderer(DUMB_IT_SIGRENDERER *src, int n_channels, IT_CALLBACKS *callbacks)
172{
173 DUMB_IT_SIGRENDERER *dst;
174 int i;
175
176 if (!src) {
177 if (callbacks) free(callbacks);
178 return NULL;
179 }
180
181 dst = malloc(sizeof(*dst));
182 if (!dst) {
183 if (callbacks) free(callbacks);
184 return NULL;
185 }
186
187 dst->sigdata = src->sigdata;
188
189 dst->n_channels = n_channels;
190
191 dst->globalvolume = src->globalvolume;
192 dst->globalvolslide = src->globalvolslide;
193
194 dst->tempo = src->tempo;
195 dst->temposlide = src->temposlide;
196
197 for (i = 0; i < DUMB_IT_N_CHANNELS; i++)
198 dup_channel(&dst->channel[i], &src->channel[i]);
199
200 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
201 dst->playing[i] = dup_playing(src->playing[i], dst->channel, src->channel);
202
203 dst->tick = src->tick;
204 dst->speed = src->speed;
205 dst->rowcount = src->rowcount;
206
207 dst->order = src->order;
208 dst->row = src->row;
209 dst->processorder = src->processorder;
210 dst->processrow = src->processrow;
211 dst->breakrow = src->breakrow;
212 dst->pat_loop_row = src->pat_loop_row;
213
214 dst->n_rows = src->n_rows;
215
216 dst->entry_start = src->entry_start;
217 dst->entry = src->entry;
218 dst->entry_end = src->entry_end;
219
220 dst->time_left = src->time_left;
221 dst->sub_time_left = src->sub_time_left;
222
223 dst->click_remover = NULL;
224
225 dst->callbacks = callbacks;
226
227 return dst;
228}
229
230
231
232static IT_MIDI default_midi = {
233 /* unsigned char SFmacro[16][16]; */
234 {
235 {0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
236 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
237 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
238 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
239 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
240 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
241 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
242 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
243 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
244 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
245 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
246 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
247 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
248 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
249 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
250 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
251 },
252 /* unsigned char SFmacrolen[16]; */
253 {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
254 /* unsigned short SFmacroz[16]; */
255 /* Bitfield; bit 0 set = z in first position */
256 {
257 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
258 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
259 },
260 /* unsigned char Zmacro[128][16]; */
261 {
262 {0xF0, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
263 {0xF0, 0xF0, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
264 {0xF0, 0xF0, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
265 {0xF0, 0xF0, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
266 {0xF0, 0xF0, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
267 {0xF0, 0xF0, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
268 {0xF0, 0xF0, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
269 {0xF0, 0xF0, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
270 {0xF0, 0xF0, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
271 {0xF0, 0xF0, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
272 {0xF0, 0xF0, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
273 {0xF0, 0xF0, 0x01, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
274 {0xF0, 0xF0, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
275 {0xF0, 0xF0, 0x01, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
276 {0xF0, 0xF0, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
277 {0xF0, 0xF0, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
278
279 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
280 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
281 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
282 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
283 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
284 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
285 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
286 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
287 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
288 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
289 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
290 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
291 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
292 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
293 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
294 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
295
296 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
297 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
298 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
299 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
300 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
301 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
302 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
303 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
304 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
305 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
306 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
307 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
308 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
309 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
310 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
311 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
312
313 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
314 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
315 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
316 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
317 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
318 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
319 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
320 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
321 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
322 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
323 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
324 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
325 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
326 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
327 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
328 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
329
330 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
331 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
332 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
333 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
334 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
335 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
336 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
337 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
338 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
339 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
340 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
341 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
342 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
343 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
344 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
345 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
346
347 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
348 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
349 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
350 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
351 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
352 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
353 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
354 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
355 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
356 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
357 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
358 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
359 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
360 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
361 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
362 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
363
364 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
365 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
366 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
367 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
368 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
369 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
370 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
371 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
372 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
373 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
374 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
375 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
376 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
377 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
378 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
379 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
380
381 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
382 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
383 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
384 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
385 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
386 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
387 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
388 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
389 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
390 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
391 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
392 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
393 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
394 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
395 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
396 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
397 },
398 /* unsigned char Zmacrolen[128]; */
399 {
400 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
408 }
409};
410
411
412
413static void it_reset_filter_state(IT_FILTER_STATE *state)
414{
415 state->currsample = 0;
416 state->prevsample = 0;
417}
418
419
420
421#define LOG10 2.30258509299
422
423/* IMPORTANT: This function expects one extra sample in 'src' so it can apply
424 * click removal. It reads size samples, starting from src[0], and writes its
425 * output starting at dst[pos]. The pos parameter is required for getting
426 * click removal right.
427 */
428static void it_filter(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int sampfreq, int cutoff, int resonance)
429{
430 float currsample = state->currsample;
431 float prevsample = state->prevsample;
432
433 float a, b, c;
434
435 {
436 float inv_angle = (float)(sampfreq * pow(0.5, 0.25 + cutoff*(1.0/(24<<IT_ENVELOPE_SHIFT))) * (1.0/(2*3.14159265358979323846*110.0)));
437 float loss = (float)exp(resonance*(-LOG10*1.2/128.0));
438 float d, e;
439#if 0
440 loss *= 2; // This is the mistake most players seem to make!
441#endif
442
443#if 1
444 d = (1.0f - loss) / inv_angle;
445 if (d > 2.0f) d = 2.0f;
446 d = (loss - d) * inv_angle;
447 e = inv_angle * inv_angle;
448 a = 1.0f / (1.0f + d + e);
449 c = -e * a;
450 b = 1.0f - a - c;
451#else
452 a = 1.0f / (inv_angle*inv_angle + inv_angle*loss + loss);
453 c = -(inv_angle*inv_angle) * a;
454 b = 1.0f - a - c;
455#endif
456 }
457
458 dst += pos;
459
460 if (cr) {
461 float startstep = src[0]*a + currsample*b + prevsample*c;
462 dumb_record_click(cr, pos, (sample_t)startstep);
463 }
464
465#define INT_FILTERS
466#ifdef INT_FILTERS
467#define MULSCA(a, b) ((int)((LONG_LONG)((a) << 4) * (b) >> 32))
468#define SCALEB 12
469 {
470 int ai = (int)(a * (1 << (16+SCALEB)));
471 int bi = (int)(b * (1 << (16+SCALEB)));
472 int ci = (int)(c * (1 << (16+SCALEB)));
473 sample_t csi = (sample_t)currsample;
474 sample_t psi = (sample_t)prevsample;
475 sample_t *dst_end = dst + size;
476 while (dst < dst_end) {
477 {
478 sample_t nsi = MULSCA(*src++, ai) + MULSCA(csi, bi) + MULSCA(psi, ci);
479 psi = csi;
480 csi = nsi;
481 }
482 *dst++ += csi;
483 }
484 currsample = csi;
485 prevsample = psi;
486 }
487#else
488 {
489 int i = size % 3;
490 while (i > 0) {
491 {
492 float newsample = *src++*a + currsample*b + prevsample*c;
493 prevsample = currsample;
494 currsample = newsample;
495 }
496 *dst++ += (sample_t)currsample;
497 i--;
498 }
499 i = size / 3;
500 while (i > 0) {
501 float newsample;
502 /* Gotta love unrolled loops! */
503 *dst++ += (sample_t)(newsample = *src++*a + currsample*b + prevsample*c);
504 *dst++ += (sample_t)(prevsample = *src++*a + newsample*b + currsample*c);
505 *dst++ += (sample_t)(currsample = *src++*a + prevsample*b + newsample*c);
506 i--;
507 }
508 }
509#endif
510
511 if (cr) {
512 float endstep = *src*a + currsample*b + prevsample*c;
513 dumb_record_click(cr, pos + size, -(sample_t)endstep);
514 }
515
516 state->currsample = currsample;
517 state->prevsample = prevsample;
518}
519
520#undef LOG10
521
522
523
524static signed char it_sine[256] = {
525 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
526 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
527 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
528 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
529 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
530 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
531 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
532 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
533 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
534 -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
535 -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
536 -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
537 -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
538 -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
539 -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
540 -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2
541};
542
543
544
545#if 0
546/** WARNING: use these! */
547/** JULIEN: Plus for XM compatibility it could be interesting to rename
548 * it_sawtooth[] to it_rampdown[], and add an it_rampup[].
549 * Also, still for XM compat', twood be good if it was possible to tell the
550 * the player not to retrig' the waveform on a new instrument.
551 * Both of these are only for completness though, as I don't think it would
552 * be very noticeable ;)
553 */
554/** ENTHEH: IT also has the 'don't retrig' thingy :) */
555
556static signed char it_sawtooth[256] = {
557 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56,
558 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48,
559 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40,
560 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32,
561 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24,
562 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
563 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8,
564 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0,
565 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8,
566 -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16,
567 -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24,
568 -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32,
569 -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,
570 -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48,
571 -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56,
572 -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64
573};
574
575
576
577static signed char it_squarewave[256] = {
578 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
579 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
580 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
581 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
582 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
583 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
584 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
585 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
586 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
587 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
588 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
589 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
590 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
591 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
594};
595
596#endif
597
598
599
600static void reset_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
601{
602 int i;
603
604 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
605 IT_CHANNEL *channel = &sigrenderer->channel[i];
606 channel->note_cut_count = 0;
607 channel->note_delay_count = 0;
608 }
609}
610
611
612
613static void reset_effects(DUMB_IT_SIGRENDERER *sigrenderer)
614{
615 int i;
616
617 sigrenderer->globalvolslide = 0;
618 sigrenderer->temposlide = 0;
619
620 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
621 IT_CHANNEL *channel = &sigrenderer->channel[i];
622 channel->volslide = 0;
623 channel->xm_volslide = 0;
624 channel->channelvolslide = 0;
625 channel->arpeggio = 0;
626 channel->retrig = 0;
627 if (channel->xm_retrig) {
628 channel->xm_retrig = 0;
629 channel->retrig_tick = 0;
630 }
631 channel->tremor_time &= 127;
632 channel->portamento = 0;
633 channel->toneporta = 0;
634 if (channel->playing) {
635 channel->playing->vibrato_n = 0;
636 channel->playing->tremolo_speed = 0;
637 channel->playing->tremolo_depth = 0;
638 }
639 }
640}
641
642
643
644static void update_tremor(IT_CHANNEL *channel)
645{
646 if ((channel->tremor_time & 128) && channel->playing) {
647 if (channel->tremor_time == 128)
648 channel->tremor_time = (channel->lastI >> 4) | 192;
649 else if (channel->tremor_time == 192)
650 channel->tremor_time = (channel->lastI & 15) | 128;
651 else
652 channel->tremor_time--;
653 }
654}
655
656
657
658static void it_pickup_loop(DUMB_RESAMPLER *resampler, void *data)
659{
660 resampler->pos -= resampler->end - resampler->start;
661 ((IT_PLAYING *)data)->time_lost += resampler->end - resampler->start;
662}
663
664
665
666static void it_pickup_pingpong_loop(DUMB_RESAMPLER *resampler, void *data)
667{
668 if (resampler->dir < 0) {
669 resampler->pos = (resampler->start << 1) - 1 - resampler->pos;
670 resampler->subpos ^= 65535;
671 resampler->dir = 1;
672 ((IT_PLAYING *)data)->time_lost += (resampler->end - resampler->start) << 1;
673 } else {
674 resampler->pos = (resampler->end << 1) - 1 - resampler->pos;
675 resampler->subpos ^= 65535;
676 resampler->dir = -1;
677 }
678}
679
680
681
682static void it_pickup_stop_at_end(DUMB_RESAMPLER *resampler, void *data)
683{
684 (void)data;
685
686 if (resampler->dir < 0) {
687 resampler->pos = (resampler->start << 1) - 1 - resampler->pos;
688 resampler->subpos ^= 65535;
689 /* By rights, time_lost would be updated here. However, there is no
690 * need at this point; it will not be used.
691 *
692 * ((IT_PLAYING *)data)->time_lost += (resampler->src_end - resampler->src_start) << 1;
693 */
694 resampler->dir = 1;
695 } else
696 resampler->dir = 0;
697}
698
699
700
701static void it_playing_update_resamplers(IT_PLAYING *playing)
702{
703 if ((playing->sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) {
704 playing->resampler[0].start = playing->sample->sus_loop_start;
705 playing->resampler[0].end = playing->sample->sus_loop_end;
706 if (playing->sample->flags & IT_SAMPLE_PINGPONG_SUS_LOOP)
707 playing->resampler[0].pickup = &it_pickup_pingpong_loop;
708 else
709 playing->resampler[0].pickup = &it_pickup_loop;
710 } else if (playing->sample->flags & IT_SAMPLE_LOOP) {
711 playing->resampler[0].start = playing->sample->loop_start;
712 playing->resampler[0].end = playing->sample->loop_end;
713 if (playing->sample->flags & IT_SAMPLE_PINGPONG_LOOP)
714 playing->resampler[0].pickup = &it_pickup_pingpong_loop;
715 else
716 playing->resampler[0].pickup = &it_pickup_loop;
717 } else {
718 if (playing->sample->flags & IT_SAMPLE_SUS_LOOP)
719 playing->resampler[0].start = playing->sample->sus_loop_start;
720 else
721 playing->resampler[0].start = 0;
722 playing->resampler[0].end = playing->sample->length;
723 playing->resampler[0].pickup = &it_pickup_stop_at_end;
724 }
725 playing->resampler[1].start = playing->resampler[0].start;
726 playing->resampler[1].end = playing->resampler[0].end;
727 playing->resampler[1].pickup = playing->resampler[0].pickup;
728 ASSERT(playing->resampler[0].pickup_data == playing);
729 ASSERT(playing->resampler[1].pickup_data == playing);
730}
731
732
733
734/* This should be called whenever the sample or sample position changes. */
735static void it_playing_reset_resamplers(IT_PLAYING *playing, long pos)
736{
737 dumb_reset_resampler(&playing->resampler[0], playing->sample->left, pos, 0, 0);
738 dumb_reset_resampler(&playing->resampler[1], playing->sample->right, pos, 0, 0);
739 playing->resampler[1].pickup_data = playing->resampler[0].pickup_data = playing;
740 playing->time_lost = 0;
741 playing->flags &= ~IT_PLAYING_DEAD;
742 it_playing_update_resamplers(playing);
743}
744
745
746
747static void update_retrig(IT_CHANNEL *channel)
748{
749 if (channel->xm_retrig) {
750 channel->retrig_tick--;
751 if (channel->retrig_tick <= 0) {
752 if (channel->playing) it_playing_reset_resamplers(channel->playing, 0);
753 channel->retrig_tick = channel->xm_retrig;
754 }
755 } else if (channel->retrig & 0x0F) {
756 channel->retrig_tick--;
757 if (channel->retrig_tick <= 0) {
758 if (channel->retrig < 0x10) {
759 } else if (channel->retrig < 0x20) {
760 channel->volume--;
761 if (channel->volume > 64) channel->volume = 0;
762 } else if (channel->retrig < 0x30) {
763 channel->volume -= 2;
764 if (channel->volume > 64) channel->volume = 0;
765 } else if (channel->retrig < 0x40) {
766 channel->volume -= 4;
767 if (channel->volume > 64) channel->volume = 0;
768 } else if (channel->retrig < 0x50) {
769 channel->volume -= 8;
770 if (channel->volume > 64) channel->volume = 0;
771 } else if (channel->retrig < 0x60) {
772 channel->volume -= 16;
773 if (channel->volume > 64) channel->volume = 0;
774 } else if (channel->retrig < 0x70) {
775 channel->volume <<= 1;
776 channel->volume /= 3;
777 } else if (channel->retrig < 0x80) {
778 channel->volume >>= 1;
779 } else if (channel->retrig < 0x90) {
780 } else if (channel->retrig < 0xA0) {
781 channel->volume++;
782 if (channel->volume > 64) channel->volume = 64;
783 } else if (channel->retrig < 0xB0) {
784 channel->volume += 2;
785 if (channel->volume > 64) channel->volume = 64;
786 } else if (channel->retrig < 0xC0) {
787 channel->volume += 4;
788 if (channel->volume > 64) channel->volume = 64;
789 } else if (channel->retrig < 0xD0) {
790 channel->volume += 8;
791 if (channel->volume > 64) channel->volume = 64;
792 } else if (channel->retrig < 0xE0) {
793 channel->volume += 16;
794 if (channel->volume > 64) channel->volume = 64;
795 } else if (channel->retrig < 0xF0) {
796 channel->volume *= 3;
797 channel->volume >>= 1;
798 if (channel->volume > 64) channel->volume = 64;
799 } else {
800 channel->volume <<= 1;
801 if (channel->volume > 64) channel->volume = 64;
802 }
803 if (channel->playing) it_playing_reset_resamplers(channel->playing, 0);
804 channel->retrig_tick = channel->retrig & 0x0F;
805 }
806 }
807}
808
809
810
811static void update_smooth_effects(DUMB_IT_SIGRENDERER *sigrenderer)
812{
813 int i;
814
815 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
816 IT_CHANNEL *channel = &sigrenderer->channel[i];
817 IT_PLAYING *playing = channel->playing;
818
819 if (playing) {
820 playing->vibrato_time += playing->vibrato_n *
821 (playing->vibrato_speed << 2);
822 playing->tremolo_time += playing->tremolo_speed << 2;
823 }
824 }
825}
826
827
828
829static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer)
830{
831 int i;
832
833 if (sigrenderer->globalvolslide) {
834 sigrenderer->globalvolume += sigrenderer->globalvolslide;
835 if (sigrenderer->globalvolume > 128) {
836 if (sigrenderer->globalvolslide >= 0)
837 sigrenderer->globalvolume = 128;
838 else
839 sigrenderer->globalvolume = 0;
840 }
841 }
842
843 if (sigrenderer->temposlide) {
844 sigrenderer->tempo += sigrenderer->temposlide;
845 if (sigrenderer->tempo < 32) {
846 if (sigrenderer->temposlide >= 0)
847 sigrenderer->tempo = 255;
848 else
849 sigrenderer->tempo = 32;
850 }
851 }
852
853 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
854 IT_CHANNEL *channel = &sigrenderer->channel[i];
855 IT_PLAYING *playing = channel->playing;
856
857 if (channel->xm_volslide) {
858 channel->volume += channel->xm_volslide;
859 if (channel->volume > 64) {
860 if (channel->xm_volslide >= 0)
861 channel->volume = 64;
862 else
863 channel->volume = 0;
864 }
865 }
866
867 if (channel->volslide) {
868 channel->volume += channel->volslide;
869 if (channel->volume > 64) {
870 if (channel->volslide >= 0)
871 channel->volume = 64;
872 else
873 channel->volume = 0;
874 }
875 }
876
877 if (channel->channelvolslide) {
878 channel->channelvolume += channel->channelvolslide;
879 if (channel->channelvolume > 64) {
880 if (channel->channelvolslide >= 0)
881 channel->channelvolume = 64;
882 else
883 channel->channelvolume = 0;
884 }
885 if (channel->playing)
886 channel->playing->channel_volume = channel->channelvolume;
887 }
888
889 update_tremor(channel);
890
891 channel->arpeggio = (channel->arpeggio << 4) | (channel->arpeggio >> 8);
892 channel->arpeggio &= 0xFFF;
893
894 update_retrig(channel);
895
896 if (playing) {
897 playing->slide += channel->portamento;
898
899 if (sigrenderer->sigdata->flags & IT_LINEAR_SLIDES) {
900 if (channel->toneporta && channel->destnote < 120) {
901 int currpitch = ((playing->note - 60) << 8) + playing->slide;
902 int destpitch = (channel->destnote - 60) << 8;
903 if (currpitch > destpitch) {
904 currpitch -= channel->toneporta;
905 if (currpitch < destpitch) {
906 currpitch = destpitch;
907 channel->destnote = IT_NOTE_OFF;
908 }
909 } else if (currpitch < destpitch) {
910 currpitch += channel->toneporta;
911 if (currpitch > destpitch) {
912 currpitch = destpitch;
913 channel->destnote = IT_NOTE_OFF;
914 }
915 }
916 playing->slide = currpitch - ((playing->note - 60) << 8);
917 }
918 } else {
919 if (channel->toneporta && channel->destnote < 120) {
920 float amiga_multiplier = playing->sample->C5_speed * (1.0f / AMIGA_DIVISOR);
921
922 float deltanote = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note);
923 /* deltanote is 1.0 for C-5, 0.5 for C-6, etc. */
924
925 float deltaslid = deltanote - playing->slide * amiga_multiplier;
926
927 float destdelta = (float)pow(DUMB_SEMITONE_BASE, 60 - channel->destnote);
928 if (deltaslid < destdelta) {
929 playing->slide -= channel->toneporta;
930 deltaslid = deltanote - playing->slide * amiga_multiplier;
931 if (deltaslid > destdelta) {
932 playing->note = channel->destnote;
933 playing->slide = 0;
934 channel->destnote = IT_NOTE_OFF;
935 }
936 } else {
937 playing->slide += channel->toneporta;
938 deltaslid = deltanote - playing->slide * amiga_multiplier;
939 if (deltaslid < destdelta) {
940 playing->note = channel->destnote;
941 playing->slide = 0;
942 channel->destnote = IT_NOTE_OFF;
943 }
944 }
945 }
946 }
947 }
948 }
949
950 update_smooth_effects(sigrenderer);
951}
952
953
954
955static void update_pattern_variables(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
956{
957 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
958
959 if (entry->mask & IT_ENTRY_EFFECT) {
960 if (entry->effect == IT_S) {
961 unsigned char effectvalue = entry->effectvalue;
962 if (effectvalue == 0)
963 effectvalue = channel->lastS;
964 channel->lastS = effectvalue;
965 switch (effectvalue >> 4) {
966 //case IT_S7:
967 case IT_S_PATTERN_LOOP:
968 {
969 unsigned char v = effectvalue & 15;
970 if (v == 0)
971 channel->pat_loop_row = sigrenderer->processrow;
972 else {
973 if (channel->pat_loop_count == 0) {
974 channel->pat_loop_count = v;
975 sigrenderer->pat_loop_row = channel->pat_loop_row;
976 } else {
977 if (--channel->pat_loop_count)
978 sigrenderer->pat_loop_row = channel->pat_loop_row;
979 else if (!(sigrenderer->sigdata->flags & IT_WAS_AN_XM))
980 channel->pat_loop_row = sigrenderer->processrow + 1;
981 }
982 }
983 }
984 break;
985 case IT_S_PATTERN_DELAY:
986 sigrenderer->rowcount = 1 + (effectvalue & 15);
987 break;
988 }
989 }
990 }
991}
992
993
994
995/* This function guarantees that channel->sample will always be valid if it
996 * is nonzero. In other words, to check if it is valid, simply check if it is
997 * nonzero.
998 */
999static void instrument_to_sample(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1000{
1001 if (sigdata->flags & IT_USE_INSTRUMENTS) {
1002 if (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments) {
1003 if (channel->note < 120) {
1004 channel->sample = sigdata->instrument[channel->instrument-1].map_sample[channel->note];
1005 channel->truenote = sigdata->instrument[channel->instrument-1].map_note[channel->note];
1006 } else
1007 channel->sample = 0;
1008 } else
1009 channel->sample = 0;
1010 } else {
1011 channel->sample = channel->instrument;
1012 channel->truenote = channel->note;
1013 }
1014 if (!(channel->sample >= 1 && channel->sample <= sigdata->n_samples && (sigdata->sample[channel->sample-1].flags & IT_SAMPLE_EXISTS)))
1015 channel->sample = 0;
1016}
1017
1018
1019
1020static void fix_sample_looping(IT_PLAYING *playing)
1021{
1022 if ((playing->sample->flags & (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) ==
1023 (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP)) {
1024 if (playing->resampler[0].dir < 0) {
1025 playing->resampler[1].pos = playing->resampler[0].pos = (playing->sample->sus_loop_end << 1) - 1 - playing->resampler[0].pos;
1026 playing->resampler[1].subpos = playing->resampler[0].subpos ^= 65535;
1027 playing->resampler[1].dir = playing->resampler[0].dir = 1;
1028 }
1029
1030 playing->resampler[1].pos = playing->resampler[0].pos += playing->time_lost;
1031 }
1032}
1033
1034
1035
1036static void retrigger_it_envelopes(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1037{
1038 channel->playing->volume_envelope.next_node = 0;
1039 channel->playing->volume_envelope.tick = -1;
1040 channel->playing->pan_envelope.next_node = 0;
1041 channel->playing->pan_envelope.tick = -1;
1042 channel->playing->pitch_envelope.next_node = 0;
1043 channel->playing->pitch_envelope.tick = -1;
1044 channel->playing->fadeoutcount = 1024;
1045 // Should we remove IT_PLAYING_BACKGROUND? Test with sample with sustain loop...
1046 channel->playing->flags &= ~(IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING | IT_PLAYING_DEAD);
1047 it_playing_update_resamplers(channel->playing);
1048
1049 if (channel->sample)
1050 if (sigdata->flags & IT_USE_INSTRUMENTS)
1051 channel->playing->env_instrument = &sigdata->instrument[channel->instrument-1];
1052}
1053
1054
1055
1056static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel)
1057{
1058 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
1059 unsigned char nna;
1060 int i;
1061
1062 if (channel->playing) {
1063#ifdef INVALID_NOTES_CAUSE_NOTE_CUT
1064 if (channel->note == IT_NOTE_OFF)
1065 nna = NNA_NOTE_OFF;
1066 else if (channel->note >= 120 || !channel->playing->instrument || (channel->playing->flags & IT_PLAYING_DEAD))
1067 nna = NNA_NOTE_CUT;
1068 else
1069 nna = channel->playing->instrument->new_note_action;
1070#else
1071 if (channel->note == IT_NOTE_CUT)
1072 nna = NNA_NOTE_CUT;
1073 if (channel->note >= 120)
1074 nna = NNA_NOTE_OFF;
1075 else if (!channel->playing->instrument || (channel->playing->flags & IT_PLAYING_DEAD))
1076 nna = NNA_NOTE_CUT;
1077 else
1078 nna = channel->playing->instrument->new_note_action;
1079#endif
1080
1081 switch (nna) {
1082 case NNA_NOTE_CUT:
1083 free(channel->playing);
1084 channel->playing = NULL;
1085 break;
1086 case NNA_NOTE_OFF:
1087 channel->playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_SUSTAINOFF;
1088 fix_sample_looping(channel->playing);
1089 it_playing_update_resamplers(channel->playing);
1090 if (channel->playing->instrument)
1091 if ((channel->playing->instrument->volume_envelope.flags & (IT_ENVELOPE_ON | IT_ENVELOPE_LOOP_ON)) != IT_ENVELOPE_ON)
1092 channel->playing->flags |= IT_PLAYING_FADING;
1093 break;
1094 case NNA_NOTE_FADE:
1095 channel->playing->flags |= IT_PLAYING_BACKGROUND | IT_PLAYING_FADING;
1096 break;
1097 }
1098 }
1099
1100 if (channel->sample == 0 || channel->note >= 120)
1101 return;
1102
1103 channel->destnote = IT_NOTE_OFF;
1104
1105 if (channel->playing) {
1106 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1107 if (!sigrenderer->playing[i]) {
1108 sigrenderer->playing[i] = channel->playing;
1109 channel->playing = NULL;
1110 break;
1111 }
1112 }
1113/** WARNING - come up with some more heuristics for replacing old notes */
1114#if 0
1115 if (channel->playing) {
1116 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
1117 if (sigrenderer->playing[i]->flags & IT_PLAYING_BACKGROUND) {
1118 write_seqtime();
1119 sequence_c(SEQUENCE_STOP_SIGNAL);
1120 sequence_c(i);
1121 channel->VChannel = &module->VChannel[i];
1122 break;
1123 }
1124 }
1125 }
1126#endif
1127 }
1128
1129 if (channel->playing)
1130 free(channel->playing);
1131
1132 channel->playing = malloc(sizeof(*channel->playing));
1133
1134 if (!channel->playing)
1135 return;
1136
1137 channel->playing->flags = 0;
1138 channel->playing->channel = channel;
1139 channel->playing->sample = &sigdata->sample[channel->sample-1];
1140 if (sigdata->flags & IT_USE_INSTRUMENTS)
1141 channel->playing->instrument = &sigdata->instrument[channel->instrument-1];
1142 else
1143 channel->playing->instrument = NULL;
1144 channel->playing->env_instrument = channel->playing->instrument;
1145 channel->playing->sampnum = channel->sample;
1146 channel->playing->instnum = channel->instrument;
1147 channel->playing->channel_volume = channel->channelvolume;
1148 channel->playing->note = channel->truenote;
1149 channel->playing->filter_cutoff = 127;
1150 channel->playing->filter_resonance = 0;
1151 channel->playing->true_filter_cutoff = 127 << 8;
1152 channel->playing->true_filter_resonance = 0;
1153 channel->playing->vibrato_speed = 0;
1154 channel->playing->vibrato_depth = 0;
1155 channel->playing->vibrato_n = 0;
1156 channel->playing->vibrato_time = 0;
1157 channel->playing->tremolo_speed = 0;
1158 channel->playing->tremolo_depth = 0;
1159 channel->playing->tremolo_time = 0;
1160 channel->playing->sample_vibrato_time = 0;
1161 channel->playing->sample_vibrato_depth = 0;
1162 channel->playing->slide = 0;
1163 channel->playing->volume_envelope.next_node = 0;
1164 channel->playing->volume_envelope.tick = -1;
1165 channel->playing->pan_envelope.next_node = 0;
1166 channel->playing->pan_envelope.tick = -1;
1167 channel->playing->pitch_envelope.next_node = 0;
1168 channel->playing->pitch_envelope.tick = -1;
1169 channel->playing->fadeoutcount = 1024;
1170 it_reset_filter_state(&channel->playing->filter_state[0]);
1171 it_reset_filter_state(&channel->playing->filter_state[1]);
1172 it_playing_reset_resamplers(channel->playing, 0);
1173
1174 /** WARNING - is everything initialised? */
1175}
1176
1177
1178
1179static void get_default_volpan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1180{
1181 if (channel->sample == 0)
1182 return;
1183
1184 channel->volume = sigdata->sample[channel->sample-1].default_volume;
1185
1186 {
1187 int pan = sigdata->sample[channel->sample-1].default_pan;
1188 if (pan >= 128 && pan <= 192) {
1189 channel->pan = pan - 128;
1190 return;
1191 }
1192 }
1193
1194 if (sigdata->flags & IT_USE_INSTRUMENTS) {
1195 IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1];
1196 if (instrument->default_pan <= 64)
1197 channel->pan = instrument->default_pan;
1198 if (instrument->filter_cutoff >= 128)
1199 channel->filter_cutoff = instrument->filter_cutoff - 128;
1200 if (instrument->filter_resonance >= 128)
1201 channel->filter_resonance = instrument->filter_resonance - 128;
1202 }
1203}
1204
1205
1206
1207static void get_true_pan(DUMB_IT_SIGDATA *sigdata, IT_CHANNEL *channel)
1208{
1209 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1210
1211 if (!IT_IS_SURROUND_SHIFTED(channel->truepan) && (sigdata->flags & IT_USE_INSTRUMENTS)) {
1212 IT_INSTRUMENT *instrument = &sigdata->instrument[channel->instrument-1];
1213 int truepan = channel->truepan;
1214 truepan += (channel->note - instrument->pp_centre) * instrument->pp_separation << (IT_ENVELOPE_SHIFT - 3);
1215 channel->truepan = MID(0, truepan, 64 << IT_ENVELOPE_SHIFT);
1216 }
1217}
1218
1219
1220
1221static void post_process_it_volpan(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
1222{
1223 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
1224
1225 if (entry->mask & IT_ENTRY_VOLPAN) {
1226 if (entry->volpan <= 84) {
1227 /* Volume */
1228 /* Fine volume slide up */
1229 /* Fine volume slide down */
1230 } else if (entry->volpan <= 94) {
1231 /* Volume slide up */
1232 unsigned char v = entry->volpan - 85;
1233 if (v == 0)
1234 v = channel->lastvolslide;
1235 channel->lastvolslide = v;
1236 /* = effect Dx0 where x == entry->volpan - 85 */
1237 channel->volslide = v;
1238 } else if (entry->volpan <= 104) {
1239 /* Volume slide down */
1240 unsigned char v = entry->volpan - 95;
1241 if (v == 0)
1242 v = channel->lastvolslide;
1243 channel->lastvolslide = v;
1244 /* = effect D0x where x == entry->volpan - 95 */
1245 channel->volslide = -v;
1246 } else if (entry->volpan <= 114) {
1247 /* Portamento down */
1248 unsigned char v = (entry->volpan - 105) << 2;
1249 if (v == 0)
1250 v = channel->lastEF;
1251 channel->lastEF = v;
1252 channel->portamento -= v << 4;
1253 } else if (entry->volpan <= 124) {
1254 /* Portamento up */
1255 unsigned char v = (entry->volpan - 115) << 2;
1256 if (v == 0)
1257 v = channel->lastEF;
1258 channel->lastEF = v;
1259 channel->portamento += v << 4;
1260 } else if (entry->volpan <= 202) {
1261 /* Pan */
1262 /* Tone Portamento */
1263 } else if (entry->volpan <= 212) {
1264 /* Vibrato */
1265 unsigned char v = entry->volpan - 203;
1266 if (v == 0)
1267 v = channel->lastHdepth;
1268 else {
1269 v <<= 2;
1270 channel->lastHdepth = v;
1271 }
1272 if (channel->playing) {
1273 channel->playing->vibrato_speed = channel->lastHspeed;
1274 channel->playing->vibrato_depth = v;
1275 channel->playing->vibrato_n++;
1276 }
1277 }
1278 }
1279}
1280
1281
1282
1283static void it_send_midi(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel, unsigned char byte)
1284{
1285 if (sigrenderer->callbacks->midi)
1286 if ((*sigrenderer->callbacks->midi)(sigrenderer->callbacks->midi_data, channel - sigrenderer->channel, byte))
1287 return;
1288
1289 switch (channel->midi_state) {
1290 case 4: /* Ready to receive resonance parameter */
1291 if (byte < 0x80) channel->filter_resonance = byte;
1292 channel->midi_state = 0;
1293 break;
1294 case 3: /* Ready to receive cutoff parameter */
1295 if (byte < 0x80) channel->filter_cutoff = byte;
1296 channel->midi_state = 0;
1297 break;
1298 case 2: /* Ready for byte specifying which parameter will follow */
1299 if (byte == 0) /* Cutoff */
1300 channel->midi_state = 3;
1301 else if (byte == 1) /* Resonance */
1302 channel->midi_state = 4;
1303 else
1304 channel->midi_state = 0;
1305 break;
1306 default: /* Counting initial F0 bytes */
1307 switch (byte) {
1308 case 0xF0:
1309 channel->midi_state++;
1310 break;
1311 case 0xFA:
1312 case 0xFC:
1313 case 0xFF:
1314 /* Reset filter parameters for all channels */
1315 {
1316 int i;
1317 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
1318 sigrenderer->channel[i].filter_cutoff = 127;
1319 sigrenderer->channel[i].filter_resonance = 0;
1320 //// should we be resetting channel[i].playing->filter_* here?
1321 }
1322 }
1323 /* Fall through */
1324 default:
1325 channel->midi_state = 0;
1326 break;
1327 }
1328 }
1329}
1330
1331
1332
1333/* Returns 1 if a callback caused termination of playback. */
1334static int process_effects(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
1335{
1336 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
1337
1338 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
1339
1340 if (entry->mask & IT_ENTRY_EFFECT) {
1341 switch (entry->effect) {
1342/*
1343Notes about effects (as compared to other module formats)
1344
1345C This is now in *HEX*. (Used to be in decimal in ST3)
1346E/F/G/H/U You need to check whether the song uses Amiga/Linear slides.
1347H/U Vibrato in Impulse Tracker is two times finer than in
1348 any other tracker and is updated EVERY tick.
1349 If "Old Effects" is *ON*, then the vibrato is played in the
1350 normal manner (every non-row tick and normal depth)
1351E/F/G These commands ALL share the same memory.
1352Oxx Offsets to samples are to the 'xx00th' SAMPLE. (ie. for
1353 16 bit samples, the offset is xx00h*2)
1354 Oxx past the sample end will be ignored, unless "Old Effects"
1355 is ON, in which case the Oxx will play from the end of the
1356 sample.
1357Yxy This uses a table 4 times larger (hence 4 times slower) than
1358 vibrato or tremelo. If the waveform is set to random, then
1359 the 'speed' part of the command is interpreted as a delay.
1360*/
1361 case IT_SET_SPEED:
1362 if (entry->effectvalue)
1363 sigrenderer->tick = sigrenderer->speed = entry->effectvalue;
1364 else if (sigdata->flags & IT_WAS_AN_XM) {
1365 sigrenderer->speed = 0;
1366 if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
1367 return 1;
1368 }
1369 break;
1370
1371 case IT_JUMP_TO_ORDER: sigrenderer->processorder = entry->effectvalue - 1; sigrenderer->processrow = 0xFFFE; break;
1372 case IT_BREAK_TO_ROW: sigrenderer->breakrow = entry->effectvalue; sigrenderer->processrow = 0xFFFE; break;
1373
1374 case IT_VOLSLIDE_VIBRATO:
1375 if (channel->playing) {
1376 channel->playing->vibrato_speed = channel->lastHspeed;
1377 channel->playing->vibrato_depth = channel->lastHdepth;
1378 channel->playing->vibrato_n++;
1379 }
1380 /* Fall through and process volume slide. */
1381 case IT_VOLUME_SLIDE:
1382 case IT_VOLSLIDE_TONEPORTA:
1383 /* The tone portamento component is handled elsewhere. */
1384 {
1385 unsigned char v = entry->effectvalue;
1386 if (!(sigdata->flags & IT_WAS_A_MOD)) {
1387 if (v == 0)
1388 v = channel->lastDKL;
1389 channel->lastDKL = v;
1390 }
1391 if ((v & 0x0F) == 0) { /* Dx0 */
1392 channel->volslide = v >> 4;
1393 if (channel->volslide == 15 && !(sigdata->flags & IT_WAS_AN_XM)) {
1394 channel->volume += 15;
1395 if (channel->volume > 64) channel->volume = 64;
1396 }
1397 } else if ((v & 0xF0) == 0) { /* D0x */
1398 channel->volslide = -v;
1399 if (channel->volslide == -15 && !(sigdata->flags & IT_WAS_AN_XM)) {
1400 channel->volume -= 15;
1401 if (channel->volume > 64) channel->volume = 0;
1402 }
1403 } else if ((v & 0x0F) == 0x0F) { /* DxF */
1404 channel->volume += v >> 4;
1405 if (channel->volume > 64) channel->volume = 64;
1406 } else if ((v & 0xF0) == 0xF0) { /* DFx */
1407 channel->volume -= v & 15;
1408 if (channel->volume > 64) channel->volume = 0;
1409 }
1410 }
1411 break;
1412 case IT_XM_FINE_VOLSLIDE_DOWN:
1413 {
1414 unsigned char v = entry->effectvalue;
1415 if (v == 0)
1416 v = channel->xm_lastEB;
1417 channel->xm_lastEB = v;
1418 channel->volume -= v;
1419 if (channel->volume > 64) channel->volume = 0;
1420 }
1421 break;
1422 case IT_XM_FINE_VOLSLIDE_UP:
1423 {
1424 unsigned char v = entry->effectvalue;
1425 if (v == 0)
1426 v = channel->xm_lastEA;
1427 channel->xm_lastEA = v;
1428 channel->volume += v;
1429 if (channel->volume > 64) channel->volume = 64;
1430 }
1431 break;
1432 case IT_PORTAMENTO_DOWN:
1433 {
1434 unsigned char v = entry->effectvalue;
1435 if (sigdata->flags & IT_WAS_AN_XM) {
1436 if (!(sigdata->flags & IT_WAS_A_MOD)) {
1437 if (v == 0xF0)
1438 v |= channel->xm_lastE2;
1439 else if (v >= 0xF0)
1440 channel->xm_lastE2 = v & 15;
1441 else if (v == 0xE0)
1442 v |= channel->xm_lastX2;
1443 else
1444 channel->xm_lastX2 = v & 15;
1445 }
1446 } else {
1447 if (v == 0)
1448 v = channel->lastEF;
1449 channel->lastEF = v;
1450 }
1451 if (channel->playing) {
1452 if ((v & 0xF0) == 0xF0)
1453 channel->playing->slide -= (v & 15) << 4;
1454 else if ((v & 0xF0) == 0xE0)
1455 channel->playing->slide -= (v & 15) << 2;
1456 else
1457 channel->portamento -= v << 4;
1458 }
1459 }
1460 break;
1461 case IT_PORTAMENTO_UP:
1462 {
1463 unsigned char v = entry->effectvalue;
1464 if (sigdata->flags & IT_WAS_AN_XM) {
1465 if (!(sigdata->flags & IT_WAS_A_MOD)) {
1466 if (v == 0xF0)
1467 v |= channel->xm_lastE1;
1468 else if (v >= 0xF0)
1469 channel->xm_lastE1 = v & 15;
1470 else if (v == 0xE0)
1471 v |= channel->xm_lastX1;
1472 else
1473 channel->xm_lastX1 = v & 15;
1474 }
1475 } else {
1476 if (v == 0)
1477 v = channel->lastEF;
1478 channel->lastEF = v;
1479 }
1480 if (channel->playing) {
1481 if ((v & 0xF0) == 0xF0)
1482 channel->playing->slide += (v & 15) << 4;
1483 else if ((v & 0xF0) == 0xE0)
1484 channel->playing->slide += (v & 15) << 2;
1485 else
1486 channel->portamento += v << 4;
1487 }
1488 }
1489 break;
1490 case IT_XM_PORTAMENTO_DOWN:
1491 {
1492 unsigned char v = entry->effectvalue;
1493 if (!(sigdata->flags & IT_WAS_A_MOD)) {
1494 if (v == 0)
1495 v = channel->lastJ;
1496 channel->lastJ = v;
1497 }
1498 if (channel->playing)
1499 channel->portamento -= v << 4;
1500 }
1501 break;
1502 case IT_XM_PORTAMENTO_UP:
1503 {
1504 unsigned char v = entry->effectvalue;
1505 if (!(sigdata->flags & IT_WAS_A_MOD)) {
1506 if (v == 0)
1507 v = channel->lastEF;
1508 channel->lastEF = v;
1509 }
1510 if (channel->playing)
1511 channel->portamento += v << 4;
1512 }
1513 break;
1514 case IT_VIBRATO:
1515 {
1516 unsigned char speed = entry->effectvalue >> 4;
1517 unsigned char depth = entry->effectvalue & 15;
1518 if (speed == 0)
1519 speed = channel->lastHspeed;
1520 channel->lastHspeed = speed;
1521 if (depth == 0)
1522 depth = channel->lastHdepth;
1523 else {
1524 if (sigdata->flags & IT_OLD_EFFECTS)
1525 depth <<= 3;
1526 else
1527 depth <<= 2;
1528 channel->lastHdepth = depth;
1529 }
1530 if (channel->playing) {
1531 channel->playing->vibrato_speed = speed;
1532 channel->playing->vibrato_depth = depth;
1533 channel->playing->vibrato_n++;
1534 }
1535 }
1536 break;
1537 case IT_TREMOR:
1538 {
1539 unsigned char v = entry->effectvalue;
1540 if (v == 0)
1541 v = channel->lastI;
1542 else if (!(sigdata->flags & IT_OLD_EFFECTS)) {
1543 if (v & 0xF0) v -= 0x10;
1544 if (v & 0x0F) v -= 0x01;
1545 }
1546 channel->lastI = v;
1547 channel->tremor_time |= 128;
1548 }
1549 update_tremor(channel);
1550 break;
1551 case IT_ARPEGGIO:
1552 {
1553 unsigned char v = entry->effectvalue;
1554 /* XM files have no memory for arpeggio (000 = no effect)
1555 * and we use lastJ for portamento down instead.
1556 */
1557 if (!(sigdata->flags & IT_WAS_AN_XM)) {
1558 if (v == 0)
1559 v = channel->lastJ;
1560 channel->lastJ = v;
1561 }
1562 channel->arpeggio = v;
1563 }
1564 break;
1565 case IT_SET_CHANNEL_VOLUME:
1566 if (sigdata->flags & IT_WAS_AN_XM)
1567 channel->volume = MIN(entry->effectvalue, 64);
1568 else if (entry->effectvalue <= 64)
1569 channel->channelvolume = entry->effectvalue;
1570#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
1571 else
1572 channel->channelvolume = 64;
1573#endif
1574 if (channel->playing)
1575 channel->playing->channel_volume = channel->channelvolume;
1576 break;
1577 case IT_CHANNEL_VOLUME_SLIDE:
1578 {
1579 unsigned char v = entry->effectvalue;
1580 if (v == 0)
1581 v = channel->lastN;
1582 channel->lastN = v;
1583 if ((v & 0x0F) == 0) { /* Nx0 */
1584 channel->channelvolslide = v >> 4;
1585 } else if ((v & 0xF0) == 0) { /* N0x */
1586 channel->channelvolslide = -v;
1587 } else {
1588 if ((v & 0x0F) == 0x0F) { /* NxF */
1589 channel->channelvolume += v >> 4;
1590 if (channel->channelvolume > 64) channel->channelvolume = 64;
1591 } else if ((v & 0xF0) == 0xF0) { /* NFx */
1592 channel->channelvolume -= v & 15;
1593 if (channel->channelvolume > 64) channel->channelvolume = 0;
1594 } else
1595 break;
1596 if (channel->playing)
1597 channel->playing->channel_volume = channel->channelvolume;
1598 }
1599 }
1600 break;
1601 case IT_SET_SAMPLE_OFFSET:
1602 {
1603 unsigned char v = entry->effectvalue;
1604 if (sigdata->flags & IT_WAS_A_MOD) {
1605 if (v == 0) break;
1606 } else {
1607 if (v == 0)
1608 v = channel->lastO;
1609 channel->lastO = v;
1610 }
1611 /* Note: we set the offset even if tone portamento is
1612 * specified. Impulse Tracker does the same.
1613 */
1614 if (entry->mask & IT_ENTRY_NOTE) {
1615 if (channel->playing) {
1616 int offset = ((int)channel->high_offset << 16) | ((int)v << 8);
1617 IT_PLAYING *playing = channel->playing;
1618 IT_SAMPLE *sample = playing->sample;
1619 int end;
1620 if ((sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF))
1621 end = sample->sus_loop_end;
1622 else if (sample->flags & IT_SAMPLE_LOOP)
1623 end = sample->loop_end;
1624 else
1625 end = sample->length;
1626 if (offset < end)
1627 it_playing_reset_resamplers(playing, offset);
1628 else if (sigdata->flags & IT_OLD_EFFECTS)
1629 it_playing_reset_resamplers(playing, end);
1630 }
1631 }
1632 }
1633 break;
1634 //case IT_PANNING_SLIDE:
1635 /** JULIEN: guess what? the docs are wrong! (how unusual ;)
1636 * Pxy seems to memorize its previous value... and there
1637 * might be other mistakes like that... (sigh!)
1638 */
1639 /** ENTHEH: umm... but... the docs say that Pxy memorises its
1640 * value... don't they? :o
1641 */
1642 case IT_RETRIGGER_NOTE:
1643 {
1644 unsigned char v = entry->effectvalue;
1645 if (sigdata->flags & IT_WAS_AN_XM) {
1646 if ((v & 0x0F) == 0) v |= channel->lastQ & 0x0F;
1647 if ((v & 0xF0) == 0) v |= channel->lastQ & 0xF0;
1648 } else {
1649 if (v == 0)
1650 v = channel->lastQ;
1651 }
1652 channel->lastQ = v;
1653 if ((v & 0x0F) == 0) v |= 0x01;
1654 channel->retrig = v;
1655 if (entry->mask & IT_ENTRY_NOTE) {
1656 channel->retrig_tick = v & 0x0F;
1657 /* Emulate a bug */
1658 if (sigdata->flags & IT_WAS_AN_XM)
1659 update_retrig(channel);
1660 } else
1661 update_retrig(channel);
1662 }
1663 break;
1664 case IT_XM_RETRIGGER_NOTE:
1665 channel->retrig_tick = channel->xm_retrig = entry->effectvalue;
1666 if (entry->effectvalue == 0)
1667 if (channel->playing) it_playing_reset_resamplers(channel->playing, 0);
1668 break;
1669 case IT_TREMOLO:
1670 {
1671 unsigned char speed = entry->effectvalue >> 4;
1672 unsigned char depth = entry->effectvalue & 15;
1673 if (speed == 0)
1674 speed = channel->lastRspeed;
1675 channel->lastRspeed = speed;
1676 if (depth == 0)
1677 depth = channel->lastRdepth;
1678 channel->lastRdepth = depth;
1679 if (channel->playing) {
1680 channel->playing->tremolo_speed = speed;
1681 channel->playing->tremolo_depth = depth;
1682 }
1683 }
1684 break;
1685 case IT_S:
1686 {
1687 /* channel->lastS was set in update_pattern_variables(). */
1688 unsigned char effectvalue = channel->lastS;
1689 switch (effectvalue >> 4) {
1690 //case IT_S_SET_FILTER:
1691 //case IT_S_SET_GLISSANDO_CONTROL:
1692 //case IT_S_FINETUNE:
1693 //case IT_S_SET_VIBRATO_WAVEFORM:
1694 //case IT_S_SET_TREMOLO_WAVEFORM:
1695 //case IT_S_SET_PANBRELLO_WAVEFORM:
1696 /* Waveforms for commands S3x, S4x and S5x:
1697 * 0: Sine wave
1698 * 1: Ramp down
1699 * 2: Square wave
1700 * 3: Random wave
1701 */
1702 case IT_S_FINE_PATTERN_DELAY:
1703 sigrenderer->tick += effectvalue & 15;
1704 break;
1705 //case IT_S7:
1706 case IT_S_SET_PAN:
1707 channel->pan =
1708 ((effectvalue & 15) << 2) |
1709 ((effectvalue & 15) >> 2);
1710 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1711 break;
1712 case IT_S_SET_SURROUND_SOUND:
1713 if ((effectvalue & 15) == 1)
1714 channel->pan = IT_SURROUND;
1715 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1716 break;
1717 case IT_S_SET_HIGH_OFFSET:
1718 channel->high_offset = effectvalue & 15;
1719 break;
1720 //case IT_S_PATTERN_LOOP:
1721 case IT_S_DELAYED_NOTE_CUT:
1722 channel->note_cut_count = effectvalue & 15;
1723 if (!channel->note_cut_count) {
1724 if (sigdata->flags & IT_WAS_AN_XM)
1725 channel->volume = 0;
1726 else
1727 channel->note_cut_count = 1;
1728 }
1729 break;
1730 case IT_S_SET_MIDI_MACRO:
1731 channel->SFmacro = effectvalue & 15;
1732 break;
1733 }
1734 }
1735 break;
1736 case IT_SET_SONG_TEMPO:
1737 {
1738 unsigned char v = entry->effectvalue;
1739 if (v == 0)
1740 v = channel->lastW;
1741 channel->lastW = v;
1742 if (v < 0x10)
1743 sigrenderer->temposlide = -v;
1744 else if (v < 0x20)
1745 sigrenderer->temposlide = v & 15;
1746 else
1747 sigrenderer->tempo = v;
1748 }
1749 break;
1750 case IT_FINE_VIBRATO:
1751 {
1752 unsigned char speed = entry->effectvalue >> 4;
1753 unsigned char depth = entry->effectvalue & 15;
1754 if (speed == 0)
1755 speed = channel->lastHspeed;
1756 channel->lastHspeed = speed;
1757 if (depth == 0)
1758 depth = channel->lastHdepth;
1759 else {
1760 if (sigdata->flags & IT_OLD_EFFECTS)
1761 depth <<= 1;
1762 channel->lastHdepth = depth;
1763 }
1764 if (channel->playing) {
1765 channel->playing->vibrato_speed = speed;
1766 channel->playing->vibrato_depth = depth;
1767 channel->playing->vibrato_n++;
1768 }
1769 }
1770 break;
1771 case IT_SET_GLOBAL_VOLUME:
1772 if (entry->effectvalue <= 128)
1773 sigrenderer->globalvolume = entry->effectvalue;
1774#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
1775 else
1776 sigrenderer->globalvolume = 128;
1777#endif
1778 break;
1779 case IT_GLOBAL_VOLUME_SLIDE:
1780 {
1781 unsigned char v = entry->effectvalue;
1782 if (v == 0)
1783 v = channel->lastW;
1784 channel->lastW = v;
1785 if ((v & 0x0F) == 0) { /* Wx0 */
1786 sigrenderer->globalvolslide =
1787 (sigdata->flags & IT_WAS_AN_XM) ? (v >> 4)*2 : (v >> 4);
1788 } else if ((v & 0xF0) == 0) { /* W0x */
1789 sigrenderer->globalvolslide =
1790 (sigdata->flags & IT_WAS_AN_XM) ? (-v)*2 : (-v);
1791 } else if ((v & 0x0F) == 0x0F) { /* WxF */
1792 sigrenderer->globalvolume += v >> 4;
1793 if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 128;
1794 } else if ((v & 0xF0) == 0xF0) { /* WFx */
1795 sigrenderer->globalvolume -= v & 15;
1796 if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 0;
1797 }
1798 }
1799 break;
1800 case IT_SET_PANNING:
1801 channel->pan = (entry->effectvalue + 2) >> 2;
1802 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1803 break;
1804 //case IT_PANBRELLO:
1805 case IT_MIDI_MACRO:
1806 {
1807 IT_MIDI *midi = sigdata->midi ? sigdata->midi : &default_midi;
1808 if (entry->effectvalue >= 0x80) {
1809 int n = midi->Zmacrolen[entry->effectvalue-0x80];
1810 int i;
1811 for (i = 0; i < n; i++)
1812 it_send_midi(sigrenderer, channel, midi->Zmacro[entry->effectvalue-0x80][i]);
1813 } else {
1814 int n = midi->SFmacrolen[channel->SFmacro];
1815 int i, j;
1816 for (i = 0, j = 1; i < n; i++, j <<= 1)
1817 it_send_midi(sigrenderer, channel,
1818 midi->SFmacroz[channel->SFmacro] & j ?
1819 entry->effectvalue : midi->SFmacro[channel->SFmacro][i]);
1820 }
1821 }
1822 break;
1823 }
1824 }
1825
1826 if (!(sigdata->flags & IT_WAS_AN_XM))
1827 post_process_it_volpan(sigrenderer, entry);
1828
1829 return 0;
1830}
1831
1832
1833
1834static int process_it_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
1835{
1836 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
1837 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
1838
1839 // When tone portamento and instrument are specified:
1840 // If Gxx is off:
1841 // - same sample, do nothing but portamento
1842 // - diff sample, retrigger all but keep current note+slide + do porta
1843 // - if instrument is invalid, nothing; if sample is invalid, cut
1844 // If Gxx is on:
1845 // - same sample or new sample invalid, retrigger envelopes
1846 // - diff sample/inst, start using new envelopes
1847 // When tone portamento is specified alone, sample won't change.
1848 // TODO: consider what happens with instrument alone after all this...
1849
1850 if (entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) {
1851 if (entry->mask & IT_ENTRY_INSTRUMENT)
1852 channel->instrument = entry->instrument;
1853 instrument_to_sample(sigdata, channel);
1854 if (channel->note < 120) {
1855 if ((sigdata->flags & IT_USE_INSTRUMENTS) && channel->sample == 0)
1856 return 1;
1857 if (entry->mask & IT_ENTRY_INSTRUMENT)
1858 get_default_volpan(sigdata, channel);
1859 } else
1860 it_retrigger_note(sigrenderer, channel);
1861 }
1862
1863 /** WARNING: This is not ideal, since channel->playing might not get allocated owing to lack of memory... */
1864 if (channel->playing &&
1865 (((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) ||
1866 ((entry->mask & IT_ENTRY_EFFECT) && (entry->effect == IT_TONE_PORTAMENTO || entry->effect == IT_VOLSLIDE_TONEPORTA))))
1867 {
1868 if (entry->mask & IT_ENTRY_INSTRUMENT) {
1869 if (sigdata->flags & IT_COMPATIBLE_GXX)
1870 retrigger_it_envelopes(sigdata, channel);
1871 else if ((!(sigdata->flags & IT_USE_INSTRUMENTS) ||
1872 (channel->instrument >= 1 && channel->instrument <= sigdata->n_instruments)) &&
1873 channel->sample != channel->playing->sampnum)
1874 {
1875 unsigned char note = channel->playing->note;
1876 int slide = channel->playing->slide;
1877 it_retrigger_note(sigrenderer, channel);
1878 if (channel->playing) {
1879 channel->playing->note = note;
1880 channel->playing->slide = slide;
1881 // Should we be preserving sample_vibrato_time? depth?
1882 }
1883 }
1884 }
1885
1886 if ((entry->mask & IT_ENTRY_VOLPAN) && entry->volpan >= 193 && entry->volpan <= 202) {
1887 /* Tone Portamento in the volume column */
1888 static const unsigned char slidetable[] = {0, 1, 4, 8, 16, 32, 64, 96, 128, 255};
1889 unsigned char v = slidetable[entry->volpan - 193];
1890 if (sigdata->flags & IT_COMPATIBLE_GXX) {
1891 if (v == 0)
1892 v = channel->lastG;
1893 channel->lastG = v;
1894 } else {
1895 if (v == 0)
1896 v = channel->lastEF;
1897 channel->lastEF = v;
1898 }
1899 if (entry->mask & IT_ENTRY_NOTE)
1900 if (channel->sample)
1901 channel->destnote = channel->truenote;
1902 channel->toneporta = v << 4;
1903 } else {
1904 /* Tone Portamento in the effect column */
1905 unsigned char v;
1906 if (entry->effect == IT_TONE_PORTAMENTO)
1907 v = entry->effectvalue;
1908 else
1909 v = 0;
1910 if (sigdata->flags & IT_COMPATIBLE_GXX) {
1911 if (v == 0)
1912 v = channel->lastG;
1913 channel->lastG = v;
1914 } else {
1915 if (v == 0)
1916 v = channel->lastEF;
1917 channel->lastEF = v;
1918 }
1919 if (entry->mask & IT_ENTRY_NOTE)
1920 if (channel->sample)
1921 channel->destnote = channel->truenote;
1922 channel->toneporta = v << 4;
1923 }
1924 } else if ((entry->mask & IT_ENTRY_NOTE) ||
1925 ((entry->mask & IT_ENTRY_INSTRUMENT) && (!channel->playing || entry->instrument != channel->playing->instnum)))
1926 {
1927 if (channel->note < 120) {
1928 get_true_pan(sigdata, channel);
1929 it_retrigger_note(sigrenderer, channel);
1930 }
1931 }
1932
1933 if (entry->mask & IT_ENTRY_VOLPAN) {
1934 if (entry->volpan <= 64) {
1935 /* Volume */
1936 channel->volume = entry->volpan;
1937 } else if (entry->volpan <= 74) {
1938 /* Fine volume slide up */
1939 unsigned char v = entry->volpan - 65;
1940 if (v == 0)
1941 v = channel->lastvolslide;
1942 channel->lastvolslide = v;
1943 /* = effect DxF where x == entry->volpan - 65 */
1944 channel->volume += v;
1945 if (channel->volume > 64) channel->volume = 64;
1946 } else if (entry->volpan <= 84) {
1947 /* Fine volume slide down */
1948 unsigned char v = entry->volpan - 75;
1949 if (v == 0)
1950 v = channel->lastvolslide;
1951 channel->lastvolslide = v;
1952 /* = effect DFx where x == entry->volpan - 75 */
1953 channel->volume -= v;
1954 if (channel->volume > 64) channel->volume = 0;
1955 } else if (entry->volpan < 128) {
1956 /* Volume slide up */
1957 /* Volume slide down */
1958 /* Portamento down */
1959 /* Portamento up */
1960 } else if (entry->volpan <= 192) {
1961 /* Pan */
1962 channel->pan = entry->volpan - 128;
1963 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
1964 }
1965 /* else */
1966 /* Tone Portamento */
1967 /* Vibrato */
1968 }
1969 return 0;
1970}
1971
1972
1973
1974static void retrigger_xm_envelopes(IT_PLAYING *playing)
1975{
1976 playing->volume_envelope.next_node = 0;
1977 playing->volume_envelope.tick = -1;
1978 playing->pan_envelope.next_node = 0;
1979 playing->pan_envelope.tick = -1;
1980 playing->fadeoutcount = 1024;
1981}
1982
1983
1984
1985static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
1986{
1987 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
1988 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
1989
1990 if (entry->mask & IT_ENTRY_INSTRUMENT) {
1991 channel->instrument = entry->instrument;
1992 instrument_to_sample(sigdata, channel);
1993 if (channel->playing) {
1994 /* Retrigger vol/pan envelopes if enabled, and cancel fadeout.
1995 * Also reset vol/pan to that of _original_ instrument.
1996 */
1997 channel->playing->flags &= ~(IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING);
1998 it_playing_update_resamplers(channel->playing);
1999
2000 channel->volume = channel->playing->sample->default_volume;
2001 if (channel->pan >= 128 && channel->pan <= 192)
2002 channel->pan = channel->playing->sample->default_pan - 128;
2003
2004 retrigger_xm_envelopes(channel->playing);
2005 }
2006 }
2007
2008 if (entry->mask & IT_ENTRY_NOTE) {
2009 if (!(entry->mask & IT_ENTRY_INSTRUMENT))
2010 instrument_to_sample(sigdata, channel);
2011
2012 if (channel->note >= 120) {
2013 if (channel->playing) {
2014 if (!(sigdata->instrument[channel->instrument-1].volume_envelope.flags & IT_ENVELOPE_ON))
2015 if (!(entry->mask & IT_ENTRY_INSTRUMENT))
2016 channel->volume = 0;
2017 channel->playing->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
2018 it_playing_update_resamplers(channel->playing);
2019 }
2020 } else if (channel->sample == 0) {
2021 /** If we get here, one of the following is the case:
2022 ** 1. The instrument has never been specified on this channel.
2023 ** 2. The specified instrument is invalid.
2024 ** 3. The instrument has no sample mapped to the selected note.
2025 ** What should happen?
2026 **
2027 ** Experimentation shows that any existing note stops and cannot
2028 ** be brought back. A subsequent instrument change fixes that.
2029 **/
2030 if (channel->playing) {
2031 free(channel->playing);
2032 channel->playing = NULL;
2033 }
2034 return;
2035 } else if (channel->playing && (entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
2036 /* Don't retrigger note; portamento in the volume column. */
2037 } else if (channel->playing &&
2038 (entry->mask & IT_ENTRY_EFFECT) &&
2039 (entry->effect == IT_TONE_PORTAMENTO ||
2040 entry->effect == IT_VOLSLIDE_TONEPORTA)) {
2041 /* Don't retrigger note; portamento in the effects column. */
2042 } else {
2043 channel->destnote = IT_NOTE_OFF;
2044
2045 if (!channel->playing) {
2046 channel->playing = malloc(sizeof(*channel->playing));
2047 if (!channel->playing)
2048 return;
2049 // Adding the following seems to do the trick for the case where a piece starts with an instrument alone and then some notes alone.
2050 retrigger_xm_envelopes(channel->playing);
2051 }
2052
2053 channel->playing->flags = 0;
2054 channel->playing->channel = channel;
2055 channel->playing->sample = &sigdata->sample[channel->sample-1];
2056 if (sigdata->flags & IT_USE_INSTRUMENTS)
2057 channel->playing->instrument = &sigdata->instrument[channel->instrument-1];
2058 else
2059 channel->playing->instrument = NULL;
2060 channel->playing->env_instrument = channel->playing->instrument;
2061 channel->playing->sampnum = channel->sample;
2062 channel->playing->instnum = channel->instrument;
2063 channel->playing->channel_volume = channel->channelvolume;
2064 channel->playing->note = channel->truenote;
2065 channel->playing->filter_cutoff = 127;
2066 channel->playing->filter_resonance = 0;
2067 channel->playing->true_filter_cutoff = 127 << 8;
2068 channel->playing->true_filter_resonance = 0;
2069 channel->playing->vibrato_speed = 0;
2070 channel->playing->vibrato_depth = 0;
2071 channel->playing->vibrato_n = 0;
2072 channel->playing->vibrato_time = 0;
2073 channel->playing->tremolo_speed = 0;
2074 channel->playing->tremolo_depth = 0;
2075 channel->playing->tremolo_time = 0;
2076 channel->playing->sample_vibrato_time = 0;
2077 channel->playing->sample_vibrato_depth = 0;
2078 channel->playing->slide = 0;
2079 it_reset_filter_state(&channel->playing->filter_state[0]); // Are these
2080 it_reset_filter_state(&channel->playing->filter_state[1]); // necessary?
2081 it_playing_reset_resamplers(channel->playing, 0);
2082
2083 /** WARNING - is everything initialised? */
2084 }
2085 }
2086
2087 if ((entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) == (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) {
2088 if (channel->playing) retrigger_xm_envelopes(channel->playing);
2089 get_default_volpan(sigdata, channel);
2090 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
2091 }
2092
2093 if ((entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
2094 /* Tone Portamento */
2095 unsigned char v = (entry->volpan & 15) << 4;
2096 if (v == 0)
2097 v = channel->lastG;
2098 channel->lastG = v;
2099 if (entry->mask & IT_ENTRY_NOTE)
2100 if (channel->sample)
2101 channel->destnote = channel->truenote;
2102 channel->toneporta = v << 4;
2103 } else if ((entry->mask & IT_ENTRY_EFFECT) &&
2104 (entry->effect == IT_TONE_PORTAMENTO ||
2105 entry->effect == IT_VOLSLIDE_TONEPORTA)) {
2106 unsigned char v;
2107 if (entry->effect == IT_TONE_PORTAMENTO)
2108 v = entry->effectvalue;
2109 else
2110 v = 0;
2111 if (v == 0)
2112 v = channel->lastG;
2113 channel->lastG = v;
2114 if (entry->mask & IT_ENTRY_NOTE)
2115 if (channel->sample)
2116 channel->destnote = channel->truenote;
2117 channel->toneporta = v << 4;
2118 }
2119
2120 if (entry->mask & IT_ENTRY_VOLPAN) {
2121 int effect = entry->volpan >> 4;
2122 int value = entry->volpan & 15;
2123 switch (effect) {
2124 case 0x6: /* Volume slide down */
2125 channel->xm_volslide = -value;
2126 break;
2127 case 0x7: /* Volume slide up */
2128 channel->xm_volslide = value;
2129 break;
2130 case 0x8: /* Fine volume slide down */
2131 channel->volume -= value;
2132 if (channel->volume > 64) channel->volume = 0;
2133 break;
2134 case 0x9: /* Fine volume slide up */
2135 channel->volume += value;
2136 if (channel->volume > 64) channel->volume = 64;
2137 break;
2138 case 0xA: /* Set vibrato speed */
2139 if (value)
2140 channel->lastHspeed = value;
2141 if (channel->playing)
2142 channel->playing->vibrato_speed = channel->lastHspeed;
2143 break;
2144 case 0xB: /* Vibrato */
2145 if (value)
2146 channel->lastHdepth = value << 2; /** WARNING: correct ? */
2147 if (channel->playing) {
2148 channel->playing->vibrato_depth = channel->lastHdepth;
2149 channel->playing->vibrato_speed = channel->lastHspeed;
2150 channel->playing->vibrato_n++;
2151 }
2152 break;
2153 case 0xC: /* Set panning */
2154 channel->pan = (value*64)/15;
2155 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
2156 break;
2157 case 0xD: /* Pan slide left */
2158 // TODO
2159 // channel->xm_panslide = -value;
2160 break;
2161 case 0xE: /* Pan slide Right */
2162 // TODO
2163 // channel->xm_panslide = value;
2164 break;
2165 case 0xF: /* Tone porta */
2166 break;
2167 default: /* Volume */
2168 channel->volume = entry->volpan - 0x10;
2169 break;
2170 }
2171 }
2172}
2173
2174
2175
2176/* This function assumes !IT_IS_END_ROW(entry). */
2177static int process_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
2178{
2179 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
2180
2181 if (sigdata->flags & IT_WAS_AN_XM)
2182 process_xm_note_data(sigrenderer, entry);
2183 else
2184 if (process_it_note_data(sigrenderer, entry)) return 0;
2185
2186 return process_effects(sigrenderer, entry);
2187}
2188
2189
2190
2191static int process_entry(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
2192{
2193 IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
2194
2195 if (entry->mask & IT_ENTRY_NOTE)
2196 channel->note = entry->note;
2197
2198 if ((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_S) {
2199 /* channel->lastS was set in update_pattern_variables(). */
2200 unsigned char effectvalue = channel->lastS;
2201 if (effectvalue >> 4 == IT_S_NOTE_DELAY) {
2202 channel->note_delay_count = effectvalue & 15;
2203 if (channel->note_delay_count == 0)
2204 channel->note_delay_count = 1;
2205 channel->note_delay_entry = entry;
2206 return 0;
2207 }
2208 }
2209
2210 return process_note_data(sigrenderer, entry);
2211}
2212
2213
2214
2215static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
2216{
2217 int i;
2218
2219 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2220 IT_CHANNEL *channel = &sigrenderer->channel[i];
2221
2222 if (channel->note_cut_count) {
2223 channel->note_cut_count--;
2224 if (channel->note_cut_count == 0) {
2225 if (sigrenderer->sigdata->flags & IT_WAS_AN_XM)
2226 channel->volume = 0;
2227 else if (channel->playing) {
2228 free(channel->playing);
2229 channel->playing = NULL;
2230 }
2231 }
2232 } else if (channel->note_delay_count) {
2233 channel->note_delay_count--;
2234 if (channel->note_delay_count == 0)
2235 process_note_data(sigrenderer, channel->note_delay_entry);
2236 /* Don't bother checking the return value; if the note
2237 * was delayed, there can't have been a speed=0.
2238 */
2239 }
2240 }
2241}
2242
2243
2244
2245static int envelope_get_y(IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2246{
2247 int ys, ye;
2248 int ts, te;
2249 int t;
2250
2251 if (pe->next_node <= 0)
2252 return envelope->node_y[0] << IT_ENVELOPE_SHIFT;
2253
2254 if (pe->next_node >= envelope->n_nodes)
2255 return envelope->node_y[envelope->n_nodes-1] << IT_ENVELOPE_SHIFT;
2256
2257 ys = envelope->node_y[pe->next_node-1] << IT_ENVELOPE_SHIFT;
2258 ts = envelope->node_t[pe->next_node-1];
2259 te = envelope->node_t[pe->next_node];
2260
2261 if (ts == te)
2262 return ys;
2263
2264 ye = envelope->node_y[pe->next_node] << IT_ENVELOPE_SHIFT;
2265
2266 t = pe->tick;
2267
2268 return ys + (ye - ys) * (t - ts) / (te - ts);
2269}
2270
2271
2272
2273static int it_envelope_end(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2274{
2275 if (pe->next_node >= envelope->n_nodes)
2276 return 1;
2277
2278 if (pe->tick < envelope->node_t[pe->next_node]) return 0;
2279
2280 if ((envelope->flags & IT_ENVELOPE_LOOP_ON) &&
2281 envelope->loop_end >= pe->next_node &&
2282 envelope->node_t[envelope->loop_end] <= pe->tick) return 0;
2283
2284 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) &&
2285 !(playing->flags & IT_PLAYING_SUSTAINOFF) &&
2286 envelope->sus_loop_end >= pe->next_node &&
2287 envelope->node_t[envelope->sus_loop_end] <= pe->tick) return 0;
2288
2289 if (envelope->node_t[envelope->n_nodes-1] <= pe->tick) return 1;
2290
2291 return 0;
2292}
2293
2294
2295
2296/* This returns 1 if the envelope finishes. */
2297static int update_it_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2298{
2299 if (!(envelope->flags & IT_ENVELOPE_ON))
2300 return 0;
2301
2302 if (pe->next_node >= envelope->n_nodes)
2303 return 1;
2304
2305 while (pe->tick >= envelope->node_t[pe->next_node]) {
2306 if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && pe->next_node == envelope->loop_end) {
2307 pe->next_node = envelope->loop_start;
2308 pe->tick = envelope->node_t[envelope->loop_start];
2309 return it_envelope_end(playing, envelope, pe);
2310 }
2311 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF) && pe->next_node == envelope->sus_loop_end) {
2312 pe->next_node = envelope->sus_loop_start;
2313 pe->tick = envelope->node_t[envelope->sus_loop_start];
2314 return it_envelope_end(playing, envelope, pe);
2315 }
2316
2317 pe->next_node++;
2318
2319 if (pe->next_node >= envelope->n_nodes)
2320 return 1;
2321 }
2322
2323 pe->tick++;
2324
2325 return it_envelope_end(playing, envelope, pe);
2326}
2327
2328
2329
2330static void update_it_envelopes(IT_PLAYING *playing)
2331{
2332 IT_ENVELOPE *envelope = &playing->env_instrument->volume_envelope;
2333
2334 if (update_it_envelope(playing, envelope, &playing->volume_envelope)) {
2335 playing->flags |= IT_PLAYING_FADING;
2336 if (envelope->n_nodes && envelope->node_y[envelope->n_nodes-1] == 0)
2337 playing->flags |= IT_PLAYING_DEAD;
2338 }
2339
2340 update_it_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope);
2341 update_it_envelope(playing, &playing->env_instrument->pitch_envelope, &playing->pitch_envelope);
2342}
2343
2344
2345
2346static int xm_envelope_is_sustaining(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2347{
2348 if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF))
2349 if (envelope->sus_loop_start < envelope->n_nodes)
2350 if (pe->tick == envelope->node_t[envelope->sus_loop_start])
2351 return 1;
2352 return 0;
2353}
2354
2355
2356
2357static void update_xm_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLAYING_ENVELOPE *pe)
2358{
2359 if (!(envelope->flags & IT_ENVELOPE_ON))
2360 return;
2361
2362 if (xm_envelope_is_sustaining(playing, envelope, pe))
2363 return;
2364
2365 if (pe->tick >= envelope->node_t[envelope->n_nodes-1])
2366 return;
2367
2368 pe->tick++;
2369
2370 /* pe->next_node must be kept up to date for envelope_get_y(). */
2371 while (pe->tick > envelope->node_t[pe->next_node])
2372 pe->next_node++;
2373
2374 if ((envelope->flags & IT_ENVELOPE_LOOP_ON) && envelope->loop_end < envelope->n_nodes) {
2375 if (pe->tick == envelope->node_t[envelope->loop_end]) {
2376 pe->next_node = MID(0, envelope->loop_start, envelope->n_nodes - 1);
2377 pe->tick = envelope->node_t[pe->next_node];
2378 }
2379 }
2380
2381 if (xm_envelope_is_sustaining(playing, envelope, pe))
2382 return;
2383
2384 if (pe->tick >= envelope->node_t[envelope->n_nodes-1])
2385 return;
2386}
2387
2388
2389
2390static void update_xm_envelopes(IT_PLAYING *playing)
2391{
2392 update_xm_envelope(playing, &playing->env_instrument->volume_envelope, &playing->volume_envelope);
2393 update_xm_envelope(playing, &playing->env_instrument->pan_envelope, &playing->pan_envelope);
2394}
2395
2396
2397
2398static void update_fadeout(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing)
2399{
2400 if (playing->flags & IT_PLAYING_FADING) {
2401 playing->fadeoutcount -= playing->env_instrument->fadeout;
2402 if (playing->fadeoutcount <= 0) {
2403 playing->fadeoutcount = 0;
2404 if (!(sigdata->flags & IT_WAS_AN_XM))
2405 playing->flags |= IT_PLAYING_DEAD;
2406 }
2407 }
2408}
2409
2410
2411
2412static void process_playing(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing)
2413{
2414 if (playing->instrument) {
2415 if (sigdata->flags & IT_WAS_AN_XM)
2416 update_xm_envelopes(playing);
2417 else
2418 update_it_envelopes(playing);
2419 update_fadeout(sigdata, playing);
2420 }
2421
2422 //Calculate final volume if required
2423 //Calculate final pan if required
2424
2425 if (sigdata->flags & IT_WAS_AN_XM) {
2426 /* 'depth' is used to store the tick number for XM files. */
2427 if (playing->sample_vibrato_depth < playing->sample->vibrato_rate)
2428 playing->sample_vibrato_depth++;
2429 } else {
2430 playing->sample_vibrato_depth += playing->sample->vibrato_rate;
2431 if (playing->sample_vibrato_depth > playing->sample->vibrato_depth << 8)
2432 playing->sample_vibrato_depth = playing->sample->vibrato_depth << 8;
2433 }
2434
2435 playing->sample_vibrato_time += playing->sample->vibrato_speed;
2436}
2437
2438
2439
2440static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
2441{
2442 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
2443 int i;
2444
2445 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2446 IT_CHANNEL *channel = &sigrenderer->channel[i];
2447 IT_PLAYING *playing = channel->playing;
2448
2449 if (playing) {
2450 int vibrato_shift = it_sine[playing->vibrato_time];
2451 vibrato_shift *= playing->vibrato_n;
2452 vibrato_shift *= playing->vibrato_depth;
2453 vibrato_shift >>= 4;
2454
2455 if (sigdata->flags & IT_OLD_EFFECTS)
2456 vibrato_shift = -vibrato_shift;
2457
2458 playing->volume = channel->volume;
2459 playing->pan = channel->truepan;
2460
2461 if (sigdata->flags & IT_LINEAR_SLIDES) {
2462 int currpitch = ((playing->note - 60) << 8) + playing->slide
2463 + vibrato_shift;
2464
2465 /* We add a feature here, which is that of keeping the pitch
2466 * within range. Otherwise it crashes. Trust me. It happened.
2467 * The limit 32768 gives almost 11 octaves either way.
2468 */
2469 if (currpitch < -32768)
2470 currpitch = -32768;
2471 else if (currpitch > 32767)
2472 currpitch = 32767;
2473
2474 playing->delta = (float)pow(DUMB_PITCH_BASE, currpitch);
2475 playing->delta *= playing->sample->C5_speed / 65536.0f;
2476 } else {
2477 int slide = playing->slide + vibrato_shift;
2478
2479 playing->delta = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note);
2480 /* playing->delta is 1.0 for C-5, 0.5 for C-6, etc. */
2481
2482 playing->delta *= 1.0f / playing->sample->C5_speed;
2483
2484 playing->delta -= slide / AMIGA_DIVISOR;
2485
2486 if (playing->delta < (1.0f / 65536.0f) / 32768.0f) {
2487 // Should XM notes die if Amiga slides go out of range?
2488 playing->flags |= IT_PLAYING_DEAD;
2489 continue;
2490 }
2491
2492 playing->delta = (1.0f / 65536.0f) / playing->delta;
2493 }
2494
2495 playing->delta *= (float)pow(DUMB_SEMITONE_BASE, channel->arpeggio >> 8);
2496
2497 playing->filter_cutoff = channel->filter_cutoff;
2498 playing->filter_resonance = channel->filter_resonance;
2499 }
2500 }
2501
2502 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2503 if (sigrenderer->channel[i].playing) {
2504 process_playing(sigdata, sigrenderer->channel[i].playing);
2505 if (!(sigdata->flags & IT_WAS_AN_XM)) {
2506 if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) {
2507 free(sigrenderer->channel[i].playing);
2508 sigrenderer->channel[i].playing = NULL;
2509 }
2510 }
2511 }
2512 }
2513
2514 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2515 if (sigrenderer->playing[i]) {
2516 process_playing(sigdata, sigrenderer->playing[i]);
2517 if (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) {
2518 free(sigrenderer->playing[i]);
2519 sigrenderer->playing[i] = NULL;
2520 }
2521 }
2522 }
2523}
2524
2525
2526
2527static int process_tick(DUMB_IT_SIGRENDERER *sigrenderer)
2528{
2529 DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
2530
2531 // Set note vol/freq to vol/freq set for each channel
2532
2533 if (sigrenderer->speed && --sigrenderer->tick == 0) {
2534 reset_tick_counts(sigrenderer);
2535 sigrenderer->tick = sigrenderer->speed;
2536 sigrenderer->rowcount--;
2537 if (sigrenderer->rowcount == 0) {
2538 sigrenderer->rowcount = 1;
2539 if (sigrenderer->pat_loop_row >= 0) {
2540 int n = sigrenderer->pat_loop_row - 1;
2541 sigrenderer->row = sigrenderer->processrow = n;
2542 sigrenderer->pat_loop_row = -1;
2543 if (n < 0)
2544 sigrenderer->entry = NULL;
2545 else {
2546 sigrenderer->entry = sigrenderer->entry_start;
2547 while (n) {
2548 while (sigrenderer->entry < sigrenderer->entry_end) {
2549 if (IT_IS_END_ROW(sigrenderer->entry)) {
2550 sigrenderer->entry++;
2551 break;
2552 }
2553 sigrenderer->entry++;
2554 }
2555 n--;
2556 }
2557 }
2558 }
2559
2560 sigrenderer->processrow++;
2561
2562 if (sigrenderer->processrow >= sigrenderer->n_rows) {
2563 IT_PATTERN *pattern;
2564 int n;
2565
2566 sigrenderer->processrow = sigrenderer->breakrow;
2567 sigrenderer->breakrow = 0;
2568
2569 for (;;) {
2570 sigrenderer->processorder++;
2571
2572 if (sigrenderer->processorder >= sigdata->n_orders) {
2573 sigrenderer->processorder = sigdata->restart_position;
2574 if (sigrenderer->processorder >= sigdata->n_orders) {
2575 /* Restarting beyond end. We'll loop for now. */
2576 sigrenderer->processorder = -1;
2577 continue;
2578 }
2579 }
2580
2581 n = sigdata->order[sigrenderer->processorder];
2582
2583 if (n < sigdata->n_patterns)
2584 break;
2585
2586#ifdef INVALID_ORDERS_END_SONG
2587 if (n != IT_ORDER_SKIP)
2588 sigrenderer->processorder = -1;
2589#else
2590 if (n == IT_ORDER_END)
2591 sigrenderer->processorder = -1;
2592#endif
2593 }
2594
2595 pattern = &sigdata->pattern[n];
2596
2597 sigrenderer->n_rows = pattern->n_rows;
2598
2599 if (sigrenderer->processrow >= sigrenderer->n_rows)
2600 sigrenderer->processrow = 0;
2601
2602/** WARNING - everything pertaining to a new pattern initialised? */
2603
2604 sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
2605 sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
2606
2607 if (sigrenderer->order >= sigrenderer->processorder) {
2608 if (sigrenderer->callbacks->loop) {
2609 if ((*sigrenderer->callbacks->loop)(sigrenderer->callbacks->loop_data))
2610 return 1;
2611 if (sigrenderer->speed == 0)
2612 goto speed0; /* I love goto */
2613 }
2614 }
2615 sigrenderer->order = sigrenderer->processorder;
2616
2617 n = sigrenderer->processrow;
2618 while (n) {
2619 while (sigrenderer->entry < sigrenderer->entry_end) {
2620 if (IT_IS_END_ROW(sigrenderer->entry)) {
2621 sigrenderer->entry++;
2622 break;
2623 }
2624 sigrenderer->entry++;
2625 }
2626 n--;
2627 }
2628 sigrenderer->row = sigrenderer->processrow;
2629 } else {
2630 if (sigrenderer->entry) {
2631 while (sigrenderer->entry < sigrenderer->entry_end) {
2632 if (IT_IS_END_ROW(sigrenderer->entry)) {
2633 sigrenderer->entry++;
2634 break;
2635 }
2636 sigrenderer->entry++;
2637 }
2638 sigrenderer->row++;
2639 } else {
2640 sigrenderer->entry = sigrenderer->entry_start;
2641 sigrenderer->row = 0;
2642 }
2643 }
2644
2645 reset_effects(sigrenderer);
2646
2647 {
2648 IT_ENTRY *entry = sigrenderer->entry;
2649
2650 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
2651 update_pattern_variables(sigrenderer, entry++);
2652 }
2653
2654 {
2655 IT_ENTRY *entry = sigrenderer->entry;
2656
2657 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
2658 if (process_entry(sigrenderer, entry++))
2659 return 1;
2660 }
2661
2662 if (!(sigdata->flags & IT_OLD_EFFECTS))
2663 update_smooth_effects(sigrenderer);
2664 } else {
2665 {
2666 IT_ENTRY *entry = sigrenderer->entry;
2667
2668 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
2669 process_effects(sigrenderer, entry++);
2670 /* Don't bother checking the return value; if there
2671 * was a pattern delay, there can't be a speed=0.
2672 */
2673 }
2674
2675 update_effects(sigrenderer);
2676 }
2677 } else {
2678 speed0:
2679 update_effects(sigrenderer);
2680 update_tick_counts(sigrenderer);
2681 }
2682
2683 process_all_playing(sigrenderer);
2684
2685 sigrenderer->time_left += TICK_TIME_DIVIDEND / sigrenderer->tempo;
2686
2687 return 0;
2688}
2689
2690
2691
2692int dumb_it_max_to_mix = 64;
2693
2694
2695
2696static float calculate_volume(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume)
2697{
2698 if (volume != 0) {
2699 int vol;
2700
2701 if (playing->channel->flags & IT_CHANNEL_MUTED)
2702 return 0;
2703
2704 if ((playing->channel->tremor_time & 192) == 128)
2705 return 0;
2706
2707 vol = it_sine[playing->tremolo_time];
2708 vol *= playing->tremolo_depth;
2709
2710 vol = (playing->volume << 5) + vol;
2711
2712 if (vol <= 0)
2713 return 0;
2714
2715 if (vol > 64 << 5)
2716 vol = 64 << 5;
2717
2718 volume *= vol; /* 64 << 5 */
2719 volume *= playing->sample->global_volume; /* 64 */
2720 volume *= playing->channel_volume; /* 64 */
2721 volume *= sigrenderer->globalvolume; /* 128 */
2722 volume *= sigrenderer->sigdata->mixing_volume; /* 128 */
2723 volume *= 1.0f / ((64 << 5) * 64.0f * 64.0f * 128.0f * 128.0f);
2724
2725 if (volume && playing->instrument) {
2726 if (playing->env_instrument->volume_envelope.flags & IT_ENVELOPE_ON) {
2727 volume *= envelope_get_y(&playing->env_instrument->volume_envelope, &playing->volume_envelope);
2728 volume *= 1.0f / (64 << IT_ENVELOPE_SHIFT);
2729 }
2730 volume *= playing->instrument->global_volume; /* 128 */
2731 volume *= playing->fadeoutcount; /* 1024 */
2732 volume *= 1.0f / (128.0f * 1024.0f);
2733 }
2734 }
2735
2736 return volume;
2737}
2738
2739
2740
2741static int apply_pan_envelope(IT_PLAYING *playing)
2742{
2743 int pan = playing->pan;
2744 if (pan <= 64 << IT_ENVELOPE_SHIFT && playing->env_instrument && (playing->env_instrument->pan_envelope.flags & IT_ENVELOPE_ON)) {
2745 int p = envelope_get_y(&playing->env_instrument->pan_envelope, &playing->pan_envelope);
2746 if (pan > 32 << IT_ENVELOPE_SHIFT)
2747 p *= (64 << IT_ENVELOPE_SHIFT) - pan;
2748 else
2749 p *= pan;
2750 pan += p >> (5 + IT_ENVELOPE_SHIFT);
2751 }
2752 return pan;
2753}
2754
2755
2756
2757/* Note: if a click remover is provided, and store_end_sample is set, then
2758 * the end point will be computed twice. This situation should not arise.
2759 */
2760static long render_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume, float delta, long pos, long size, sample_t **samples, int store_end_sample, int *left_to_mix)
2761{
2762 int pan;
2763
2764 long size_rendered;
2765
2766 if (playing->flags & IT_PLAYING_DEAD)
2767 return 0;
2768
2769 if (*left_to_mix <= 0)
2770 volume = 0;
2771
2772 pan = apply_pan_envelope(playing);
2773
2774#define RESAMPLERV(rv, resampler, dst, volume) \
2775{ \
2776 rv = dumb_resample(resampler, dst, size, volume, delta); \
2777 if (store_end_sample) \
2778 (dst)[rv] = RESAMPLE_VALUE(resampler, volume); \
2779}
2780
2781#define RESAMPLE(resampler, dst, volume) \
2782{ \
2783 int i; \
2784 RESAMPLERV(i, resampler, dst, volume); \
2785}
2786
2787#define RESAMPLE_VALUE(resampler, volume) \
2788 dumb_resample_get_current_sample(resampler, volume)
2789
2790 if (volume == 0) {
2791 size_rendered = dumb_resample(&playing->resampler[0], NULL, size, 0, delta);
2792 if (playing->sample->flags & IT_SAMPLE_STEREO)
2793 dumb_resample(&playing->resampler[1], NULL, size, 0, delta);
2794 } else {
2795 if (sigrenderer->n_channels == 2) {
2796 float vol = volume;
2797 DUMB_RESAMPLER start = playing->resampler[0];
2798 if (!IT_IS_SURROUND_SHIFTED(pan)) vol *= 2.0f - pan * (1.0f / (32 << IT_ENVELOPE_SHIFT));
2799 if (sigrenderer->click_remover && sigrenderer->click_remover[0])
2800 dumb_record_click(sigrenderer->click_remover[0], pos, RESAMPLE_VALUE(&playing->resampler[0], vol));
2801 RESAMPLERV(size_rendered, &playing->resampler[0], samples[0] + pos, vol);
2802 if (sigrenderer->click_remover && sigrenderer->click_remover[0])
2803 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], vol));
2804 vol = -vol;
2805 if (!IT_IS_SURROUND_SHIFTED(pan)) vol += 2.0f * volume;
2806 if (playing->sample->flags & IT_SAMPLE_STEREO) {
2807 if (sigrenderer->click_remover && sigrenderer->click_remover[1])
2808 dumb_record_click(sigrenderer->click_remover[1], pos, RESAMPLE_VALUE(&playing->resampler[1], vol));
2809 RESAMPLE(&playing->resampler[1], samples[1] + pos, vol);
2810 if (sigrenderer->click_remover && sigrenderer->click_remover[1])
2811 dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[1], vol));
2812 } else {
2813 playing->resampler[0] = start;
2814 if (sigrenderer->click_remover && sigrenderer->click_remover[1])
2815 dumb_record_click(sigrenderer->click_remover[1], pos, RESAMPLE_VALUE(&playing->resampler[0], vol));
2816 RESAMPLE(&playing->resampler[0], samples[1] + pos, vol);
2817 if (sigrenderer->click_remover && sigrenderer->click_remover[1])
2818 dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], vol));
2819 }
2820 } else {
2821 if (playing->sample->flags & IT_SAMPLE_STEREO) {
2822 float vol = 0.5f * volume;
2823 if (!IT_IS_SURROUND_SHIFTED(pan)) vol *= 2.0f - pan * (1.0f / (32 << IT_ENVELOPE_SHIFT));
2824 if (sigrenderer->click_remover && sigrenderer->click_remover[0]) {
2825 sample_t startstep, endstep;
2826 startstep = RESAMPLE_VALUE(&playing->resampler[0], vol);
2827 RESAMPLE(&playing->resampler[0], samples[0] + pos, vol);
2828 endstep = RESAMPLE_VALUE(&playing->resampler[0], vol);
2829 if (!IT_IS_SURROUND_SHIFTED(pan)) vol = 2.0f * volume - vol;
2830 startstep += RESAMPLE_VALUE(&playing->resampler[1], vol);
2831 RESAMPLERV(size_rendered, &playing->resampler[1], samples[0] + pos, vol);
2832 endstep += RESAMPLE_VALUE(&playing->resampler[1], vol);
2833 dumb_record_click(sigrenderer->click_remover[0], pos, startstep);
2834 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -endstep);
2835 } else {
2836 RESAMPLE(&playing->resampler[0], samples[0] + pos, vol);
2837 if (!IT_IS_SURROUND_SHIFTED(pan)) vol = 2.0f * volume - vol;
2838 RESAMPLERV(size_rendered, &playing->resampler[1], samples[0] + pos, vol);
2839 }
2840 } else {
2841 if (sigrenderer->click_remover && sigrenderer->click_remover[0])
2842 dumb_record_click(sigrenderer->click_remover[0], pos, RESAMPLE_VALUE(&playing->resampler[0], volume));
2843 RESAMPLERV(size_rendered, &playing->resampler[0], samples[0] + pos, volume);
2844 if (sigrenderer->click_remover && sigrenderer->click_remover[0])
2845 dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -RESAMPLE_VALUE(&playing->resampler[0], volume));
2846 }
2847 }
2848 (*left_to_mix)--;
2849 }
2850
2851 if (playing->resampler[0].dir == 0)
2852 playing->flags |= IT_PLAYING_DEAD;
2853
2854 return size_rendered;
2855}
2856
2857
2858
2859typedef struct IT_TO_MIX
2860{
2861 IT_PLAYING *playing;
2862 float volume;
2863}
2864IT_TO_MIX;
2865
2866
2867
2868static int it_to_mix_compare(const void *e1, const void *e2)
2869{
2870 if (((const IT_TO_MIX *)e1)->volume > ((const IT_TO_MIX *)e2)->volume)
2871 return -1;
2872
2873 if (((const IT_TO_MIX *)e1)->volume < ((const IT_TO_MIX *)e2)->volume)
2874 return 1;
2875
2876 return 0;
2877}
2878
2879
2880
2881static void apply_pitch_modifications(DUMB_IT_SIGDATA *sigdata, IT_PLAYING *playing, float *delta, int *cutoff)
2882{
2883 {
2884 int sample_vibrato_shift = it_sine[playing->sample_vibrato_time];
2885
2886 if (sigdata->flags & IT_WAS_AN_XM) {
2887 int depth = playing->sample->vibrato_depth; /* True depth */
2888 if (playing->sample->vibrato_rate) {
2889 depth *= playing->sample_vibrato_depth; /* Tick number */
2890 depth /= playing->sample->vibrato_rate; /* XM sweep */
2891 }
2892 sample_vibrato_shift *= depth;
2893 } else
2894 sample_vibrato_shift *= playing->sample_vibrato_depth >> 8;
2895
2896 sample_vibrato_shift >>= 4;
2897
2898 *delta *= (float)pow(DUMB_PITCH_BASE, sample_vibrato_shift);
2899 }
2900
2901 if (playing->env_instrument &&
2902 (playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_ON))
2903 {
2904 int p = envelope_get_y(&playing->env_instrument->pitch_envelope, &playing->pitch_envelope);
2905 if (playing->env_instrument->pitch_envelope.flags & IT_ENVELOPE_PITCH_IS_FILTER)
2906 *cutoff = (*cutoff * (p+(32<<IT_ENVELOPE_SHIFT))) >> (6 + IT_ENVELOPE_SHIFT);
2907 else
2908 *delta *= (float)pow(DUMB_PITCH_BASE, p >> (IT_ENVELOPE_SHIFT - 7));
2909 }
2910}
2911
2912
2913
2914static void render(DUMB_IT_SIGRENDERER *sigrenderer, float volume, float delta, long pos, long size, sample_t **samples)
2915{
2916 int i;
2917
2918 int n_to_mix = 0;
2919 IT_TO_MIX to_mix[DUMB_IT_TOTAL_CHANNELS];
2920 int left_to_mix = dumb_it_max_to_mix;
2921
2922 sample_t **samples_to_filter = NULL;
2923
2924 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2925 if (sigrenderer->channel[i].playing && !(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
2926 to_mix[n_to_mix].playing = sigrenderer->channel[i].playing;
2927 to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->channel[i].playing, volume);
2928 n_to_mix++;
2929 }
2930 }
2931
2932 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2933 if (sigrenderer->playing[i]) { /* Won't be dead; it would have been freed. */
2934 to_mix[n_to_mix].playing = sigrenderer->playing[i];
2935 to_mix[n_to_mix].volume = volume == 0 ? 0 : calculate_volume(sigrenderer, sigrenderer->playing[i], volume);
2936 n_to_mix++;
2937 }
2938 }
2939
2940 if (volume != 0)
2941 qsort(to_mix, n_to_mix, sizeof(IT_TO_MIX), &it_to_mix_compare);
2942
2943 for (i = 0; i < n_to_mix; i++) {
2944 IT_PLAYING *playing = to_mix[i].playing;
2945 float note_delta = delta * playing->delta;
2946 int cutoff = playing->filter_cutoff << IT_ENVELOPE_SHIFT;
2947
2948 apply_pitch_modifications(sigrenderer->sigdata, playing, &note_delta, &cutoff);
2949
2950 if (cutoff != 127 << IT_ENVELOPE_SHIFT || playing->filter_resonance != 0) {
2951 playing->true_filter_cutoff = cutoff;
2952 playing->true_filter_resonance = playing->filter_resonance;
2953 }
2954
2955 if (to_mix[i].volume && (playing->true_filter_cutoff != 127 << IT_ENVELOPE_SHIFT || playing->true_filter_resonance != 0)) {
2956 if (!samples_to_filter) {
2957 samples_to_filter = create_sample_buffer(sigrenderer->n_channels, size + 1);
2958 if (!samples_to_filter) {
2959 render_playing(sigrenderer, playing, 0, note_delta, pos, size, NULL, 0, &left_to_mix);
2960 continue;
2961 }
2962 }
2963 {
2964 long size_rendered;
2965 DUMB_CLICK_REMOVER **cr = sigrenderer->click_remover;
2966 dumb_silence(samples_to_filter[0], sigrenderer->n_channels * (size + 1));
2967 sigrenderer->click_remover = NULL;
2968 size_rendered = render_playing(sigrenderer, playing, to_mix[i].volume, note_delta, 0, size, samples_to_filter, 1, &left_to_mix);
2969 sigrenderer->click_remover = cr;
2970 it_filter(cr ? cr[0] : NULL, &playing->filter_state[0], samples[0], pos, samples_to_filter[0], size_rendered,
2971 65536.0f/delta, playing->true_filter_cutoff, playing->true_filter_resonance);
2972 if (sigrenderer->n_channels == 2)
2973 it_filter(cr ? cr[1] : NULL, &playing->filter_state[1], samples[1], pos, samples_to_filter[1], size_rendered,
2974 65536.0f/delta, playing->true_filter_cutoff, playing->true_filter_resonance);
2975 // warning: filtering is not prevented by low left_to_mix!
2976 }
2977 } else {
2978 it_reset_filter_state(&playing->filter_state[0]);
2979 it_reset_filter_state(&playing->filter_state[1]);
2980 render_playing(sigrenderer, playing, to_mix[i].volume, note_delta, pos, size, samples, 0, &left_to_mix);
2981 }
2982 }
2983
2984 destroy_sample_buffer(samples_to_filter);
2985
2986 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
2987 if (sigrenderer->channel[i].playing) {
2988 if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) {
2989 free(sigrenderer->channel[i].playing);
2990 sigrenderer->channel[i].playing = NULL;
2991 }
2992 }
2993 }
2994
2995 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
2996 if (sigrenderer->playing[i]) {
2997 if (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) {
2998 free(sigrenderer->playing[i]);
2999 sigrenderer->playing[i] = NULL;
3000 }
3001 }
3002 }
3003}
3004
3005
3006
3007static DUMB_IT_SIGRENDERER *init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_channels, int startorder, IT_CALLBACKS *callbacks, DUMB_CLICK_REMOVER **cr)
3008{
3009 DUMB_IT_SIGRENDERER *sigrenderer;
3010 int i;
3011
3012 if (startorder > sigdata->n_orders) {
3013 free(callbacks);
3014 dumb_destroy_click_remover_array(n_channels, cr);
3015 return NULL;
3016 }
3017
3018 sigrenderer = malloc(sizeof(*sigrenderer));
3019 if (!sigrenderer) {
3020 free(callbacks);
3021 dumb_destroy_click_remover_array(n_channels, cr);
3022 return NULL;
3023 }
3024
3025 sigrenderer->callbacks = callbacks;
3026 sigrenderer->click_remover = cr;
3027
3028 sigrenderer->sigdata = sigdata;
3029 sigrenderer->n_channels = n_channels;
3030 sigrenderer->globalvolume = sigdata->global_volume;
3031 sigrenderer->tempo = sigdata->tempo;
3032
3033 for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
3034 IT_CHANNEL *channel = &sigrenderer->channel[i];
3035#if IT_CHANNEL_MUTED != 1
3036#error this is wrong
3037#endif
3038 channel->flags = sigdata->channel_pan[i] >> 7;
3039 channel->volume = (sigdata->flags & IT_WAS_AN_XM) ? 0 : 64;
3040 channel->pan = sigdata->channel_pan[i] & 0x7F;
3041 channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
3042 channel->channelvolume = sigdata->channel_volume[i];
3043 channel->instrument = 0;
3044 channel->note = 0;
3045 channel->SFmacro = 0;
3046 channel->filter_cutoff = 127;
3047 channel->filter_resonance = 0;
3048 channel->xm_retrig = 0;
3049 channel->retrig_tick = 0;
3050 channel->tremor_time = 0;
3051 channel->midi_state = 0;
3052 channel->lastvolslide = 0;
3053 channel->lastDKL = 0;
3054 channel->lastEF = 0;
3055 channel->lastG = 0;
3056 channel->lastHspeed = 0;
3057 channel->lastHdepth = 0;
3058 channel->lastRspeed = 0;
3059 channel->lastRdepth = 0;
3060 channel->lastI = 0;
3061 channel->lastJ = 0;
3062 channel->lastN = 0;
3063 channel->lastO = 0;
3064 channel->high_offset = 0;
3065 channel->lastQ = 0;
3066 channel->lastS = 0;
3067 channel->pat_loop_row = 0;
3068 channel->pat_loop_count = 0;
3069 channel->lastW = 0;
3070 channel->xm_lastE1 = 0;
3071 channel->xm_lastE2 = 0;
3072 channel->xm_lastEA = 0;
3073 channel->xm_lastEB = 0;
3074 channel->xm_lastX1 = 0;
3075 channel->xm_lastX2 = 0;
3076 channel->playing = NULL;
3077 }
3078
3079 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
3080 sigrenderer->playing[i] = NULL;
3081
3082 sigrenderer->speed = sigdata->speed;
3083
3084 sigrenderer->processrow = 0;
3085 sigrenderer->breakrow = 0;
3086 sigrenderer->pat_loop_row = -1;
3087 sigrenderer->rowcount = 1;
3088
3089 reset_tick_counts(sigrenderer);
3090
3091 sigrenderer->tick = sigrenderer->speed;
3092
3093 {
3094 IT_PATTERN *pattern;
3095 int n;
3096
3097 sigrenderer->processorder = startorder;
3098 for (;;) {
3099 n = sigdata->order[sigrenderer->processorder];
3100
3101 if (n < sigdata->n_patterns)
3102 break;
3103
3104#ifdef INVALID_ORDERS_END_SONG
3105 if (n != IT_ORDER_SKIP)
3106#else
3107 if (n == IT_ORDER_END)
3108#endif
3109 {
3110 _dumb_it_end_sigrenderer(sigrenderer);
3111 return NULL;
3112 }
3113
3114 sigrenderer->processorder++;
3115 if (sigrenderer->processorder >= sigdata->n_orders)
3116 sigrenderer->processorder = 0;
3117 if (sigrenderer->processorder == startorder) {
3118 _dumb_it_end_sigrenderer(sigrenderer);
3119 return NULL;
3120 }
3121 }
3122
3123 pattern = &sigdata->pattern[n];
3124
3125 sigrenderer->n_rows = pattern->n_rows;
3126
3127/** WARNING - everything pertaining to a new pattern initialised? */
3128
3129 sigrenderer->entry = sigrenderer->entry_start = pattern->entry;
3130 sigrenderer->entry_end = sigrenderer->entry + pattern->n_entries;
3131
3132 sigrenderer->order = sigrenderer->processorder;
3133 sigrenderer->row = 0;
3134 }
3135
3136 reset_effects(sigrenderer);
3137
3138 {
3139 IT_ENTRY *entry = sigrenderer->entry;
3140
3141 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry))
3142 update_pattern_variables(sigrenderer, entry++);
3143 }
3144
3145 {
3146 IT_ENTRY *entry = sigrenderer->entry;
3147
3148 while (entry < sigrenderer->entry_end && !IT_IS_END_ROW(entry)) {
3149 if (process_entry(sigrenderer, entry++)) {
3150 /* Oops, that song ended quickly! */
3151 _dumb_it_end_sigrenderer(sigrenderer);
3152 return NULL;
3153 }
3154 }
3155 }
3156
3157 if (!(sigdata->flags & IT_OLD_EFFECTS))
3158 update_smooth_effects(sigrenderer);
3159
3160 process_all_playing(sigrenderer);
3161
3162 sigrenderer->time_left = TICK_TIME_DIVIDEND / sigrenderer->tempo;
3163 sigrenderer->sub_time_left = 0;
3164
3165 return sigrenderer;
3166}
3167
3168
3169
3170void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data)
3171{
3172 if (sigrenderer) {
3173 sigrenderer->callbacks->loop = callback;
3174 sigrenderer->callbacks->loop_data = data;
3175 }
3176}
3177
3178
3179
3180void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data)
3181{
3182 if (sigrenderer) {
3183 sigrenderer->callbacks->xm_speed_zero = callback;
3184 sigrenderer->callbacks->xm_speed_zero_data = data;
3185 }
3186}
3187
3188
3189
3190void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char byte), void *data)
3191{
3192 if (sigrenderer) {
3193 sigrenderer->callbacks->midi = callback;
3194 sigrenderer->callbacks->midi_data = data;
3195 }
3196}
3197
3198
3199
3200static IT_CALLBACKS *create_callbacks(void)
3201{
3202 IT_CALLBACKS *callbacks = malloc(sizeof(*callbacks));
3203 if (!callbacks) return NULL;
3204 callbacks->loop = NULL;
3205 callbacks->xm_speed_zero = NULL;
3206 callbacks->midi = NULL;
3207 return callbacks;
3208}
3209
3210
3211
3212static DUMB_IT_SIGRENDERER *dumb_it_init_sigrenderer(DUMB_IT_SIGDATA *sigdata, int n_channels, int startorder)
3213{
3214 IT_CALLBACKS *callbacks;
3215
3216 if (!sigdata) return NULL;
3217
3218 callbacks = create_callbacks();
3219 if (!callbacks) return NULL;
3220
3221 return init_sigrenderer(sigdata, n_channels, startorder, callbacks,
3222 dumb_create_click_remover_array(n_channels));
3223}
3224
3225
3226
3227DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder)
3228{
3229 DUMB_IT_SIGDATA *itsd = duh_get_it_sigdata(duh);
3230 DUMB_IT_SIGRENDERER *itsr = dumb_it_init_sigrenderer(itsd, n_channels, startorder);
3231 return duh_encapsulate_it_sigrenderer(itsr, n_channels, 0);
3232}
3233
3234
3235
3236static sigrenderer_t *it_start_sigrenderer(DUH *duh, sigdata_t *vsigdata, int n_channels, long pos)
3237{
3238 DUMB_IT_SIGDATA *sigdata = vsigdata;
3239 DUMB_IT_SIGRENDERER *sigrenderer;
3240
3241 (void)duh;
3242
3243 {
3244 IT_CALLBACKS *callbacks = create_callbacks();
3245 if (!callbacks) return NULL;
3246
3247 if (sigdata->checkpoint) {
3248 IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
3249 while (checkpoint->next && checkpoint->next->time < pos)
3250 checkpoint = checkpoint->next;
3251 sigrenderer = dup_sigrenderer(checkpoint->sigrenderer, n_channels, callbacks);
3252 if (!sigrenderer) return NULL;
3253 sigrenderer->click_remover = dumb_create_click_remover_array(n_channels);
3254 pos -= checkpoint->time;
3255 } else {
3256 sigrenderer = init_sigrenderer(sigdata, n_channels, 0, callbacks,
3257 dumb_create_click_remover_array(n_channels));
3258 if (!sigrenderer) return NULL;
3259 }
3260 }
3261
3262 for (;;) {
3263 if (sigrenderer->time_left >= pos)
3264 break;
3265
3266 render(sigrenderer, 0, 1.0f, 0, sigrenderer->time_left, NULL);
3267
3268 pos -= sigrenderer->time_left;
3269 sigrenderer->time_left = 0;
3270
3271 if (process_tick(sigrenderer)) {
3272 _dumb_it_end_sigrenderer(sigrenderer);
3273 return NULL;
3274 }
3275 }
3276
3277 render(sigrenderer, 0, 1.0f, 0, pos, NULL);
3278 sigrenderer->time_left -= pos;
3279
3280 /** WARNING - everything initialised? */
3281
3282 return sigrenderer;
3283}
3284
3285
3286
3287static long it_sigrenderer_get_samples(
3288 sigrenderer_t *vsigrenderer,
3289 float volume, float delta,
3290 long size, sample_t **samples
3291)
3292{
3293 DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer;
3294 long pos;
3295 int dt;
3296 long todo;
3297 LONG_LONG t;
3298
3299 if (sigrenderer->order < 0) return 0;
3300
3301 pos = 0;
3302 dt = (int)(delta * 65536.0f + 0.5f);
3303
3304 /* When samples is finally used in render_playing(), it won't be used if
3305 * volume is 0.
3306 */
3307 if (!samples) volume = 0;
3308
3309 for (;;) {
3310 todo = (long)((((LONG_LONG)sigrenderer->time_left << 16) | sigrenderer->sub_time_left) / dt);
3311
3312 if (todo >= size)
3313 break;
3314
3315 render(sigrenderer, volume, delta, pos, todo, samples);
3316
3317 pos += todo;
3318 size -= todo;
3319
3320 t = sigrenderer->sub_time_left - (LONG_LONG)todo * dt;
3321 sigrenderer->sub_time_left = (long)t & 65535;
3322 sigrenderer->time_left += (long)(t >> 16);
3323
3324 if (process_tick(sigrenderer)) {
3325 sigrenderer->order = -1;
3326 sigrenderer->row = -1;
3327 return pos;
3328 }
3329 }
3330
3331 render(sigrenderer, volume, delta, pos, size, samples);
3332
3333 pos += size;
3334
3335 t = sigrenderer->sub_time_left - (LONG_LONG)size * dt;
3336 sigrenderer->sub_time_left = (long)t & 65535;
3337 sigrenderer->time_left += (long)(t >> 16);
3338
3339 dumb_remove_clicks_array(sigrenderer->n_channels, sigrenderer->click_remover, samples, pos, 512.0f / delta);
3340
3341 return pos;
3342}
3343
3344
3345
3346static void it_sigrenderer_get_current_sample(sigrenderer_t *vsigrenderer, float volume, sample_t *samples)
3347{
3348 DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer;
3349 (void)volume; // for consideration: in any of these such functions, is 'volume' going to be required?
3350 dumb_click_remover_get_offset_array(sigrenderer->n_channels, sigrenderer->click_remover, samples);
3351}
3352
3353
3354
3355void _dumb_it_end_sigrenderer(sigrenderer_t *vsigrenderer)
3356{
3357 DUMB_IT_SIGRENDERER *sigrenderer = vsigrenderer;
3358
3359 int i;
3360
3361 if (sigrenderer) {
3362 for (i = 0; i < DUMB_IT_N_CHANNELS; i++)
3363 if (sigrenderer->channel[i].playing)
3364 free(sigrenderer->channel[i].playing);
3365
3366 for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
3367 if (sigrenderer->playing[i])
3368 free(sigrenderer->playing[i]);
3369
3370 dumb_destroy_click_remover_array(sigrenderer->n_channels, sigrenderer->click_remover);
3371
3372 if (sigrenderer->callbacks)
3373 free(sigrenderer->callbacks);
3374
3375 free(vsigrenderer);
3376 }
3377}
3378
3379
3380
3381DUH_SIGTYPE_DESC _dumb_sigtype_it = {
3382 SIGTYPE_IT,
3383 NULL,
3384 &it_start_sigrenderer,
3385 NULL,
3386 &it_sigrenderer_get_samples,
3387 &it_sigrenderer_get_current_sample,
3388 &_dumb_it_end_sigrenderer,
3389 &_dumb_it_unload_sigdata
3390};
3391
3392
3393
3394DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos)
3395{
3396 return duh_encapsulate_raw_sigrenderer(it_sigrenderer, &_dumb_sigtype_it, n_channels, pos);
3397}
3398
3399
3400
3401DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer)
3402{
3403 return duh_get_raw_sigrenderer(sigrenderer, SIGTYPE_IT);
3404}
3405
3406
3407
3408/* Values of 64 or more will access NNA channels here. */
3409void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state)
3410{
3411 IT_PLAYING *playing;
3412 int t; /* temporary var for holding accurate pan and filter cutoff */
3413 float delta;
3414 ASSERT(channel < DUMB_IT_TOTAL_CHANNELS);
3415 if (!sr) { state->sample = 0; return; }
3416 if (channel >= DUMB_IT_N_CHANNELS) {
3417 playing = sr->playing[channel - DUMB_IT_N_CHANNELS];
3418 if (!playing) { state->sample = 0; return; }
3419 } else {
3420 playing = sr->channel[channel].playing;
3421 if (!playing) { state->sample = 0; return; }
3422 }
3423
3424 if (playing->flags & IT_PLAYING_DEAD) { state->sample = 0; return; }
3425
3426 state->channel = playing->channel - sr->channel;
3427 state->sample = playing->sampnum;
3428 state->volume = calculate_volume(sr, playing, 1.0f);
3429
3430 t = apply_pan_envelope(playing);
3431 state->pan = (unsigned char)((t + 128) >> IT_ENVELOPE_SHIFT);
3432 state->subpan = (signed char)t;
3433
3434 delta = playing->delta * 65536.0f;
3435 t = playing->filter_cutoff << IT_ENVELOPE_SHIFT;
3436 apply_pitch_modifications(sr->sigdata, playing, &delta, &t);
3437 state->freq = (int)delta;
3438 if (t == 127 << IT_ENVELOPE_SHIFT && playing->filter_resonance == 0) {
3439 state->filter_resonance = playing->true_filter_resonance;
3440 t = playing->true_filter_cutoff;
3441 } else
3442 state->filter_resonance = playing->filter_resonance;
3443 state->filter_cutoff = (unsigned char)(t >> 8);
3444 state->filter_subcutoff = (unsigned char)t;
3445}
3446
3447
3448
3449int dumb_it_callback_terminate(void *data)
3450{
3451 (void)data;
3452 return 1;
3453}
3454
3455
3456
3457int dumb_it_callback_midi_block(void *data, int channel, unsigned char byte)
3458{
3459 (void)data;
3460 (void)channel;
3461 (void)byte;
3462 return 1;
3463}
3464
3465
3466
3467#define IT_CHECKPOINT_INTERVAL (30 * 65536) /* Half a minute */
3468
3469
3470
3471/* Returns the length of the module, up until it first loops. */
3472long _dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata)
3473{
3474 IT_CHECKPOINT *checkpoint = malloc(sizeof(*checkpoint));
3475 if (!checkpoint) return 0;
3476 checkpoint->time = 0;
3477 checkpoint->sigrenderer = dumb_it_init_sigrenderer(sigdata, 0, 0);
3478 if (!checkpoint->sigrenderer) {
3479 free(checkpoint);
3480 return 0;
3481 }
3482 checkpoint->sigrenderer->callbacks->loop = &dumb_it_callback_terminate;
3483 checkpoint->sigrenderer->callbacks->xm_speed_zero = &dumb_it_callback_terminate;
3484 sigdata->checkpoint = checkpoint;
3485
3486 for (;;) {
3487 long l;
3488 DUMB_IT_SIGRENDERER *sigrenderer = dup_sigrenderer(checkpoint->sigrenderer, 0, checkpoint->sigrenderer->callbacks);
3489 checkpoint->sigrenderer->callbacks = NULL;
3490 if (!sigrenderer) {
3491 checkpoint->next = NULL;
3492 return checkpoint->time;
3493 }
3494
3495 l = it_sigrenderer_get_samples(sigrenderer, 0, 1.0f, IT_CHECKPOINT_INTERVAL, NULL);
3496 if (l < IT_CHECKPOINT_INTERVAL) {
3497 _dumb_it_end_sigrenderer(sigrenderer);
3498 checkpoint->next = NULL;
3499 return checkpoint->time + l;
3500 }
3501
3502 checkpoint->next = malloc(sizeof(*checkpoint->next));
3503 if (!checkpoint->next) {
3504 _dumb_it_end_sigrenderer(sigrenderer);
3505 return checkpoint->time + IT_CHECKPOINT_INTERVAL;
3506 }
3507
3508 checkpoint->next->time = checkpoint->time + IT_CHECKPOINT_INTERVAL;
3509 checkpoint = checkpoint->next;
3510 checkpoint->sigrenderer = sigrenderer;
3511 }
3512}
diff --git a/apps/codecs/dumb/src/it/itunload.c b/apps/codecs/dumb/src/it/itunload.c
deleted file mode 100644
index 8f282bea2e..0000000000
--- a/apps/codecs/dumb/src/it/itunload.c
+++ /dev/null
@@ -1,71 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * itunload.c - Code to free an Impulse Tracker / / \ \
12 * module from memory. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21
22#include "dumb.h"
23#include "internal/it.h"
24
25
26
27void _dumb_it_unload_sigdata(sigdata_t *vsigdata)
28{
29 if (vsigdata) {
30 DUMB_IT_SIGDATA *sigdata = vsigdata;
31 int n;
32
33 if (sigdata->order)
34 free(sigdata->order);
35
36 if (sigdata->instrument)
37 free(sigdata->instrument);
38
39 if (sigdata->sample) {
40 for (n = 0; n < sigdata->n_samples; n++) {
41 if (sigdata->sample[n].left)
42 free(sigdata->sample[n].left);
43 if (sigdata->sample[n].right)
44 free(sigdata->sample[n].right);
45 }
46 free(sigdata->sample);
47 }
48
49 if (sigdata->pattern) {
50 for (n = 0; n < sigdata->n_patterns; n++)
51 if (sigdata->pattern[n].entry)
52 free(sigdata->pattern[n].entry);
53 free(sigdata->pattern);
54 }
55
56 if (sigdata->midi)
57 free(sigdata->midi);
58
59 {
60 IT_CHECKPOINT *checkpoint = sigdata->checkpoint;
61 while (checkpoint) {
62 IT_CHECKPOINT *next = checkpoint->next;
63 _dumb_it_end_sigrenderer(checkpoint->sigrenderer);
64 free(checkpoint);
65 checkpoint = next;
66 }
67 }
68
69 free(vsigdata);
70 }
71}
diff --git a/apps/codecs/dumb/src/it/loadmod.c b/apps/codecs/dumb/src/it/loadmod.c
deleted file mode 100644
index f7bbcb50e6..0000000000
--- a/apps/codecs/dumb/src/it/loadmod.c
+++ /dev/null
@@ -1,42 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * loadmod.c - Code to read a good old-fashioned / / \ \
12 * Amiga module file, opening and | < / \_
13 * closing it for you. | \/ /\ /
14 * \_ / > /
15 * By entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24
25/* dumb_load_mod(): loads a MOD file into a DUH struct, returning a pointer
26 * to the DUH struct. When you have finished with it, you must pass the
27 * pointer to unload_duh() so that the memory can be freed.
28 */
29DUH *dumb_load_mod(const char *filename)
30{
31 DUH *duh;
32 DUMBFILE *f = dumbfile_open(filename);
33
34 if (!f)
35 return NULL;
36
37 duh = dumb_read_mod(f);
38
39 dumbfile_close(f);
40
41 return duh;
42}
diff --git a/apps/codecs/dumb/src/it/loads3m.c b/apps/codecs/dumb/src/it/loads3m.c
deleted file mode 100644
index dfe6a9268e..0000000000
--- a/apps/codecs/dumb/src/it/loads3m.c
+++ /dev/null
@@ -1,42 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * loads3m.c - Code to read a ScreamTracker 3 / / \ \
12 * file, opening and closing it for | < / \_
13 * you. | \/ /\ /
14 * \_ / > /
15 * By entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24
25/* dumb_load_s3m(): loads an S3M file into a DUH struct, returning a pointer
26 * to the DUH struct. When you have finished with it, you must pass the
27 * pointer to unload_duh() so that the memory can be freed.
28 */
29DUH *dumb_load_s3m(const char *filename)
30{
31 DUH *duh;
32 DUMBFILE *f = dumbfile_open(filename);
33
34 if (!f)
35 return NULL;
36
37 duh = dumb_read_s3m(f);
38
39 dumbfile_close(f);
40
41 return duh;
42}
diff --git a/apps/codecs/dumb/src/it/loadxm.c b/apps/codecs/dumb/src/it/loadxm.c
deleted file mode 100644
index 9cee06d6ee..0000000000
--- a/apps/codecs/dumb/src/it/loadxm.c
+++ /dev/null
@@ -1,42 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * loadxm.c - Code to read a Fast Tracker II / / \ \
12 * file, opening and closing it for | < / \_
13 * you. | \/ /\ /
14 * \_ / > /
15 * By entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include "dumb.h"
21#include "internal/it.h"
22
23
24
25/* dumb_load_xm(): loads an XM file into a DUH struct, returning a pointer
26 * to the DUH struct. When you have finished with it, you must pass the
27 * pointer to unload_duh() so that the memory can be freed.
28 */
29DUH *dumb_load_xm(const char *filename)
30{
31 DUH *duh;
32 DUMBFILE *f = dumbfile_open(filename);
33
34 if (!f)
35 return NULL;
36
37 duh = dumb_read_xm(f);
38
39 dumbfile_close(f);
40
41 return duh;
42}
diff --git a/apps/codecs/dumb/src/it/readmod.c b/apps/codecs/dumb/src/it/readmod.c
deleted file mode 100644
index 452c8900a4..0000000000
--- a/apps/codecs/dumb/src/it/readmod.c
+++ /dev/null
@@ -1,594 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readmod.c - Code to read a good old-fashioned / / \ \
12 * Amiga module from an open file. | < / \_
13 * | \/ /\ /
14 * By Ben Davis. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29static int it_mod_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer)
30{
31 int pos;
32 int channel;
33 int row;
34 IT_ENTRY *entry;
35
36 pattern->n_rows = 64;
37
38 if (n_channels == 0) {
39 /* Read the first four channels, leaving gaps for the rest. */
40 for (pos = 0; pos < 64*8*4; pos += 8*4)
41 dumbfile_getnc(buffer + pos, 4*4, f);
42 /* Read the other channels into the gaps we left. */
43 for (pos = 4*4; pos < 64*8*4; pos += 8*4)
44 dumbfile_getnc(buffer + pos, 4*4, f);
45
46 n_channels = 8;
47 } else
48 dumbfile_getnc(buffer, 64 * n_channels * 4, f);
49
50 if (dumbfile_error(f))
51 return -1;
52
53 /* compute number of entries */
54 pattern->n_entries = 64; /* Account for the row end markers */
55 pos = 0;
56 for (row = 0; row < 64; row++) {
57 for (channel = 0; channel < n_channels; channel++) {
58 if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3])
59 pattern->n_entries++;
60 pos += 4;
61 }
62 }
63
64 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
65 if (!pattern->entry)
66 return -1;
67
68 entry = pattern->entry;
69 pos = 0;
70 for (row = 0; row < 64; row++) {
71 for (channel = 0; channel < n_channels; channel++) {
72 if (buffer[pos+0] | buffer[pos+1] | buffer[pos+2] | buffer[pos+3]) {
73 unsigned char sample = (buffer[pos+0] & 0xF0) | (buffer[pos+2] >> 4);
74 int period = ((int)(buffer[pos+0] & 0x0F) << 8) | buffer[pos+1];
75
76 entry->channel = channel;
77 entry->mask = 0;
78
79 if (period) {
80 int note;
81 entry->mask |= IT_ENTRY_NOTE;
82
83 /* frequency = (AMIGA_DIVISOR / 8) / (period * 2)
84 * C-1: period = 214 -> frequency = 16726
85 * so, set C5_speed to 16726
86 * and period = 214 should translate to C5 aka 60
87 * halve the period, go up an octive
88 *
89 * period = 214 / pow(DUMB_SEMITONE_BASE, note - 60)
90 * pow(DUMB_SEMITONE_BASE, note - 60) = 214 / period
91 * note - 60 = log(214/period) / log(DUMB_SEMITONE_BASE)
92 */
93 note = (int)floor(log(214.0/period) / log(DUMB_SEMITONE_BASE) + 60.5);
94 entry->note = MID(0, note, 119);
95 // or should we preserve the period?
96 //entry->note = buffer[pos+0] & 0x0F; /* High nibble */
97 //entry->volpan = buffer[pos+1]; /* Low byte */
98 // and what about finetune?
99 }
100
101 if (sample) {
102 entry->mask |= IT_ENTRY_INSTRUMENT;
103 entry->instrument = sample;
104 }
105
106 _dumb_it_xm_convert_effect(buffer[pos+2] & 0x0F, buffer[pos+3], entry);
107
108 entry++;
109 }
110 pos += 4;
111 }
112 IT_SET_END_ROW(entry);
113 entry++;
114 }
115
116 return 0;
117}
118
119
120
121/* This function does not skip the name (22 bytes); it is assumed the caller
122 * has already done that.
123 */
124static int it_mod_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
125{
126 int finetune;
127
128/**
129 21 22 Chars Sample 1 name. If the name is not a full
130 22 chars in length, it will be null
131 terminated.
132
133If
134the sample name begins with a '#' character (ASCII $23 (35)) then this is
135assumed not to be an instrument name, and is probably a message.
136*/
137 sample->length = dumbfile_mgetw(f) << 1;
138 finetune = (signed char)(dumbfile_getc(f) << 4) >> 4; /* signed nibble */
139/** Each finetune step changes the note 1/8th of a semitone. */
140 sample->global_volume = 64;
141 sample->default_volume = dumbfile_getc(f); // Should we be setting global_volume to this instead?
142 sample->loop_start = dumbfile_mgetw(f) << 1;
143 sample->loop_end = sample->loop_start + (dumbfile_mgetw(f) << 1);
144/**
145Once this sample has been played completely from beginning
146to end, if the repeat length (next field) is greater than two bytes it
147will loop back to this position in the sample and continue playing. Once
148it has played for the repeat length, it continues to loop back to the
149repeat start offset. This means the sample continues playing until it is
150told to stop.
151*/
152
153 if (sample->length <= 0) {
154 sample->flags = 0;
155 return 0;
156 }
157
158 sample->flags = IT_SAMPLE_EXISTS;
159
160 sample->default_pan = 0;
161 sample->C5_speed = (long)(16726.0*pow(DUMB_PITCH_BASE, finetune*32));
162 // the above line might be wrong
163
164 if (sample->loop_end > sample->length)
165 sample->loop_end = sample->length;
166
167 if (sample->loop_end - sample->loop_start > 2)
168 sample->flags |= IT_SAMPLE_LOOP;
169
170 sample->vibrato_speed = 0;
171 sample->vibrato_depth = 0;
172 sample->vibrato_rate = 0;
173 sample->vibrato_waveform = 0; // do we have to set _all_ these?
174
175 return dumbfile_error(f);
176}
177
178
179
180static int it_mod_read_sample_data(IT_SAMPLE *sample, DUMBFILE *f)
181{
182 long i;
183 long truncated_size;
184
185 /* let's get rid of the sample data coming after the end of the loop */
186 if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
187 truncated_size = sample->length - sample->loop_end;
188 sample->length = sample->loop_end;
189 } else {
190 truncated_size = 0;
191 }
192
193 sample->left = malloc(sample->length * sizeof(*sample->left));
194
195 if (!sample->left)
196 return -1;
197
198 /* Sample data are stored in "8-bit two's compliment format" (sic). */
199 for (i = 0; i < sample->length; i++)
200 sample->left[i] = (int)(signed char)dumbfile_getc(f) << 16;
201
202 /* skip truncated data */
203 dumbfile_skip(f, truncated_size);
204 // Should we be truncating it?
205
206 if (dumbfile_error(f))
207 return -1;
208
209 return 0;
210}
211
212
213
214typedef struct BUFFERED_MOD BUFFERED_MOD;
215
216struct BUFFERED_MOD
217{
218 unsigned char *buffered;
219 long ptr, len;
220 DUMBFILE *remaining;
221};
222
223
224
225static int buffer_mod_skip(void *f, long n)
226{
227 BUFFERED_MOD *bm = f;
228 if (bm->buffered) {
229 bm->ptr += n;
230 if (bm->ptr >= bm->len) {
231 free(bm->buffered);
232 bm->buffered = NULL;
233 return dumbfile_skip(bm->remaining, bm->ptr - bm->len);
234 }
235 return 0;
236 }
237 return dumbfile_skip(bm->remaining, n);
238}
239
240
241
242static int buffer_mod_getc(void *f)
243{
244 BUFFERED_MOD *bm = f;
245 if (bm->buffered) {
246 int rv = bm->buffered[bm->ptr++];
247 if (bm->ptr >= bm->len) {
248 free(bm->buffered);
249 bm->buffered = NULL;
250 }
251 return rv;
252 }
253 return dumbfile_getc(bm->remaining);
254}
255
256
257
258static long buffer_mod_getnc(char *ptr, long n, void *f)
259{
260 BUFFERED_MOD *bm = f;
261 if (bm->buffered) {
262 int left = bm->len - bm->ptr;
263 if (n >= left) {
264 int rv;
265 memcpy(ptr, bm->buffered + bm->ptr, left);
266 free(bm->buffered);
267 bm->buffered = NULL;
268 rv = dumbfile_getnc(ptr + left, n - left, bm->remaining);
269 return left + MAX(rv, 0);
270 }
271 memcpy(ptr, bm->buffered + bm->ptr, n);
272 bm->ptr += n;
273 return n;
274 }
275 return dumbfile_getnc(ptr, n, bm->remaining);
276}
277
278
279
280static void buffer_mod_close(void *f)
281{
282 BUFFERED_MOD *bm = f;
283 if (bm->buffered) free(bm->buffered);
284 /* Do NOT close bm->remaining */
285 free(f);
286}
287
288
289
290DUMBFILE_SYSTEM buffer_mod_dfs = {
291 NULL,
292 &buffer_mod_skip,
293 &buffer_mod_getc,
294 &buffer_mod_getnc,
295 &buffer_mod_close
296};
297
298
299
300#define MOD_FFT_OFFSET (20 + 31*(22+2+1+1+2+2) + 1 + 1 + 128)
301
302static DUMBFILE *dumbfile_buffer_mod(DUMBFILE *f, unsigned long *fft)
303{
304 BUFFERED_MOD *bm = malloc(sizeof(*bm));
305 if (!bm) return NULL;
306
307 bm->buffered = malloc(MOD_FFT_OFFSET + 4);
308 if (!bm->buffered) {
309 free(bm);
310 return NULL;
311 }
312
313 bm->len = dumbfile_getnc(bm->buffered, MOD_FFT_OFFSET + 4, f);
314
315 if (bm->len > 0) {
316 if (bm->len >= MOD_FFT_OFFSET + 4)
317 *fft = (unsigned long)bm->buffered[MOD_FFT_OFFSET ] << 24
318 | (unsigned long)bm->buffered[MOD_FFT_OFFSET+1] << 16
319 | (unsigned long)bm->buffered[MOD_FFT_OFFSET+2] << 8
320 | (unsigned long)bm->buffered[MOD_FFT_OFFSET+3];
321 else
322 *fft = 0;
323 bm->ptr = 0;
324 } else {
325 free(bm->buffered);
326 bm->buffered = NULL;
327 }
328
329 bm->remaining = f;
330
331 return dumbfile_open_ex(bm, &buffer_mod_dfs);
332}
333
334
335
336static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f)
337{
338 DUMB_IT_SIGDATA *sigdata;
339 int n_channels;
340 int i;
341 unsigned long fft;
342
343 f = dumbfile_buffer_mod(f, &fft);
344 if (!f)
345 return NULL;
346
347 /**
348 1 20 Chars Title of the song. If the title is not a
349 full 20 chars in length, it will be null-
350 terminated.
351 */
352 if (dumbfile_skip(f, 20)) {
353 dumbfile_close(f);
354 return NULL;
355 }
356
357 sigdata = malloc(sizeof(*sigdata));
358 if (!sigdata) {
359 dumbfile_close(f);
360 return NULL;
361 }
362
363 sigdata->n_samples = 31;
364
365 switch (fft) {
366 case DUMB_ID('M','.','K','.'):
367 case DUMB_ID('M','!','K','!'):
368 case DUMB_ID('M','&','K','!'):
369 case DUMB_ID('N','.','T','.'):
370 case DUMB_ID('F','L','T','4'):
371 n_channels = 4;
372 break;
373 case DUMB_ID('F','L','T','8'):
374 n_channels = 0;
375 /* 0 indicates a special case; two four-channel patterns must be
376 * combined into one eight-channel pattern. Pattern indexes must
377 * be halved. Why oh why do they obfuscate so?
378 */
379 for (i = 0; i < 128; i++)
380 sigdata->order[i] >>= 1;
381 break;
382 case DUMB_ID('C','D','8','1'):
383 case DUMB_ID('O','C','T','A'):
384 case DUMB_ID('O','K','T','A'):
385 n_channels = 8;
386 break;
387 case DUMB_ID('1','6','C','N'):
388 n_channels = 16;
389 break;
390 case DUMB_ID('3','2','C','N'):
391 n_channels = 32;
392 break;
393 default:
394 /* If we get an illegal tag, assume 4 channels 15 samples. */
395 if ((fft & 0x0000FFFFL) == DUMB_ID(0,0,'C','H')) {
396 if (fft >= '1' << 24 && fft < '4' << 24) {
397 n_channels = ((fft & 0x00FF0000L) >> 16) - '0';
398 if ((unsigned int)n_channels >= 10) {
399 /* Rightmost character wasn't a digit. */
400 n_channels = 4;
401 sigdata->n_samples = 15;
402 } else {
403 n_channels += (((fft & 0xFF000000L) >> 24) - '0') * 10;
404 /* MODs should really only go up to 32 channels, but we're lenient. */
405 if ((unsigned int)(n_channels - 1) >= DUMB_IT_N_CHANNELS - 1) {
406 /* No channels or too many? Can't be right... */
407 n_channels = 4;
408 sigdata->n_samples = 15;
409 }
410 }
411 } else {
412 n_channels = 4;
413 sigdata->n_samples = 15;
414 }
415 } else if ((fft & 0x00FFFFFFL) == DUMB_ID(0,'C','H','N')) {
416 n_channels = (fft >> 24) - '0';
417 if ((unsigned int)(n_channels - 1) >= 9) {
418 /* Character was '0' or it wasn't a digit */
419 n_channels = 4;
420 sigdata->n_samples = 15;
421 }
422 } else if ((fft & 0xFFFFFF00L) == DUMB_ID('T','D','Z',0)) {
423 n_channels = (fft & 0x000000FFL) - '0';
424 if ((unsigned int)(n_channels - 1) >= 9) {
425 /* We've been very lenient, given that it should have
426 * been 1, 2 or 3, but this MOD has been very naughty and
427 * must be punished.
428 */
429 n_channels = 4;
430 sigdata->n_samples = 15;
431 }
432 } else {
433 n_channels = 4;
434 sigdata->n_samples = 15;
435 }
436 }
437
438 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
439 if (!sigdata->sample) {
440 free(sigdata);
441 dumbfile_close(f);
442 return NULL;
443 }
444
445 sigdata->order = NULL;
446 sigdata->instrument = NULL;
447 sigdata->pattern = NULL;
448 sigdata->midi = NULL;
449 sigdata->checkpoint = NULL;
450
451 for (i = 0; i < sigdata->n_samples; i++)
452 sigdata->sample[i].right = sigdata->sample[i].left = NULL;
453
454 for (i = 0; i < sigdata->n_samples; i++) {
455 if (dumbfile_skip(f, 22) ||
456 it_mod_read_sample_header(&sigdata->sample[i], f))
457 {
458 _dumb_it_unload_sigdata(sigdata);
459 dumbfile_close(f);
460 return NULL;
461 }
462 }
463
464 sigdata->n_orders = dumbfile_getc(f);
465 sigdata->restart_position = dumbfile_getc(f);
466 // what if this is >= 127? what about with Fast Tracker II?
467
468 if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
469 _dumb_it_unload_sigdata(sigdata);
470 dumbfile_close(f);
471 return NULL;
472 }
473
474 //if (sigdata->restart_position >= sigdata->n_orders)
475 //sigdata->restart_position = 0;
476
477 sigdata->order = malloc(128); /* We may need to scan the extra ones! */
478 if (!sigdata->order) {
479 _dumb_it_unload_sigdata(sigdata);
480 dumbfile_close(f);
481 return NULL;
482 }
483 if (dumbfile_getnc(sigdata->order, 128, f) < 128) {
484 _dumb_it_unload_sigdata(sigdata);
485 dumbfile_close(f);
486 return NULL;
487 }
488
489 /* "The old NST format contains only 15 samples (instead of 31). Further
490 * it doesn't contain a file format tag (id). So Pattern data offset is
491 * at 20+15*30+1+1+128."
492 * - Then I shall assume the File Format Tag never exists if there are
493 * only 15 samples. I hope this isn't a faulty assumption...
494 */
495 if (sigdata->n_samples == 31)
496 dumbfile_skip(f, 4);
497
498 /* Work out how many patterns there are. */
499 sigdata->n_patterns = -1;
500 for (i = 0; i < 128; i++)
501 if (sigdata->n_patterns < sigdata->order[i])
502 sigdata->n_patterns = sigdata->order[i];
503 sigdata->n_patterns++;
504
505 /* May as well try to save a tiny bit of memory. */
506 if (sigdata->n_orders < 128) {
507 unsigned char *order = realloc(sigdata->order, sigdata->n_orders);
508 if (order) sigdata->order = order;
509 }
510
511 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
512 if (!sigdata->pattern) {
513 _dumb_it_unload_sigdata(sigdata);
514 dumbfile_close(f);
515 return NULL;
516 }
517 for (i = 0; i < sigdata->n_patterns; i++)
518 sigdata->pattern[i].entry = NULL;
519
520 /* Read in the patterns */
521 {
522 unsigned char *buffer = malloc(256 * n_channels); /* 64 rows * 4 bytes */
523 if (!buffer) {
524 _dumb_it_unload_sigdata(sigdata);
525 dumbfile_close(f);
526 return NULL;
527 }
528 for (i = 0; i < sigdata->n_patterns; i++) {
529 if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) {
530 free(buffer);
531 _dumb_it_unload_sigdata(sigdata);
532 dumbfile_close(f);
533 return NULL;
534 }
535 }
536 free(buffer);
537 }
538
539 /* And finally, the sample data */
540 for (i = 0; i < sigdata->n_samples; i++) {
541 if (it_mod_read_sample_data(&sigdata->sample[i], f)) {
542 _dumb_it_unload_sigdata(sigdata);
543 dumbfile_close(f);
544 return NULL;
545 }
546 }
547
548 dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */
549 /* The DUMBFILE originally passed to our function is intact. */
550
551 /* Now let's initialise the remaining variables, and we're done! */
552 sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
553
554 sigdata->global_volume = 128;
555 sigdata->mixing_volume = 48;
556 /* We want 50 ticks per second; 50/6 row advances per second;
557 * 50*10=500 row advances per minute; 500/4=125 beats per minute.
558 */
559 sigdata->speed = 6;
560 sigdata->tempo = 125;
561 sigdata->pan_separation = 128;
562
563 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
564
565 for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
566 sigdata->channel_pan[i+0] = 16;
567 sigdata->channel_pan[i+1] = 48;
568 sigdata->channel_pan[i+2] = 48;
569 sigdata->channel_pan[i+3] = 16;
570 }
571
572 _dumb_it_fix_invalid_orders(sigdata);
573
574 return sigdata;
575}
576
577
578
579DUH *dumb_read_mod(DUMBFILE *f)
580{
581 sigdata_t *sigdata;
582 long length;
583
584 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
585
586 sigdata = it_mod_load_sigdata(f);
587
588 if (!sigdata)
589 return NULL;
590
591 length = _dumb_it_build_checkpoints(sigdata);
592
593 return make_duh(length, 1, &descptr, &sigdata);
594}
diff --git a/apps/codecs/dumb/src/it/reads3m.c b/apps/codecs/dumb/src/it/reads3m.c
deleted file mode 100644
index 22152c8ff9..0000000000
--- a/apps/codecs/dumb/src/it/reads3m.c
+++ /dev/null
@@ -1,668 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * reads3m.c - Code to read a ScreamTracker 3 / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * By entheh. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20// IT_STEREO... :o
21#include <stdlib.h>
22#include <string.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29/** WARNING: this is duplicated in itread.c */
30static int it_seek(DUMBFILE *f, long offset)
31{
32 long pos = dumbfile_pos(f);
33
34 if (pos > offset)
35 return -1;
36
37 if (pos < offset)
38 if (dumbfile_skip(f, offset - pos))
39 return -1;
40
41 return 0;
42}
43
44
45
46static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, DUMBFILE *f)
47{
48 unsigned char type;
49 int flags;
50
51 type = dumbfile_getc(f);
52
53 if (type > 1) {
54 /** WARNING: no adlib support */
55 }
56
57 /* Skip DOS Filename */
58 dumbfile_skip(f, 13);
59
60 *offset = dumbfile_igetw(f) << 4;
61
62 sample->length = dumbfile_igetl(f);
63 sample->loop_start = dumbfile_igetl(f);
64 sample->loop_end = dumbfile_igetl(f);
65
66 sample->default_volume = dumbfile_getc(f);
67
68 dumbfile_skip(f, 1);
69
70 if (dumbfile_getc(f) != 0)
71 /* Sample is packed apparently (or error reading from file). We don't
72 * know how to read packed samples.
73 */
74 return -1;
75
76 flags = dumbfile_getc(f);
77
78 sample->C5_speed = dumbfile_igetl(f) << 1;
79
80 /* Skip four unused bytes, three internal variables and sample name. */
81 dumbfile_skip(f, 4+2+2+4+28);
82
83 if (type == 0) {
84 /* Looks like no-existy. Anyway, there's for sure no 'SCRS'... */
85 sample->flags &= ~IT_SAMPLE_EXISTS;
86 return dumbfile_error(f);
87 }
88
89 if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','S'))
90 return -1;
91
92 sample->global_volume = 64;
93
94 sample->flags = IT_SAMPLE_EXISTS;
95 if (flags & 1) sample->flags |= IT_SAMPLE_LOOP;
96 if (flags & 2) sample->flags |= IT_SAMPLE_STEREO;
97 if (flags & 4) sample->flags |= IT_SAMPLE_16BIT;
98
99 sample->default_pan = 0; // 0 = don't use, or 160 = centre?
100
101 if (sample->length <= 0)
102 sample->flags &= ~IT_SAMPLE_EXISTS;
103 else if (sample->flags & IT_SAMPLE_LOOP) {
104 if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
105 sample->flags &= ~IT_SAMPLE_LOOP;
106 else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end)
107 sample->flags &= ~IT_SAMPLE_LOOP;
108 else
109 /* ScreamTracker seems not to save what comes after the loop end
110 * point, but rather to assume it is a duplicate of what comes at
111 * the loop start point. I am not completely sure of this though.
112 * It is easy to evade; simply truncate the sample.
113 */
114 sample->length = sample->loop_end;
115 }
116
117
118 //Do we need to set all these?
119 sample->vibrato_speed = 0;
120 sample->vibrato_depth = 0;
121 sample->vibrato_rate = 0;
122 sample->vibrato_waveform = IT_VIBRATO_SINE;
123
124 return dumbfile_error(f);
125}
126
127
128
129static int it_s3m_read_sample_data(IT_SAMPLE *sample, int ffi, DUMBFILE *f)
130{
131 long n;
132
133 sample->left = malloc(sample->length * sizeof(*sample->left));
134 if (!sample->left)
135 return -1;
136
137 if (sample->flags & IT_SAMPLE_STEREO) {
138 sample->right = malloc(sample->length * sizeof(*sample->right));
139 if (!sample->right)
140 return -1;
141 }
142
143 if (sample->flags & IT_SAMPLE_STEREO) {
144 if (sample->flags & IT_SAMPLE_16BIT) {
145 for (n = 0; n < sample->length; n++)
146 sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
147 for (n = 0; n < sample->length; n++)
148 sample->right[n] = (int)(signed short)dumbfile_igetw(f) << 8;
149 } else {
150 for (n = 0; n < sample->length; n++)
151 sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
152 for (n = 0; n < sample->length; n++)
153 sample->right[n] = (int)(signed char)dumbfile_getc(f) << 16;
154 }
155 } else if (sample->flags & IT_SAMPLE_16BIT)
156 for (n = 0; n < sample->length; n++)
157 sample->left[n] = (int)(signed short)dumbfile_igetw(f) << 8;
158 else
159 for (n = 0; n < sample->length; n++)
160 sample->left[n] = (int)(signed char)dumbfile_getc(f) << 16;
161
162 if (dumbfile_error(f))
163 return -1;
164
165 if (ffi != 1) {
166 /* Convert to signed. */
167 for (n = 0; n < sample->length; n++)
168 sample->left[n] ^= 0xFF800000;
169
170 if (sample->right)
171 for (n = 0; n < sample->length; n++)
172 sample->right[n] ^= 0xFF800000;
173 }
174
175 return 0;
176}
177
178
179
180static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
181{
182 int buflen = 0;
183 int bufpos = 0;
184
185 IT_ENTRY *entry;
186
187 unsigned char channel;
188
189 /* Haha, this is hilarious!
190 *
191 * Well, after some experimentation, it seems that different S3M writers
192 * define the format in different ways. The S3M docs say that the first
193 * two bytes hold the "length of [the] packed pattern", and the packed
194 * pattern data follow. Judging by the contents of ARMANI.S3M, packaged
195 * with ScreamTracker itself, the measure of length _includes_ the two
196 * bytes used to store the length; in other words, we should read
197 * (length - 2) more bytes. However, aryx.s3m, packaged with ModPlug
198 * Tracker, excludes these two bytes, so (length) more bytes must be
199 * read.
200 *
201 * Call me crazy, but I just find it insanely funny that the format was
202 * misunderstood in this way :D
203 *
204 * Now we can't just risk reading two extra bytes, because then we
205 * overshoot, and DUMBFILEs don't support backward seeking (for a good
206 * reason). Luckily, there is a way. We can read the data little by
207 * little, and stop when we have 64 rows in memory. Provided we protect
208 * against buffer overflow, this method should work with all sensibly
209 * written S3M files. If you find one for which it does not work, please
210 * let me know at entheh@users.sf.net so I can look at it.
211 */
212
213 /* Discard the length. */
214 dumbfile_skip(f, 2);
215
216 if (dumbfile_error(f))
217 return -1;
218
219 pattern->n_rows = 0;
220 pattern->n_entries = 0;
221
222 /* Read in the pattern data, little by little, and work out how many
223 * entries we need room for. Sorry, but this is just so funny...
224 */
225 for (;;) {
226 unsigned char b = buffer[buflen++] = dumbfile_getc(f);
227
228#if 1
229 static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
230 channel = b & 31;
231 b >>= 5;
232 pattern->n_entries++;
233 if (b) {
234 if (buflen + (signed char)used[b] >= 65536) return -1;
235 dumbfile_getnc((char *)buffer + buflen, used[b], f);
236 buflen += used[b];
237 } else {
238 /* End of row */
239 if (++pattern->n_rows == 64) break;
240 if (buflen >= 65536) return -1;
241 }
242#else
243 if (b == 0) {
244 /* End of row */
245 pattern->n_entries++;
246 if (++pattern->n_rows == 64) break;
247 if (buflen >= 65536) return -1;
248 } else {
249 static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
250 channel = b & 31;
251 b >>= 5;
252 if (b) {
253 pattern->n_entries++;
254 if (buflen + used[b] >= 65536) return -1;
255 dumbfile_getnc(buffer + buflen, used[b], f);
256 buflen += used[b];
257 }
258 }
259#endif
260
261 /* We have ensured that buflen < 65536 at this point, so it is safe
262 * to iterate and read at least one more byte without checking.
263 * However, now would be a good time to check for errors reading from
264 * the file.
265 */
266
267 if (dumbfile_error(f))
268 return -1;
269 }
270
271 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
272
273 if (!pattern->entry)
274 return -1;
275
276 entry = pattern->entry;
277
278 while (bufpos < buflen) {
279 unsigned char b = buffer[bufpos++];
280
281#if 1
282 if (!(b & ~31))
283#else
284 if (b == 0)
285#endif
286 {
287 /* End of row */
288 IT_SET_END_ROW(entry);
289 entry++;
290 continue;
291 }
292
293 channel = b & 31;
294
295 if (b & 224) {
296 entry->mask = 0;
297 entry->channel = channel;
298
299 if (b & 32) {
300 unsigned char n = buffer[bufpos++];
301 if (n != 255) {
302 if (n == 254)
303 entry->note = IT_NOTE_CUT;
304 else
305 entry->note = (n >> 4) * 12 + (n & 15);
306 entry->mask |= IT_ENTRY_NOTE;
307 }
308
309 entry->instrument = buffer[bufpos++];
310 if (entry->instrument)
311 entry->mask |= IT_ENTRY_INSTRUMENT;
312 }
313
314 if (b & 64) {
315 entry->volpan = buffer[bufpos++];
316 if (entry->volpan != 255)
317 entry->mask |= IT_ENTRY_VOLPAN;
318 }
319
320 if (b & 128) {
321 entry->effect = buffer[bufpos++];
322 entry->effectvalue = buffer[bufpos++];
323 if (entry->effect != 255) {
324 entry->mask |= IT_ENTRY_EFFECT;
325 if (entry->effect == IT_BREAK_TO_ROW)
326 entry->effectvalue -= (entry->effectvalue >> 4) * 6;
327 }
328 /** WARNING: ARGH! CONVERT TEH EFFECTS!@~ */
329 }
330
331 entry++;
332 }
333 }
334
335 ASSERT(entry == pattern->entry + pattern->n_entries);
336
337 return 0;
338}
339
340
341
342/** WARNING: this is duplicated in itread.c - also bad practice to use the same struct name unless they are unified in a header */
343/* Currently we assume the sample data are stored after the sample headers in
344 * module files. This assumption may be unjustified; let me know if you have
345 * trouble.
346 */
347
348#define IT_COMPONENT_INSTRUMENT 1
349#define IT_COMPONENT_PATTERN 2
350#define IT_COMPONENT_SAMPLE 3
351
352typedef struct IT_COMPONENT
353{
354 unsigned char type;
355 unsigned char n;
356 long offset;
357 short sampfirst; /* component[sampfirst] = first sample data after this */
358 short sampnext; /* sampnext is used to create linked lists of sample data */
359}
360IT_COMPONENT;
361
362
363
364static int it_component_compare(const void *e1, const void *e2)
365{
366 return ((const IT_COMPONENT *)e1)->offset -
367 ((const IT_COMPONENT *)e2)->offset;
368}
369
370
371
372static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f)
373{
374 DUMB_IT_SIGDATA *sigdata;
375
376 int flags, cwtv, ffi;
377 int default_pan_present;
378
379 IT_COMPONENT *component;
380 int n_components = 0;
381
382 int n;
383
384 unsigned char *buffer;
385
386 /* Skip song name. */
387 if (dumbfile_skip(f, 28)) return NULL;
388
389 if (dumbfile_getc(f) != 0x1A) return NULL;
390 if (dumbfile_getc(f) != 16) return NULL;
391
392 if (dumbfile_skip(f, 2)) return NULL;
393
394 sigdata = malloc(sizeof(*sigdata));
395
396 if (!sigdata)
397 return NULL;
398
399 sigdata->order = NULL;
400 sigdata->instrument = NULL;
401 sigdata->sample = NULL;
402 sigdata->pattern = NULL;
403 sigdata->midi = NULL;
404 sigdata->checkpoint = NULL;
405
406 sigdata->n_orders = dumbfile_igetw(f);
407 sigdata->n_instruments = 0;
408 sigdata->n_samples = dumbfile_igetw(f);
409 sigdata->n_patterns = dumbfile_igetw(f);
410
411 if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_samples > 256 || sigdata->n_patterns > 256) {
412 _dumb_it_unload_sigdata(sigdata);
413 return NULL;
414 }
415
416 sigdata->order = malloc(sigdata->n_orders);
417 if (!sigdata->order) {
418 _dumb_it_unload_sigdata(sigdata);
419 return NULL;
420 }
421
422 if (sigdata->n_samples) {
423 sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
424 if (!sigdata->sample) {
425 _dumb_it_unload_sigdata(sigdata);
426 return NULL;
427 }
428 for (n = 0; n < sigdata->n_samples; n++)
429 sigdata->sample[n].right = sigdata->sample[n].left = NULL;
430 }
431
432 if (sigdata->n_patterns) {
433 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
434 if (!sigdata->pattern) {
435 _dumb_it_unload_sigdata(sigdata);
436 return NULL;
437 }
438 for (n = 0; n < sigdata->n_patterns; n++)
439 sigdata->pattern[n].entry = NULL;
440 }
441
442 flags = dumbfile_igetw(f);
443
444 cwtv = dumbfile_igetw(f);
445
446 if (cwtv == 0x1300) {
447 /** WARNING: volume slides on every frame */
448 }
449
450 ffi = dumbfile_igetw(f);
451
452 /** WARNING: which ones? */
453 sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
454
455 if (dumbfile_mgetl(f) != DUMB_ID('S','C','R','M')) {
456 _dumb_it_unload_sigdata(sigdata);
457 return NULL;
458 }
459
460 sigdata->global_volume = dumbfile_getc(f) << 1;
461 sigdata->speed = dumbfile_getc(f);
462 if (sigdata->speed == 0) sigdata->speed = 6; // Should we? What about tempo?
463 sigdata->tempo = dumbfile_getc(f);
464 /*master_volume = */dumbfile_getc(f); // 7 bits; +128 for stereo
465 //what do we do with master_volume? it's not the same as mixing volume...
466 sigdata->mixing_volume = 48;
467
468 /* Skip GUS Ultra Click Removal byte. */
469 dumbfile_getc(f);
470
471 default_pan_present = dumbfile_getc(f);
472
473 dumbfile_skip(f, 8);
474
475 /* Skip Special Custom Data Pointer. */
476 /** WARNING: investigate this? */
477 dumbfile_igetw(f);
478
479 /* Channel settings for 32 channels, 255=unused, +128=disabled */
480 {
481 int i;
482 for (i = 0; i < 32; i++) {
483 int c = dumbfile_getc(f);
484 if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */
485 sigdata->channel_volume[i] = 64;
486 sigdata->channel_pan[i] = c & 8 ? 12 : 3;
487 /** WARNING: ah, but it should be 7 for mono... */
488 } else {
489 /** WARNING: this could be improved if we support channel muting... */
490 sigdata->channel_volume[i] = 0;
491 sigdata->channel_pan[i] = 7;
492 }
493 }
494 }
495
496 /* Orders, byte each, length = sigdata->n_orders (should be even) */
497 dumbfile_getnc((char *)sigdata->order, sigdata->n_orders, f);
498 sigdata->restart_position = 0;
499
500 component = malloc(768*sizeof(*component));
501 if (!component) {
502 _dumb_it_unload_sigdata(sigdata);
503 return NULL;
504 }
505
506 for (n = 0; n < sigdata->n_samples; n++) {
507 component[n_components].type = IT_COMPONENT_SAMPLE;
508 component[n_components].n = n;
509 component[n_components].offset = dumbfile_igetw(f) << 4;
510 component[n_components].sampfirst = -1;
511 n_components++;
512 }
513
514 for (n = 0; n < sigdata->n_patterns; n++) {
515 long offset = dumbfile_igetw(f) << 4;
516 if (offset) {
517 component[n_components].type = IT_COMPONENT_PATTERN;
518 component[n_components].n = n;
519 component[n_components].offset = offset;
520 component[n_components].sampfirst = -1;
521 n_components++;
522 } else {
523 /** WARNING: Empty 64-row pattern ... ? (this does happen!) */
524 sigdata->pattern[n].n_rows = 64;
525 sigdata->pattern[n].n_entries = 0;
526 }
527 }
528
529 qsort(component, n_components, sizeof(IT_COMPONENT), &it_component_compare);
530
531 /* I found a really dumb S3M file that claimed to contain default pan
532 * data but didn't contain any. Programs would load it by reading part of
533 * the first instrument header, assuming the data to be default pan
534 * positions, and then rereading the instrument module. We cannot do this
535 * without obfuscating the file input model, so we insert an extra check
536 * here that we won't overrun the start of the first component.
537 */
538 if (default_pan_present == 252 && component[0].offset >= dumbfile_pos(f) + 32) {
539 /* Channel default pan positions */
540 int i;
541 for (i = 0; i < 32; i++) {
542 int c = dumbfile_getc(f);
543 if (c & 32)
544 sigdata->channel_pan[i] = c & 15;
545 }
546 }
547
548 {
549 int i;
550 for (i = 0; i < 32; i++) {
551 sigdata->channel_pan[i] -= (sigdata->channel_pan[i] & 8) >> 3;
552 sigdata->channel_pan[i] = ((int)sigdata->channel_pan[i] << 5) / 7;
553 }
554 }
555
556 /** WARNING: is this right? */
557 sigdata->pan_separation = 64;
558
559 if (dumbfile_error(f)) {
560 free(component);
561 _dumb_it_unload_sigdata(sigdata);
562 return NULL;
563 }
564
565 buffer = malloc(65536);
566 if (!buffer) {
567 free(component);
568 _dumb_it_unload_sigdata(sigdata);
569 return NULL;
570 }
571
572 for (n = 0; n < n_components; n++) {
573 long offset;
574 int m;
575
576 if (it_seek(f, component[n].offset)) {
577 free(buffer);
578 free(component);
579 _dumb_it_unload_sigdata(sigdata);
580 return NULL;
581 }
582
583 switch (component[n].type) {
584
585 case IT_COMPONENT_PATTERN:
586 if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) {
587 free(buffer);
588 free(component);
589 _dumb_it_unload_sigdata(sigdata);
590 return NULL;
591 }
592 break;
593
594 case IT_COMPONENT_SAMPLE:
595 if (it_s3m_read_sample_header(&sigdata->sample[component[n].n], &offset, f)) {
596 free(buffer);
597 free(component);
598 _dumb_it_unload_sigdata(sigdata);
599 return NULL;
600 }
601
602 if (sigdata->sample[component[n].n].flags & IT_SAMPLE_EXISTS) {
603 short *sample;
604
605 for (m = n + 1; m < n_components; m++)
606 if (component[m].offset > offset)
607 break;
608 m--;
609
610 sample = &component[m].sampfirst;
611
612 while (*sample >= 0 && component[*sample].offset <= offset)
613 sample = &component[*sample].sampnext;
614
615 component[n].sampnext = *sample;
616 *sample = n;
617
618 component[n].offset = offset;
619 }
620 }
621
622 m = component[n].sampfirst;
623
624 while (m >= 0) {
625 if (it_seek(f, component[m].offset)) {
626 free(buffer);
627 free(component);
628 _dumb_it_unload_sigdata(sigdata);
629 return NULL;
630 }
631
632 if (it_s3m_read_sample_data(&sigdata->sample[component[m].n], ffi, f)) {
633 free(buffer);
634 free(component);
635 _dumb_it_unload_sigdata(sigdata);
636 return NULL;
637 }
638
639 m = component[m].sampnext;
640 }
641 }
642
643 free(buffer);
644 free(component);
645
646 _dumb_it_fix_invalid_orders(sigdata);
647
648 return sigdata;
649}
650
651
652
653DUH *dumb_read_s3m(DUMBFILE *f)
654{
655 sigdata_t *sigdata;
656 long length;
657
658 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
659
660 sigdata = it_s3m_load_sigdata(f);
661
662 if (!sigdata)
663 return NULL;
664
665 length = _dumb_it_build_checkpoints(sigdata);
666
667 return make_duh(length, 1, &descptr, &sigdata);
668}
diff --git a/apps/codecs/dumb/src/it/readxm.c b/apps/codecs/dumb/src/it/readxm.c
deleted file mode 100644
index 2aeda1fa67..0000000000
--- a/apps/codecs/dumb/src/it/readxm.c
+++ /dev/null
@@ -1,998 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * readxm.c - Code to read a Fast Tracker II / / \ \
12 * module from an open file. | < / \_
13 * | \/ /\ /
14 * By Julien Cugniere. Some bits of code taken \_ / > /
15 * from reads3m.c. | \ / /
16 * | ' /
17 * \__/
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23
24#include "dumb.h"
25#include "internal/it.h"
26
27
28
29/** TODO:
30
31 * XM_TREMOLO doesn't sound quite right...
32 * XM_E_SET_FINETUNE todo.
33 * XM_SET_ENVELOPE_POSITION todo.
34
35 * VIBRATO conversion needs to be checked (sample/effect/volume). Plus check
36 that effect memory is correct when using XM_VOLSLIDE_VIBRATO.
37 - sample vibrato (instrument vibrato) is now handled correctly. - entheh
38
39 * XM_E_SET_VIBRATO/TREMOLO_CONTROL: effectvalue&4 -> don't retrig wave when
40 a new instrument is played. In retrigger_note()?. Is it worth implementing?
41
42 * Lossy fadeout approximation. 0..31 converted to 0 --> won't fade at all.
43
44 * Replace DUMB's sawtooth by ramp_down/ramp_up. Update XM loader.
45
46 * A lot of things need to be reset when the end of the song is reached.
47
48 * It seems that IT and XM don't behave the same way when dealing with
49 mixed loops. When IT encounters multiple SBx (x>0) commands on the same
50 row, it decrements the loop count for all, but only execute the loop of
51 the last one (highest channel). FT2 only decrements the loop count of the
52 last one. Not that I know of any modules using so convoluted combinations!
53
54 * Maybe we could remove patterns that don't appear in the order table ? Or
55 provide a function to "optimize" a DUMB_IT_SIGDATA ?
56
57*/
58
59
60
61#define XM_LINEAR_FREQUENCY 1 /* otherwise, use amiga slides */
62
63#define XM_ENTRY_PACKED 128
64#define XM_ENTRY_NOTE 1
65#define XM_ENTRY_INSTRUMENT 2
66#define XM_ENTRY_VOLUME 4
67#define XM_ENTRY_EFFECT 8
68#define XM_ENTRY_EFFECTVALUE 16
69
70#define XM_NOTE_OFF 97
71
72#define XM_ENVELOPE_ON 1
73#define XM_ENVELOPE_SUSTAIN 2
74#define XM_ENVELOPE_LOOP 4
75
76#define XM_SAMPLE_NO_LOOP 0
77#define XM_SAMPLE_FORWARD_LOOP 1
78#define XM_SAMPLE_PINGPONG_LOOP 2
79#define XM_SAMPLE_16BIT 16
80#define XM_SAMPLE_STEREO 32
81
82#define XM_VIBRATO_SINE 0
83#define XM_VIBRATO_SQUARE 1
84#define XM_VIBRATO_RAMP_DOWN 2
85#define XM_VIBRATO_RAMP_UP 3
86
87
88
89/* Probably useless :) */
90static const char xm_convert_vibrato[] = {
91 IT_VIBRATO_SINE,
92 IT_VIBRATO_SQUARE,
93 IT_VIBRATO_SAWTOOTH,
94 IT_VIBRATO_SAWTOOTH
95};
96
97
98
99#define XM_MAX_SAMPLES_PER_INSTRUMENT 16
100
101
102
103/* Extra data that doesn't fit inside IT_INSTRUMENT */
104typedef struct XM_INSTRUMENT_EXTRA
105{
106 int n_samples;
107 int vibrato_type;
108 int vibrato_sweep; /* 0-0xFF */
109 int vibrato_depth; /* 0-0x0F */
110 int vibrato_speed; /* 0-0x3F */
111}
112XM_INSTRUMENT_EXTRA;
113
114
115
116/* Frees the original block if it can't resize it or if size is 0, and acts
117 * as malloc if ptr is NULL.
118 */
119static void *safe_realloc(void *ptr, size_t size)
120{
121 if (ptr == NULL)
122 return malloc(size);
123
124 if (size == 0) {
125 free(ptr);
126 return NULL;
127 } else {
128 void *new_block = realloc(ptr, size);
129 if (!new_block)
130 free(ptr);
131 return new_block;
132 }
133}
134
135
136
137/* The interpretation of the XM volume column is left to the player. Here, we
138 * just filter bad values.
139 */
140// This function is so tiny now, should we inline it?
141static void it_xm_convert_volume(int volume, IT_ENTRY *entry)
142{
143 entry->mask |= IT_ENTRY_VOLPAN;
144 entry->volpan = volume;
145
146 switch (volume >> 4) {
147 case 0xA: /* set vibrato speed */
148 case 0xB: /* vibrato */
149 case 0xF: /* tone porta */
150 case 0x6: /* vol slide up */
151 case 0x7: /* vol slide down */
152 case 0x8: /* fine vol slide up */
153 case 0x9: /* fine vol slide down */
154 case 0xC: /* set panning */
155 case 0xD: /* pan slide left */
156 case 0xE: /* pan slide right */
157 case 0x1: /* set volume */
158 case 0x2: /* set volume */
159 case 0x3: /* set volume */
160 case 0x4: /* set volume */
161 break;
162
163 case 0x5:
164 if (volume == 0x50)
165 break; /* set volume */
166 /* else fall through */
167
168 default:
169 entry->mask &= ~IT_ENTRY_VOLPAN;
170 break;
171 }
172}
173
174
175
176static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer)
177{
178 int size;
179 int pos;
180 int channel;
181 int row;
182 int effect, effectvalue;
183 IT_ENTRY *entry;
184
185 /* pattern header size */
186 if (dumbfile_igetl(f) != 0x09) {
187 TRACE("XM error: unexpected pattern header size\n");
188 return -1;
189 }
190
191 /* pattern data packing type */
192 if (dumbfile_getc(f) != 0) {
193 TRACE("XM error: unexpected pattern packing type\n");
194 return -1;
195 }
196
197 pattern->n_rows = dumbfile_igetw(f); /* 1..256 */
198 size = dumbfile_igetw(f);
199 pattern->n_entries = 0;
200
201 if (dumbfile_error(f))
202 return -1;
203
204 if (size == 0)
205 return 0;
206
207 if (size > 1280 * n_channels) {
208 TRACE("XM error: pattern data size > %d bytes\n", 1280 * n_channels);
209 return -1;
210 }
211
212 if (dumbfile_getnc(buffer, size, f) < size)
213 return -1;
214
215 /* compute number of entries */
216 pattern->n_entries = 0;
217 pos = channel = row = 0;
218 while (pos < size) {
219 if (!(buffer[pos] & XM_ENTRY_PACKED) || (buffer[pos] & 31))
220 pattern->n_entries++;
221
222 channel++;
223 if (channel >= n_channels) {
224 channel = 0;
225 row++;
226 pattern->n_entries++;
227 }
228
229 if (buffer[pos] & XM_ENTRY_PACKED) {
230 static const char offset[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
231 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 };
232 pos += 1 + offset[buffer[pos] & 31];
233 } else {
234 pos += 5;
235 }
236 }
237
238 if (row != pattern->n_rows) {
239 TRACE("XM error: wrong number of rows in pattern data\n");
240 return -1;
241 }
242
243 pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
244 if (!pattern->entry)
245 return -1;
246
247 /* read the entries */
248 entry = pattern->entry;
249 pos = channel = row = 0;
250 while (pos < size) {
251 unsigned char mask;
252
253 if (buffer[pos] & XM_ENTRY_PACKED)
254 mask = buffer[pos++] & 31;
255 else
256 mask = 31;
257
258 if (mask) {
259 ASSERT(entry < pattern->entry + pattern->n_entries);
260
261 entry->channel = channel;
262 entry->mask = 0;
263
264 if (mask & XM_ENTRY_NOTE) {
265 int note = buffer[pos++]; /* 1-96 <=> C0-B7 */
266 entry->note = (note == XM_NOTE_OFF) ? (IT_NOTE_OFF) : (note-1);
267 entry->mask |= IT_ENTRY_NOTE;
268 }
269
270 if (mask & XM_ENTRY_INSTRUMENT) {
271 entry->instrument = buffer[pos++]; /* 1-128 */
272 entry->mask |= IT_ENTRY_INSTRUMENT;
273 }
274
275 if (mask & XM_ENTRY_VOLUME)
276 it_xm_convert_volume(buffer[pos++], entry);
277
278 effect = effectvalue = 0;
279 if (mask & XM_ENTRY_EFFECT) effect = buffer[pos++];
280 if (mask & XM_ENTRY_EFFECTVALUE) effectvalue = buffer[pos++];
281 _dumb_it_xm_convert_effect(effect, effectvalue, entry);
282
283 entry++;
284 }
285
286 channel++;
287 if (channel >= n_channels) {
288 channel = 0;
289 row++;
290 IT_SET_END_ROW(entry);
291 entry++;
292 }
293 }
294
295 return 0;
296}
297
298
299
300static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data, int y_offset)
301{
302 int i, pos;
303
304 if (envelope->n_nodes > 12) {
305 TRACE("XM error: wrong number of envelope nodes (%d)\n", envelope->n_nodes);
306 envelope->n_nodes = 0;
307 return -1;
308 }
309
310 pos = 0;
311 for (i = 0; i < envelope->n_nodes; i++) {
312 envelope->node_t[i] = data[pos++];
313 if (data[pos] > 64) {
314 TRACE("XM error: out-of-range envelope node (node_y[%d]=%d)\n", i, data[pos]);
315 envelope->n_nodes = 0;
316 return -1;
317 }
318 envelope->node_y[i] = (signed char)(data[pos++] + y_offset);
319 }
320
321 return 0;
322}
323
324
325
326static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f)
327{
328 unsigned long size, bytes_read;
329 unsigned short vol_points[24];
330 unsigned short pan_points[24];
331 int i, type;
332
333 /* Header size. Tends to be more than the actual size of the structure.
334 * So unread bytes must be skipped before reading the first sample
335 * header.
336 */
337 size = dumbfile_igetl(f);
338
339 //memset(instrument, 0, sizeof(*instrument));
340 dumbfile_skip(f, 22); /* Instrument name */
341 dumbfile_skip(f, 1); /* Instrument type. Should be 0, but seems random. */
342 extra->n_samples = dumbfile_igetw(f);
343
344 if (dumbfile_error(f) || (unsigned int)extra->n_samples > XM_MAX_SAMPLES_PER_INSTRUMENT)
345 return -1;
346
347 bytes_read = 4 + 22 + 1 + 2;
348
349 if (extra->n_samples) {
350 /* sample header size */
351 if (dumbfile_igetl(f) != 0x28) {
352 TRACE("XM error: unexpected sample header size\n");
353 return -1;
354 }
355
356 /* sample map */
357 for (i = 0; i < 96; i++) {
358 instrument->map_sample[i] = dumbfile_getc(f) + 1;
359 instrument->map_note[i] = i;
360 }
361
362 if (dumbfile_error(f))
363 return 1;
364
365 /* volume/panning envelopes */
366 for (i = 0; i < 24; i++)
367 vol_points[i] = dumbfile_igetw(f);
368 for (i = 0; i < 24; i++)
369 pan_points[i] = dumbfile_igetw(f);
370
371 instrument->volume_envelope.n_nodes = dumbfile_getc(f);
372 instrument->pan_envelope.n_nodes = dumbfile_getc(f);
373
374 if (dumbfile_error(f))
375 return -1;
376
377 instrument->volume_envelope.sus_loop_start = dumbfile_getc(f);
378 instrument->volume_envelope.loop_start = dumbfile_getc(f);
379 instrument->volume_envelope.loop_end = dumbfile_getc(f);
380
381 instrument->pan_envelope.sus_loop_start = dumbfile_getc(f);
382 instrument->pan_envelope.loop_start = dumbfile_getc(f);
383 instrument->pan_envelope.loop_end = dumbfile_getc(f);
384
385 /* The envelope handler for XM files won't use sus_loop_end. */
386
387 type = dumbfile_getc(f);
388 instrument->volume_envelope.flags = 0;
389 if ((type & XM_ENVELOPE_ON) && instrument->volume_envelope.n_nodes)
390 instrument->volume_envelope.flags |= IT_ENVELOPE_ON;
391 if (type & XM_ENVELOPE_LOOP) instrument->volume_envelope.flags |= IT_ENVELOPE_LOOP_ON;
392#if 1
393 if (type & XM_ENVELOPE_SUSTAIN) instrument->volume_envelope.flags |= IT_ENVELOPE_SUSTAIN_LOOP;
394#else // This is now handled in itrender.c
395 /* let's avoid fading out when reaching the last envelope node */
396 if (!(type & XM_ENVELOPE_LOOP)) {
397 instrument->volume_envelope.loop_start = instrument->volume_envelope.n_nodes-1;
398 instrument->volume_envelope.loop_end = instrument->volume_envelope.n_nodes-1;
399 }
400 instrument->volume_envelope.flags |= IT_ENVELOPE_LOOP_ON;
401#endif
402
403 type = dumbfile_getc(f);
404 instrument->pan_envelope.flags = 0;
405 if ((type & XM_ENVELOPE_ON) && instrument->pan_envelope.n_nodes)
406 instrument->pan_envelope.flags |= IT_ENVELOPE_ON;
407 if (type & XM_ENVELOPE_LOOP) instrument->pan_envelope.flags |= IT_ENVELOPE_LOOP_ON; // should this be here?
408 if (type & XM_ENVELOPE_SUSTAIN) instrument->pan_envelope.flags |= IT_ENVELOPE_SUSTAIN_LOOP;
409
410 if (it_xm_make_envelope(&instrument->volume_envelope, vol_points, 0) != 0) {
411 TRACE("XM error: volume envelope\n");
412 if (instrument->volume_envelope.flags & IT_ENVELOPE_ON) return -1;
413 }
414
415 if (it_xm_make_envelope(&instrument->pan_envelope, pan_points, -32) != 0) {
416 TRACE("XM error: pan envelope\n");
417 if (instrument->pan_envelope.flags & IT_ENVELOPE_ON) return -1;
418 }
419
420 instrument->pitch_envelope.flags = 0;
421
422 extra->vibrato_type = dumbfile_getc(f);
423 extra->vibrato_sweep = dumbfile_getc(f);
424 extra->vibrato_depth = dumbfile_getc(f);
425 extra->vibrato_speed = dumbfile_getc(f);
426
427 if (dumbfile_error(f) || extra->vibrato_type >= 4)
428 return -1;
429
430 /** WARNING: lossy approximation */
431 instrument->fadeout = (dumbfile_igetw(f)*128 + 64)/0xFFF;
432
433 dumbfile_skip(f, 2); /* reserved */
434
435 bytes_read += 4 + 96 + 48 + 48 + 14*1 + 2 + 2;
436 }
437
438 if (dumbfile_skip(f, size - bytes_read))
439 return -1;
440
441 instrument->new_note_action = NNA_NOTE_CUT;
442 instrument->dup_check_type = DCT_OFF;
443 instrument->dup_check_action = DCA_NOTE_CUT;
444 instrument->pp_separation = 0;
445 instrument->pp_centre = 60; /* C-5 */
446 instrument->global_volume = 128;
447 instrument->default_pan = 32;
448 instrument->random_volume = 0;
449 instrument->random_pan = 0;
450 instrument->filter_cutoff = 0;
451 instrument->filter_resonance = 0;
452
453 return 0;
454}
455
456
457
458/* I (entheh) have two XM files saved by a very naughty program. After a
459 * 16-bit sample, it saved a rogue byte. The length of the sample was indeed
460 * an odd number, incremented to include the rogue byte.
461 *
462 * In this function we are converting sample lengths and loop points so they
463 * are measured in samples. This means we forget about the extra bytes, and
464 * they don't get skipped. So we fail trying to read the next instrument.
465 *
466 * To get around this, this function returns the number of rogue bytes that
467 * won't be accounted for by reading sample->length samples. It returns a
468 * negative number on failure.
469 */
470static int it_xm_read_sample_header(IT_SAMPLE *sample, DUMBFILE *f)
471{
472 int type;
473 int relative_note_number; /* relative to C4 */
474 int finetune;
475 int roguebytes;
476 int roguebytesmask;
477
478 sample->length = dumbfile_igetl(f);
479 sample->loop_start = dumbfile_igetl(f);
480 sample->loop_end = sample->loop_start + dumbfile_igetl(f);
481 sample->global_volume = 64;
482 sample->default_volume = dumbfile_getc(f);
483 finetune = (signed char)dumbfile_getc(f); /* -128..127 <=> -1 semitone .. +127/128 of a semitone */
484 type = dumbfile_getc(f);
485 sample->default_pan = (dumbfile_getc(f)*64)/255 | 128; /* 0-255 */
486 relative_note_number = (signed char)dumbfile_getc(f);
487
488 dumbfile_skip(f, 1); /* reserved */
489 dumbfile_skip(f, 22); /* sample name */
490
491 if (dumbfile_error(f))
492 return -1;
493
494 sample->C5_speed = (long)(16726.0*pow(DUMB_SEMITONE_BASE, relative_note_number)*pow(DUMB_PITCH_BASE, finetune*2));
495
496 sample->flags = IT_SAMPLE_EXISTS;
497
498 roguebytes = (int)sample->length;
499 roguebytesmask = 3;
500
501 if (type & XM_SAMPLE_16BIT) {
502 sample->flags |= IT_SAMPLE_16BIT;
503 sample->length >>= 1;
504 sample->loop_start >>= 1;
505 sample->loop_end >>= 1;
506 } else
507 roguebytesmask >>= 1;
508
509 if (type & XM_SAMPLE_STEREO) {
510 sample->flags |= IT_SAMPLE_STEREO;
511 sample->length >>= 1;
512 sample->loop_start >>= 1;
513 sample->loop_end >>= 1;
514 } else
515 roguebytesmask >>= 1;
516
517 roguebytes &= roguebytesmask;
518
519 if ((unsigned int)sample->loop_start < (unsigned int)sample->loop_end) {
520 if (type & XM_SAMPLE_FORWARD_LOOP) sample->flags |= IT_SAMPLE_LOOP;
521 if (type & XM_SAMPLE_PINGPONG_LOOP) sample->flags |= IT_SAMPLE_LOOP | IT_SAMPLE_PINGPONG_LOOP;
522 }
523
524 if (sample->length <= 0)
525 sample->flags &= ~IT_SAMPLE_EXISTS;
526 else if ((unsigned int)sample->loop_end > (unsigned int)sample->length)
527 sample->flags &= ~IT_SAMPLE_LOOP;
528 else if ((unsigned int)sample->loop_start >= (unsigned int)sample->loop_end)
529 sample->flags &= ~IT_SAMPLE_LOOP;
530
531 return roguebytes;
532}
533
534
535
536static int it_xm_read_sample_data(IT_SAMPLE *sample, unsigned char roguebytes, DUMBFILE *f)
537{
538 int old;
539 long i;
540 long truncated_size;
541
542 if (!(sample->flags & IT_SAMPLE_EXISTS))
543 return dumbfile_skip(f, roguebytes);
544
545 /* let's get rid of the sample data coming after the end of the loop */
546 if ((sample->flags & IT_SAMPLE_LOOP) && sample->loop_end < sample->length) {
547 truncated_size = sample->length - sample->loop_end;
548 sample->length = sample->loop_end;
549 } else {
550 truncated_size = 0;
551 }
552
553 sample->left = malloc(sample->length * sizeof(*sample->left));
554 if (!sample->left)
555 return -1;
556
557 if (sample->flags & IT_SAMPLE_STEREO) {
558 sample->right = malloc(sample->length * sizeof(*sample->right));
559 if (!sample->right)
560 return -1;
561 }
562
563 /* sample data is stored as signed delta values */
564 old = 0;
565 if (sample->flags & IT_SAMPLE_16BIT) {
566 for (i = 0; i < sample->length; i++) {
567 old = sample->left[i] = (int)(signed short)(old + dumbfile_igetw(f));
568 sample->left[i] <<= 8;
569 }
570 } else {
571 for (i = 0; i < sample->length; i++) {
572 old = sample->left[i] = (int)(signed char)(old + dumbfile_getc(f));
573 sample->left[i] <<= 16;
574 }
575 }
576
577 /* skip truncated data */
578 dumbfile_skip(f, (sample->flags & IT_SAMPLE_16BIT) ? (2*truncated_size) : (truncated_size));
579
580 if (sample->flags & IT_SAMPLE_STEREO) {
581 old = 0;
582 if (sample->flags & IT_SAMPLE_16BIT) {
583 for (i = 0; i < sample->length; i++) {
584 old = sample->right[i] = (int)(signed short)(old + dumbfile_igetw(f));
585 sample->right[i] <<= 8;
586 }
587 } else {
588 for (i = 0; i < sample->length; i++) {
589 old = sample->right[i] = (int)(signed char)(old + dumbfile_getc(f));
590 sample->right[i] <<= 16;
591 }
592 }
593 /* skip truncated data */
594 dumbfile_skip(f, (sample->flags & IT_SAMPLE_16BIT) ? (2*truncated_size) : (truncated_size));
595 }
596
597 dumbfile_skip(f, roguebytes);
598
599 if (dumbfile_error(f))
600 return -1;
601
602 return 0;
603}
604
605
606
607/* "Real programmers don't document. If it was hard to write,
608 * it should be hard to understand."
609 *
610 * (Never trust the documentation provided with a tracker.
611 * Real files are the only truth...)
612 */
613static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f)
614{
615 DUMB_IT_SIGDATA *sigdata;
616 char id_text[18];
617
618 int flags;
619 int n_channels;
620 int total_samples;
621 int i, j;
622
623 /* check ID text */
624 if (dumbfile_getnc(id_text, 17, f) < 17)
625 return NULL;
626 id_text[17] = 0;
627 if (strcmp(id_text, "Extended Module: ") != 0) {
628 TRACE("XM error: Not an Extended Module\n");
629 return NULL;
630 }
631
632 /* song name */
633 if (dumbfile_skip(f, 20))
634 return NULL;
635
636 if (dumbfile_getc(f) != 0x1A) {
637 TRACE("XM error: 0x1A not found\n");
638 return NULL;
639 }
640
641 /* tracker name */
642 if (dumbfile_skip(f, 20))
643 return NULL;
644
645 /* version number */
646 if (dumbfile_igetw(f) != 0x0104) {
647 TRACE("XM error: wrong format version\n");
648 return NULL;
649 }
650
651 /*
652 ------------------
653 --- Header ---
654 ------------------
655 */
656
657 /* header size */
658 if (dumbfile_igetl(f) != 0x0114) {
659 TRACE("XM error: unexpected header size\n");
660 return NULL;
661 }
662
663 sigdata = malloc(sizeof(*sigdata));
664 if (!sigdata)
665 return NULL;
666
667 sigdata->order = NULL;
668 sigdata->instrument = NULL;
669 sigdata->sample = NULL;
670 sigdata->pattern = NULL;
671 sigdata->midi = NULL;
672 sigdata->checkpoint = NULL;
673
674 sigdata->n_samples = 0;
675 sigdata->n_orders = dumbfile_igetw(f);
676 sigdata->restart_position = dumbfile_igetw(f);
677 n_channels = dumbfile_igetw(f); /* max 32 but we'll be lenient */
678 sigdata->n_patterns = dumbfile_igetw(f);
679 sigdata->n_instruments = dumbfile_igetw(f); /* max 128 */
680 flags = dumbfile_igetw(f);
681 sigdata->speed = dumbfile_igetw(f);
682 sigdata->tempo = dumbfile_igetw(f);
683
684 /* sanity checks */
685 if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > 256 || sigdata->n_patterns > 256 || sigdata->n_instruments > 128 || n_channels > DUMB_IT_N_CHANNELS) {
686 _dumb_it_unload_sigdata(sigdata);
687 return NULL;
688 }
689
690 //if (sigdata->restart_position >= sigdata->n_orders)
691 //sigdata->restart_position = 0;
692
693 /* order table */
694 sigdata->order = malloc(sigdata->n_orders*sizeof(*sigdata->order));
695 if (!sigdata->order) {
696 _dumb_it_unload_sigdata(sigdata);
697 return NULL;
698 }
699 dumbfile_getnc(sigdata->order, sigdata->n_orders, f);
700 dumbfile_skip(f, 256 - sigdata->n_orders);
701
702 if (dumbfile_error(f)) {
703 _dumb_it_unload_sigdata(sigdata);
704 return NULL;
705 }
706
707 /*
708 --------------------
709 --- Patterns ---
710 --------------------
711 */
712
713 sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
714 if (!sigdata->pattern) {
715 _dumb_it_unload_sigdata(sigdata);
716 return NULL;
717 }
718 for (i = 0; i < sigdata->n_patterns; i++)
719 sigdata->pattern[i].entry = NULL;
720
721 {
722 unsigned char *buffer = malloc(1280 * n_channels); /* 256 rows * 5 bytes */
723 if (!buffer) {
724 _dumb_it_unload_sigdata(sigdata);
725 return NULL;
726 }
727 for (i = 0; i < sigdata->n_patterns; i++) {
728 if (it_xm_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) {
729 free(buffer);
730 _dumb_it_unload_sigdata(sigdata);
731 return NULL;
732 }
733 }
734 free(buffer);
735 }
736
737 /*
738 -----------------------------------
739 --- Instruments and Samples ---
740 -----------------------------------
741 */
742
743 sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
744 if (!sigdata->instrument) {
745 _dumb_it_unload_sigdata(sigdata);
746 return NULL;
747 }
748
749 /* With XM, samples are not global, they're part of an instrument. In a
750 * file, each instrument is stored with its samples. Because of this, I
751 * don't know how to find how many samples are present in the file. Thus
752 * I have to do n_instruments reallocation on sigdata->sample.
753 * Looking at FT2, it doesn't seem possible to have more than 16 samples
754 * per instrument (even though n_samples is stored as 2 bytes). So maybe
755 * we could allocate a 128*16 array of samples, and shrink it back to the
756 * correct size when we know it?
757 * Alternatively, I could allocate samples by blocks of N (still O(n)),
758 * or double the number of allocated samples when I need more (O(log n)).
759 */
760 total_samples = 0;
761 sigdata->sample = NULL;
762
763 for (i = 0; i < sigdata->n_instruments; i++) {
764 XM_INSTRUMENT_EXTRA extra;
765
766 if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) {
767 TRACE("XM error: instrument %d\n", i+1);
768 _dumb_it_unload_sigdata(sigdata);
769 return NULL;
770 }
771
772 if (extra.n_samples) {
773 unsigned char roguebytes[XM_MAX_SAMPLES_PER_INSTRUMENT];
774
775 /* adjust instrument sample map (make indices absolute) */
776 for (j = 0; j < 96; j++)
777 sigdata->instrument[i].map_sample[j] += total_samples;
778
779 sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
780 if (!sigdata->sample) {
781 _dumb_it_unload_sigdata(sigdata);
782 return NULL;
783 }
784 for (j = total_samples; j < total_samples+extra.n_samples; j++)
785 sigdata->sample[j].right = sigdata->sample[j].left = NULL;
786
787 /* read instrument's samples */
788 for (j = 0; j < extra.n_samples; j++) {
789 IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
790 int b = it_xm_read_sample_header(sample, f);
791 if (b < 0) {
792 _dumb_it_unload_sigdata(sigdata);
793 return NULL;
794 }
795 roguebytes[j] = b;
796 // Any reason why these can't be set inside it_xm_read_sample_header()?
797 sample->vibrato_speed = extra.vibrato_speed;
798 sample->vibrato_depth = extra.vibrato_depth;
799 sample->vibrato_rate = extra.vibrato_sweep;
800 /* Rate and sweep don't match, but the difference is
801 * accounted for in itrender.c.
802 */
803 sample->vibrato_waveform = xm_convert_vibrato[extra.vibrato_type];
804 }
805 for (j = 0; j < extra.n_samples; j++) {
806 if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
807 _dumb_it_unload_sigdata(sigdata);
808 return NULL;
809 }
810 }
811 total_samples += extra.n_samples;
812 }
813 }
814
815 sigdata->n_samples = total_samples;
816
817 sigdata->flags = IT_WAS_AN_XM | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO | IT_USE_INSTRUMENTS;
818 // Are we OK with IT_COMPATIBLE_GXX off?
819 //
820 // When specifying note + instr + tone portamento, and an old note is still playing (even after note off):
821 // - If Compatible Gxx is on, the new note will be triggered only if the instrument _changes_.
822 // - If Compatible Gxx is off, the new note will always be triggered, provided the instrument is specified.
823 // - FT2 seems to do the latter (unconfirmed).
824
825 // Err, wait. XM playback has its own code. The change made to the IT
826 // playbackc code didn't affect XM playback. Forget this then. There's
827 // still a bug in XM playback though, and it'll need some investigation...
828 // tomorrow...
829
830 // UPDATE: IT_COMPATIBLE_GXX is required to be on, so that tone porta has
831 // separate memory from portamento.
832
833 if (flags & XM_LINEAR_FREQUENCY)
834 sigdata->flags |= IT_LINEAR_SLIDES;
835
836 sigdata->global_volume = 128;
837 sigdata->mixing_volume = 48;
838 sigdata->pan_separation = 128;
839
840 memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
841 memset(sigdata->channel_pan, 32, DUMB_IT_N_CHANNELS);
842
843 _dumb_it_fix_invalid_orders(sigdata);
844
845 return sigdata;
846}
847
848
849
850#if 0 // no fucking way, dude!
851
852/* The length returned is the time required to play from the beginning of the
853 * file to the last row of the last order (which is when the player will
854 * loop). Depending on the song, the sound might stop sooner.
855 * Due to fixed point roundoffs, I think this is only reliable to the second.
856 * Full precision could be achieved by using a double during the computation,
857 * or maybe a LONG_LONG.
858 */
859long it_compute_length(const DUMB_IT_SIGDATA *sigdata)
860{
861 IT_PATTERN *pattern;
862 int tempo, speed;
863 int loop_start[IT_N_CHANNELS];
864 char loop_count[IT_N_CHANNELS];
865 int order, entry;
866 int row_first_entry = 0;
867 int jump, jump_dest;
868 int delay, fine_delay;
869 int i;
870 long t;
871
872 if (!sigdata)
873 return 0;
874
875 tempo = sigdata->tempo;
876 speed = sigdata->speed;
877 order = entry = 0;
878 jump = jump_dest = 0;
879 t = 0;
880
881 /* for each PATTERN */
882 for (order = 0; order < sigdata->n_orders; order++) {
883
884 if (sigdata->order[order] == IT_ORDER_END) break;
885 if (sigdata->order[order] == IT_ORDER_SKIP) continue;
886
887 for (i = 0; i < IT_N_CHANNELS; i++)
888 loop_count[i] = -1;
889
890 pattern = &sigdata->pattern[ sigdata->order[order] ];
891 entry = 0;
892 if (jump == IT_BREAK_TO_ROW) {
893 int row = 0;
894 while (row < jump_dest)
895 if (pattern->entry[entry++].channel >= IT_N_CHANNELS)
896 row++;
897 }
898
899 /* for each ROW */
900 while (entry < pattern->n_entries) {
901 row_first_entry = entry;
902 delay = fine_delay = 0;
903 jump = 0;
904
905 /* for each note NOTE */
906 while (entry < pattern->n_entries && pattern->entry[entry].channel < IT_N_CHANNELS) {
907 int value = pattern->entry[entry].effectvalue;
908 int channel = pattern->entry[entry].channel;
909
910 switch (pattern->entry[entry].effect) {
911
912 case IT_SET_SPEED: speed = value; break;
913
914 case IT_JUMP_TO_ORDER:
915 if (value <= order) /* infinite loop */
916 return 0;
917 jump = IT_JUMP_TO_ORDER;
918 jump_dest = value;
919 break;
920
921 case IT_BREAK_TO_ROW:
922 jump = IT_BREAK_TO_ROW;
923 jump_dest = value;
924 break;
925
926 case IT_S:
927 switch (HIGH(value)) {
928 case IT_S_PATTERN_DELAY: delay = LOW(value); break;
929 case IT_S_FINE_PATTERN_DELAY: fine_delay = LOW(value); break;
930 case IT_S_PATTERN_LOOP:
931 if (LOW(value) == 0) {
932 loop_start[channel] = row_first_entry;
933 } else {
934 if (loop_count[channel] == -1)
935 loop_count[channel] = LOW(value);
936
937 if (loop_count[channel]) {
938 jump = IT_S_PATTERN_LOOP;
939 jump_dest = loop_start[channel];
940 }
941 loop_count[channel]--;
942 }
943 break;
944 }
945 break;
946
947 case IT_SET_SONG_TEMPO:
948 switch (HIGH(value)) { /* slides happen every non-row frames */
949 case 0: tempo = tempo - LOW(value)*(speed-1); break;
950 case 1: tempo = tempo + LOW(value)*(speed-1); break;
951 default: tempo = value;
952 }
953 tempo = MID(32, tempo, 255);
954 break;
955 }
956
957 entry++;
958 }
959
960 /* end of ROW */
961 entry++;
962 t += TICK_TIME_DIVIDEND * (speed*(1+delay) + fine_delay) / tempo;
963
964 if (jump == IT_JUMP_TO_ORDER) {
965 order = jump_dest - 1;
966 break;
967 } else if (jump == IT_BREAK_TO_ROW)
968 break;
969 else if (jump == IT_S_PATTERN_LOOP)
970 entry = jump_dest - 1;
971 }
972
973 /* end of PATTERN */
974 }
975
976 return t;
977}
978
979#endif /* 0 */
980
981
982
983DUH *dumb_read_xm(DUMBFILE *f)
984{
985 sigdata_t *sigdata;
986 long length;
987
988 DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
989
990 sigdata = it_xm_load_sigdata(f);
991
992 if (!sigdata)
993 return NULL;
994
995 length = _dumb_it_build_checkpoints(sigdata);
996
997 return make_duh(length, 1, &descptr, &sigdata);
998}
diff --git a/apps/codecs/dumb/src/it/xmeffect.c b/apps/codecs/dumb/src/it/xmeffect.c
deleted file mode 100644
index 6e28d5effb..0000000000
--- a/apps/codecs/dumb/src/it/xmeffect.c
+++ /dev/null
@@ -1,255 +0,0 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * xmeffect.c - Code for converting MOD/XM / / \ \
12 * effects to IT effects. | < / \_
13 * | \/ /\ /
14 * By Julien Cugniere. Ripped out of readxm.c \_ / > /
15 * by entheh. | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21
22#include <stdlib.h>
23#include <string.h>
24
25#include "dumb.h"
26#include "internal/it.h"
27
28#ifdef SIMULATOR
29#include "debug.h"
30#endif
31
32
33#if 0
34unsigned char **_dumb_malloc2(int w, int h)
35{
36 unsigned char **line = malloc(h * sizeof(*line));
37 int i;
38 if (!line) return NULL;
39
40 line[0] = malloc(w * h * sizeof(*line[0]));
41 if (!line[0]) {
42 free(line);
43 return NULL;
44 }
45
46 for (i = 1; i < h; i++)
47 line[i] = line[i-1] + w;
48
49 memset(line[0], 0, w*h);
50
51 return line;
52}
53
54
55
56void _dumb_free2(unsigned char **line)
57{
58 if (line) {
59 if (line[0])
60 free(line[0]);
61 free(line);
62 }
63}
64
65
66
67/* Effects having a memory. 2 means that the two parts of the effectvalue
68 * should be handled separately.
69 */
70static const char xm_has_memory[] = {
71/* 0 1 2 3 4 5 6 7 8 9 A B C D (E) F G H K L P R T (X) */
72 0, 1, 1, 1, 2, 1, 1, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
73
74/* E0 E1 E2 E3 E4 E5 E6 E7 E9 EA EB EC ED EE X1 X2 */
75 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
76};
77#endif
78
79
80
81/* Effects marked with 'special' are handled specifically in itrender.c */
82void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry)
83{
84#ifdef SIMULATOR
85const int log = 0;
86#endif
87
88 if ((!effect && !value) || (effect >= XM_N_EFFECTS))
89 return;
90
91#ifdef SIMULATOR
92if (log) DEBUGF("%c%02X", (effect<10)?('0'+effect):('A'+effect-10), value);
93#endif
94
95 /* Linearisation of the effect number... */
96 if (effect == XM_E) {
97 effect = EBASE + HIGH(value);
98 value = LOW(value);
99 } else if (effect == XM_X) {
100 effect = XBASE + HIGH(value);
101 value = LOW(value);
102 }
103
104#ifdef SIMULATOR
105if (log) DEBUGF(" - %2d %02X", effect, value);
106#endif
107
108#if 0 // This should be handled in itrender.c!
109 /* update effect memory */
110 switch (xm_has_memory[effect]) {
111 case 1:
112 if (!value)
113 value = memory[entry->channel][effect];
114 else
115 memory[entry->channel][effect] = value;
116 break;
117
118 case 2:
119 if (!HIGH(value))
120 SET_HIGH(value, HIGH(memory[entry->channel][effect]));
121 else
122 SET_HIGH(memory[entry->channel][effect], HIGH(value));
123
124 if (!LOW(value))
125 SET_LOW(value, LOW(memory[entry->channel][effect]));
126 else
127 SET_LOW(memory[entry->channel][effect], LOW(value));
128 break;
129 }
130#endif
131
132 /* convert effect */
133 entry->mask |= IT_ENTRY_EFFECT;
134 switch (effect) {
135
136 case XM_APPREGIO: effect = IT_ARPEGGIO; break;
137 case XM_VIBRATO: effect = IT_VIBRATO; break;
138 case XM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break; /** TODO: glissando control */
139 case XM_TREMOLO: effect = IT_TREMOLO; break;
140 case XM_SET_PANNING: effect = IT_SET_PANNING; break;
141 case XM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break;
142 case XM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break;
143 case XM_MULTI_RETRIG: effect = IT_RETRIGGER_NOTE; break;
144 case XM_TREMOR: effect = IT_TREMOR; break;
145 case XM_PORTAMENTO_UP: effect = IT_XM_PORTAMENTO_UP; break;
146 case XM_PORTAMENTO_DOWN: effect = IT_XM_PORTAMENTO_DOWN; break;
147 case XM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break; /* special */
148 case XM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break; /* special */
149 case XM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break; /* special */
150
151 case XM_PATTERN_BREAK:
152 effect = IT_BREAK_TO_ROW;
153 value = BCD_TO_NORMAL(value);
154 break;
155
156 case XM_VOLUME_SLIDE: /* special */
157 effect = IT_VOLUME_SLIDE;
158 value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value));
159 break;
160
161 case XM_PANNING_SLIDE:
162 effect = IT_PANNING_SLIDE;
163 value = HIGH(value) ? EFFECT_VALUE(0, HIGH(value)) : EFFECT_VALUE(LOW(value), 0);
164 break;
165
166 case XM_GLOBAL_VOLUME_SLIDE: /* special */
167 effect = IT_GLOBAL_VOLUME_SLIDE;
168 value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value));
169 break;
170
171 case XM_SET_TEMPO_BPM:
172 effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
173 break;
174
175 case XM_SET_GLOBAL_VOLUME:
176 effect = IT_SET_GLOBAL_VOLUME;
177 value *= 2;
178 break;
179
180 case XM_KEY_OFF:
181 /** WARNING: In FT2, the value seems to do something... Oh well,
182 * this is undocumented anyway!
183 */
184 entry->mask &= ~IT_ENTRY_EFFECT;
185 entry->mask |= IT_ENTRY_NOTE;
186 entry->note = IT_NOTE_OFF;
187 break;
188
189 case EBASE+XM_E_SET_FILTER: effect = SBASE+IT_S_SET_FILTER; break;
190 case EBASE+XM_E_SET_GLISSANDO_CONTROL: effect = SBASE+IT_S_SET_GLISSANDO_CONTROL; break; /** TODO */
191 case EBASE+XM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */
192 case EBASE+XM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break;
193 case EBASE+XM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break;
194 case EBASE+XM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break;
195 case EBASE+XM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break;
196 case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break;
197 case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break;
198
199 case EBASE + XM_E_FINE_PORTA_UP:
200 effect = IT_PORTAMENTO_UP;
201 value = EFFECT_VALUE(0xF, value);
202 break;
203
204 case EBASE + XM_E_FINE_PORTA_DOWN:
205 effect = IT_PORTAMENTO_DOWN;
206 value = EFFECT_VALUE(0xF, value);
207 break;
208
209 case EBASE + XM_E_RETRIG_NOTE:
210 effect = IT_XM_RETRIGGER_NOTE;
211 value = EFFECT_VALUE(0, value);
212 break;
213
214 case EBASE + XM_E_SET_VIBRATO_CONTROL:
215 effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM;
216 value &= ~4; /** TODO: value&4 -> don't retrig wave */
217 break;
218
219 case EBASE + XM_E_SET_TREMOLO_CONTROL:
220 effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM;
221 value &= ~4; /** TODO: value&4 -> don't retrig wave */
222 break;
223
224 case XBASE + XM_X_EXTRAFINE_PORTA_UP:
225 effect = IT_PORTAMENTO_UP;
226 value = EFFECT_VALUE(0xE, value);
227 break;
228
229 case XBASE + XM_X_EXTRAFINE_PORTA_DOWN:
230 effect = IT_PORTAMENTO_DOWN;
231 value = EFFECT_VALUE(0xE, value);
232 break;
233
234 default:
235 /* user effect (often used in demos for synchronisation) */
236 entry->mask &= ~IT_ENTRY_EFFECT;
237 }
238
239#ifdef SIMULATOR
240if (log) DEBUGF(" - %2d %02X", effect, value);
241#endif
242
243 /* Inverse linearisation... */
244 if (effect >= SBASE && effect < SBASE+16) {
245 value = EFFECT_VALUE(effect-SBASE, value);
246 effect = IT_S;
247 }
248
249#ifdef SIMULATOR
250if (log) DEBUGF(" - %c%02X\n", 'A'+effect-1, value);
251#endif
252
253 entry->effect = effect;
254 entry->effectvalue = value;
255}