summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/docs
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-03-17 20:50:03 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-03-17 20:50:03 +0000
commit27be5bc72855a0fbbdae230bc144624c9eb85f5e (patch)
treeb553f1321df924c4b744ffcab48dce5f4f081f7d /apps/codecs/dumb/docs
parent7e7662bb716917ca431204f0113d400c1014f2e8 (diff)
downloadrockbox-27be5bc72855a0fbbdae230bc144624c9eb85f5e.tar.gz
rockbox-27be5bc72855a0fbbdae230bc144624c9eb85f5e.zip
Initial check in dumb 0.9.2 - has a few usages of floating point that should
be rewritten to fixed point. seems to compile cleanly for iriver. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6197 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/dumb/docs')
-rw-r--r--apps/codecs/dumb/docs/deprec.txt281
-rw-r--r--apps/codecs/dumb/docs/dumb.txt1699
-rw-r--r--apps/codecs/dumb/docs/faq.txt263
-rw-r--r--apps/codecs/dumb/docs/fnptr.txt113
-rw-r--r--apps/codecs/dumb/docs/howto.txt845
-rw-r--r--apps/codecs/dumb/docs/modplug.txt137
-rw-r--r--apps/codecs/dumb/docs/ptr.txt129
7 files changed, 3467 insertions, 0 deletions
diff --git a/apps/codecs/dumb/docs/deprec.txt b/apps/codecs/dumb/docs/deprec.txt
new file mode 100644
index 0000000000..88ca2e9fda
--- /dev/null
+++ b/apps/codecs/dumb/docs/deprec.txt
@@ -0,0 +1,281 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * deprec.txt - Deprecated functions, why they / / \ \
12 * were deprecated, and what to do | < / \_
13 * instead. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21**********************************************
22*** How the functions have been deprecated ***
23**********************************************
24
25
26 GCC 3.1 and later provide a very useful attribute. The following:
27
28 __attribute__((__deprecated__))
29
30 when written alongside a function prototype, variable declaration or type
31 definition, will result in a warning from GCC if any such part of the API
32 is used. The warning will even tell you where the declaration is, and I
33 have inserted comments by all the deprecated declarations, telling you
34 what to do.
35
36 Unfortunately, GCC 2.x and 3.0.x and MSVC do not have any means to
37 deprecate things. The approach I have taken with these compilers is to
38 avoid prototyping the declared functions. This means you will get
39 warnings and errors, and they won't be very helpful. If your program
40 compiles, you may get strange crashes when you run it, since the compiler
41 needs the declarations in order to make sure function calls are carried
42 out correctly.
43
44 If you would like the deprecated parts of the API to be declared, you can
45 compile with the -DDUMB_DECLARE_DEPRECATED switch for GCC, or the
46 -D"DUMB_DECLARE_DEPRECATED" switch for MSVC. This will be accepted by
47 GCC 3.x but is unnecessary. Use this switch with other people's projects
48 if necessary, but please make the effort to update your own projects to
49 use the new API, as the deprecated parts may be removed in the future.
50
51 The rest of this file explains why some parts of the API were deprecated,
52 and how to adapt your code.
53
54
55**************************************
56*** What happened to DUH_RENDERER? ***
57**************************************
58
59
60 The DUH_RENDERER struct was designed for rendering audio to an end-user
61 format - 8-bit or 16-bit, signed or unsigned, with stereo samples
62 interleaved. In order for it to do this, it was built on top of the
63 hitherto undocumented DUH_SIGRENDERER struct, which rendered audio in
64 DUMB's internal 32-bit signed format with channels (left/right) stored
65 separately. The DUH_RENDERER struct contained a pointer to a
66 DUH_SIGRENDERER struct, along with some other data like the position and
67 number of channels.
68
69 There were then some developments in the API. The DUH_SIGRENDERER struct
70 also stored the position and the number of channels, so I decided to write
71 functions for returning these. Suddenly there was no need to store them in
72 the DUH_RENDERER struct. Before long, the DUH_RENDERER struct contained
73 nothing but a pointer to a DUH_SIGRENDERER.
74
75 I decided it would be a good idea to unify the structs. After all, there
76 really is no difference between the data stored in each, and it would be
77 easy to make duh_render(DUH_RENDERER *dr, ...) and
78 duh_render_signal(DUH_SIGRENDERER *sr, ...) work on the same type of
79 struct. (Note that duh_render_signal() is now deprecated too; see the next
80 section.) It took some deliberation, but I decided I didn't want functions
81 to be #defined (it prevents you from using these names for member
82 functions in C++ classes), and that meant they had to be defined
83 somewhere. Defining redundant functions is a source of bloat, inefficiency
84 and general inelegance. After weighing things up, I decided it was better
85 to deprecate the redundant functions and have people begin to use the more
86 efficient versions, and eventually the redundant functions will be able to
87 be removed.
88
89 So why did I choose to keep the more complicated name, DUH_SIGRENDERER?
90 The reason has to do with what DUMB will become in the future. Signals are
91 an inherent part of the DUH struct and how .duh files will be constructed.
92 It will be possible to have multiple signals in a single DUH struct, and
93 you will be able to choose which one you want to play (this is the 'sig'
94 parameter passed to duh_start_sigrenderer()). But don't hold your breath;
95 we still have a long way to go before .duh files will start to appear...
96
97
98typedef DUH_SIGRENDERER DUH_RENDERER;
99
100 Wherever you are using DUH_RENDERER in your program, simply replace it
101 with DUH_SIGRENDERER. An automated (case-sensitive!) search and replace
102 operation should get this done.
103
104
105DUH_RENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos);
106
107 Use duh_start_sigrenderer() instead. It takes an extra parameter, 'sig',
108 which comes after 'duh' and before 'n_channels'; pass 0 for this. So an
109 example would be, replace:
110
111 sr = duh_start_renderer(duh, 2, 0);
112
113 with:
114
115 sr = duh_start_sigrenderer(duh, 0, 2, 0);
116
117
118int duh_renderer_get_n_channels(DUH_RENDERER *dr);
119long duh_renderer_get_position(DUH_RENDERER *dr);
120void duh_end_renderer(DUH_RENDERER *dr);
121
122 These are easy enough to fix; all you have to do is replace 'renderer'
123 with 'sigrenderer'. So the new functions are:
124
125 int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer);
126 long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer);
127 void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
128
129
130Note that duh_render() has NOT been deprecated. It now uses DUH_SIGRENDERER
131instead of DUH_RENDERER, but its functionality is unchanged. You do not have
132to change calls to this function in any way.
133
134
135DUH_RENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sr);
136DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_RENDERER *dr);
137DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_RENDERER *dr);
138
139 These functions did not exist in the last release of DUMB, so you are
140 probably not using them, but they are included here for completeness. All
141 you have to do here is unwrap the function, since the structs have been
142 unified. So, for instance, replace:
143
144 duh_renderer_encapsulate_sigrenderer(my_sigrenderer)
145
146 with:
147
148 my_sigrenderer
149
150 Simple!
151
152
153AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_RENDERER *dr,
154 float volume, long bufsize, int freq);
155DUH_RENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp);
156DUH_RENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp);
157
158 Again, these functions were not in the last release, so you probably
159 aren't using them. Nevertheless, the fix is simple as always: simply
160 replace 'renderer' with 'sigrenderer'. So the new functions are:
161
162 AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sr,
163 float volume, long bufsize, int freq);
164 DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp);
165 DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp);
166
167
168*********************
169*** Miscellaneous ***
170*********************
171
172
173long duh_render_signal(DUH_SIGRENDERER *sigrenderer,
174 float volume, float delta,
175 long size, sample_t **samples);
176
177 This function used to return samples in DUMB's internal format. This
178 format consisted of 32-bit integers whose 'normal range' was -0x8000 to
179 0x7FFF (any samples outside this range would have to be clipped when sent
180 to the sound card).
181
182 DUMB's internal format has changed. DUMB still uses 32-bit integers, but
183 now the normal range is -0x800000 to 0x7FFFFF. The lowest eight bits are
184 discarded at the final stage by duh_render() when you ask for 16-bit
185 output. A new function, duh_sigrenderer_get_samples(), will return samples
186 in DUMB's new internal format. It takes exactly the same parameters, so
187 all you have to do to the call itself is change the name; however, you
188 will most likely have to change your code to account for the new
189 normalised range.
190
191 duh_render_signal() will still be able to give you the samples in DUMB's
192 old internal format, but it is inefficient. You should change your code as
193 soon as possible.
194
195
196typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples,
197 int n_channels, long length);
198
199void duh_sigrenderer_set_callback(DUH_SIGRENDERER *sigrenderer,
200 DUH_SIGRENDERER_CALLBACK callback, void *data);
201
202 This callback was intended to allow you to analyse the output. It was by
203 no means intended to let you modify the output. For this reason, the names
204 have been changed to DUH_SIGRENDERER_ANALYSER_CALLBACK and
205 duh_sigrenderer_set_analyser_callback, and the 'samples' parameter to your
206 callback should now be specified as follows:
207
208 const sample_t *const *samples
209
210 The first 'const' indicates that you must not modify the samples. The
211 second indicates that you must not modify the pointers to each channel.
212
213 There is a second reason why this change was necessary, and it is the one
214 described further up for duh_render_signal()'s entry: the format in which
215 the samples themselves are stored has changed. They are 256 times as
216 large, with a normal range from -0x800000 to 0x7FFFFF. You will most
217 likely need to change your code to account for this.
218
219 If you try to call the old function, it will print a message to stderr
220 directing you to this file, and it will not install the callback. You
221 shouldn't be able to get this far without a compiler warning (or, if you
222 don't have GCC 3.1 or later, some compiler errors).
223
224 If you wanted to use this callback to apply a DSP effect, don't worry;
225 there is a better way of doing this. It is undocumented, so contact me
226 and I shall try to help. Contact details are at the bottom of this file.
227
228 For reference, here are the new definitions:
229
230 typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data,
231 const sample_t *const *samples, int n_channels, long length);
232
233 void duh_sigrenderer_set_analyser_callback(DUH_SIGRENDERER *sigrenderer,
234 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data);
235
236
237int dumb_resampling_quality;
238
239 This variable has changed meaning. It used to hold a value from 0 to 4,
240 whose meaning was as follows:
241
242 0 - aliasing
243 1,2 - linear interpolation
244 3 - quadratic interpolation
245 4 - cubic interpolation
246
247 0,1 - always use a straightforward interpolation algorithm
248 2,3,4 - when decimating (increasing the pitch), use a linear average
249 algorithm designed to reduce frequencies that would otherwise
250 reflect off the Nyquist
251
252 Now the variable only holds values from 0 to 2, and these values have
253 preprocessor constants associated with them. The somewhat inappropriate
254 quadratic interpolation has been removed. The linear average algorithm has
255 also been removed, and may or may not come back; there are probably more
256 efficient ways of achieving the same effect, which I shall be
257 investigating in the future.
258
259 This change will have hardly any noticeable effect on existing programs.
260 Levels 2, 3 and 4 used considerably more processor time because of the
261 linear average algorithm. Likewise, Level 2 in the new scheme (cubic) uses
262 considerably more processor time than Levels 1 and 0, and Levels 3 and 4
263 will behave identically to Level 2.
264
265
266******************
267*** Conclusion ***
268******************
269
270
271"I conclude that... DUMB is the bestest music player in the world because...
272Complete this sentence in fifteen words or fewer... D'OH!"
273
274The preceding conclusion formerly appeared in dumb.txt, and is deprecated
275because it's lame.
276
277
278Ben Davis
279entheh@users.sf.net
280IRC EFnet #dumb
281See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/dumb.txt b/apps/codecs/dumb/docs/dumb.txt
new file mode 100644
index 0000000000..86b2cc3374
--- /dev/null
+++ b/apps/codecs/dumb/docs/dumb.txt
@@ -0,0 +1,1699 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * dumb.txt - DUMB library reference. / / \ \
12 * | < / \_
13 * See readme.txt for general information on | \/ /\ /
14 * DUMB and how to set it up. \_ / > /
15 * | \ / /
16 * If you are new to DUMB, see howto.txt. | ' /
17 * \__/
18 */
19
20
21***********************************
22*** Include Files and Libraries ***
23***********************************
24
25
26dumb.h
27
28 Include this if you only want the core DUMB library functions. You will
29 be able to load music files and render them into memory buffers at your
30 own pace. The core library is completely portable, and as such does not
31 access hardware; you must relay the sound data to the sound card yourself.
32 A stdio file input module is available, but you must actively register it
33 if you wish to use it (see dumb_register_stdfiles()); if you do not
34 register it, it will not be linked into your executable. You must register
35 it, or a DUMBFILE module of your own, in order to load stand-alone music
36 files.
37
38 Optimised: -ldumb or /link dumb.lib
39 Debugging: -ldumbd or /link dumbd.lib
40
41
42aldumb.h
43
44 Include this if you wish to use DUMB with Allegro. This will provide you
45 with functions to play DUHs back through Allegro's audio streams and embed
46 music files in Allegro datafiles. A file input module using Allegro's
47 packfiles is provided; you have a choice between this and the stdio
48 module (or provide one of your own). You will be able to load datafiles
49 containing music files no matter which file input module you register, or
50 even if you register no file input module. However, you must register a
51 file input module in order to load stand-alone files.
52
53 Optimised: -laldmb -ldumb -lalleg or /link aldmb.lib alleg.lib dumb.lib
54 Debugging: -laldmd -ldumbd -lalld or /link aldmd.lib alld.lib dumbd.lib
55
56 aldmb or aldmd must be linked in first, so the symbols can be resolved
57 when linking in the other two libraries.
58
59
60***************************
61*** Version Information ***
62***************************
63
64
65#define DUMB_MAJOR_VERSION
66#define DUMB_MINOR_VERSION
67#define DUMB_REVISION_VERSION
68
69 Numeric constants representing this version of DUMB. If this were version
70 1.0, DUMB_MAJOR_VERSION would be 1 and DUMB_MINOR_VERSION would be 0.
71 DUMB_REVISION_VERSION will be 0 on any significant releases, and will be
72 incremented as releases with bugfixes and minor features are made.
73
74 Typical usage:
75
76 #if DUMB_MAJOR_VERSION < 1
77 #error This add-on requires DUMB v1.0 or higher. Please upgrade.
78 #endif
79
80
81#define DUMB_VERSION
82
83 A numeric constant which appears in the format MMmmrr when displayed in
84 decimal (M for major, m for minor, r for revision). This is most useful
85 for comparing version numbers; it has little other practical use.
86
87 Typical usage:
88
89 #if DUMB_VERSION < 801
90 #error This game requires DUMB v0.8.1 or higher. Please upgrade.
91 #endif
92
93 #if DUMB_VERSION < 10002
94 #error This game requires DUMB v1.0.2 or higher. Please upgrade.
95 #endif
96
97
98#define DUMB_VERSION_STR
99
100 String constant representing this version of DUMB. If this were Version
101 1.0, DUMB_VERSION_STR would be "1.0". DUMB_REVISION_VERSION will only
102 appear on the end if it is nonzero; then DUMB_VERSION_STR might be
103 "1.0.1".
104
105
106#define DUMB_NAME
107
108 A string identifying DUMB and its version. If this were Version 1.0,
109 DUMB_NAME might be "DUMB v1.0". This constant is suitable for use in your
110 Credits screen if you wish to acknowledge the use of DUMB there.
111
112
113#define DUMB_YEAR
114#define DUMB_MONTH
115#define DUMB_DAY
116
117 Numeric constants representing the year, month and day of this release of
118 DUMB. All four digits are included in the year. Please note that
119 DUMB_MONTH and DUMB_DAY were inadvertently swapped in the v0.8 release.
120
121
122#define DUMB_YEAR_STR4
123#define DUMB_YEAR_STR2
124#define DUMB_MONTH_STR2
125#define DUMB_MONTH_STR1
126#define DUMB_DAY_STR2
127#define DUMB_DAY_STR1
128
129 String constants representing the year, month and day of this release of
130 DUMB. DUMB_MONTH_STR2 and DUMB_DAY_STR2 include a leading zero if the
131 month or day respectively are less than ten; the STR1 variations do not.
132 DUMB_YEAR_STR2 contains only the two rightmost digits of the year, while
133 DUMB_YEAR_STR4 contains all four. I recommend using DUMB_YEAR_STR4,
134 especially so soon after the turn of the century (indeed the millennium).
135 However, it is a matter of personal preference which you use.
136
137 Please note that the month and day were inadvertently swapped in the v0.8
138 release.
139
140
141#define DUMB_DATE
142
143 A numeric constant that appears in the form yyyymmdd when displayed in
144 decimal. This is most useful for comparing release dates; it has little
145 other practical use.
146
147 WARNING: The month and day were inadvertently swapped in the v0.8 release.
148 Please do not compare this constant against any date in 2002. In
149 any case, DUMB_VERSION is probably more useful for this purpose.
150
151
152#define DUMB_DATE_STR
153
154 The date as a string. The format is "d.m.yyyy", with dots used as
155 separators, the day written first, four digits for the year, and no
156 leading zeros on the day or month. This is my preferred format. If you
157 don't like it, you can construct your own format using the other
158 constants. For example, "mm/dd/yy" could be constructed as follows:
159
160 DUMB_MONTH_STR2 "/" DUMB_DAY_STR2 "/" DUMB_YEAR_STR2
161
162 Please note that the month and day were inadvertently swapped in the v0.8
163 release.
164
165
166*************************
167*** Basic Sample Type ***
168*************************
169
170
171typedef int sample_t;
172
173 DUMB works internally with 32-bit integer samples, with a 'normal range'
174 from -0x800000 to 0x7FFFFF (as of DUMB v0.9.2; previously they ranged from
175 -0x8000 to 0x7FFF). Any samples that exceed this range will eventually be
176 clipped, and could cause integer overflow in extreme cases.
177
178
179***********************************
180*** Library Clean-up Management ***
181***********************************
182
183
184int dumb_atexit(void (*proc)(void));
185
186 Registers a function to be called at the end of your program. You can
187 register multiple functions to be called, and the one you register last
188 will be called first. If you try to register the same function twice, the
189 second attempt will have no effect.
190
191 See fnptr.txt for help with function pointers.
192
193 You must call dumb_exit() before exiting your program for this to work
194 properly. The library itself registers functions with dumb_atexit(), so it
195 is important to call dumb_exit() even if you do not use dumb_atexit()
196 yourself.
197
198 This function will return zero on success. It will return zero when
199 trying to install the same function twice. If it fails through lack of
200 memory, it will return nonzero. Generally you can ignore the return code;
201 in the worst case some memory will not be freed at the end. If it is
202 crucial that your function be called (e.g. to shut down some hardware or
203 save critical data), then you should call your function manually at the
204 end of the program instead of registering it here - or use the stdlib
205 function atexit(), guaranteed under ANSI C to succeed for at least 32
206 functions.
207
208
209void dumb_exit(void);
210
211 You should call this before exiting your program if you have used any part
212 of DUMB in the program. Some parts of DUMB will allocate memory, and this
213 function will free it all up.
214
215 More specifically, this function will call any functions that have been
216 registered with dumb_atexit(). If a part of DUMB needs shutting down, the
217 shutdown procedure will have been registered in this way.
218
219 dumb_exit() will, of course, also call any functions you registered with
220 dumb_atexit() yourself.
221
222 After a call to dumb_exit(), the list of functions is erased. If you are
223 not ready to exit your program, you can start using DUMB anew as if your
224 program had just started. (Note that not everything will be reset in
225 practice - dumb_resampling_quality will retain whatever you set it to, for
226 example, though you should not assume it will.)
227
228 If you only need to call dumb_exit() once at the end of the program, you
229 can use the following to register dumb_exit() with stdlib.h atexit():
230
231 #include <stdlib.h>
232
233 atexit(&dumb_exit);
234
235 Then dumb_exit() will be called for you when your program exits. This is
236 the recommended method, since it will ensure clean-up even if your program
237 aborts. You should only call dumb_exit() manually if you need to shut DUMB
238 down prematurely, or if atexit() is unavailable for one reason or another.
239
240
241*****************************
242*** Sequential File Input ***
243*****************************
244
245
246 DUMB provides a strictly sequential file input system which uses the
247 DUMBFILE struct. "Strictly sequential" means you cannot seek backwards.
248 However, the system will keep track of how many bytes you have read,
249 enabling you to seek forwards. DUMBFILEs provide a convenient error
250 detection system, so you do not have to check the return value from every
251 function call in the way you do with the ANSI C functions.
252
253 Note that DUMBFILEs cannot be used for output, nor can they be used
254 portably for text files.
255
256 If an error occurs when reading data from a DUMBFILE, the DUMBFILE will
257 become inoperative. All subsequent activities on the DUMBFILE will return
258 error codes without attempting to read from the file. The position in the
259 file will also be forgotten. You can find out if this has happened at any
260 stage with the dumbfile_error() function. You are still required to close
261 the DUMBFILE, and the return value from dumbfile_close() will tell you if
262 an error has occurred.
263
264 This system allows you to input large chunks of your file, neither
265 checking every return value nor wasting time accessing a file that has
266 already experienced an error. However, before you allocate an amount of
267 memory or read in a quantity of data depending on previous input from the
268 file, you should always check that such input was valid. In particular you
269 should avoid passing zero or negative numbers to malloc(), and avoid
270 passing negative numbers to dumbfile_skip() and dumbfile_getnc().
271
272 DUMBFILEs can be hooked. In other words, you can specify your own
273 functions to do the work of reading from a file. While DUMB contains two
274 modules for this purpose, it does not set them up for you automatically.
275 In most cases you must register one of these modules yourself, or provide
276 your own module. See register_dumbfile_system(), dumb_register_stdfiles()
277 and dumb_register_packfiles().
278
279
280void register_dumbfile_system(DUMBFILE_SYSTEM *dfs);
281
282 Use this function to register a set of functions for use by the DUMBFILEs
283 (a DUMBFILE system). The DUMBFILE_SYSTEM struct contains the following
284 fields:
285
286 void *(*open)(const char *filename);
287 int (*skip)(void *f, long n);
288 int (*getc)(void *f);
289 long (*getnc)(char *ptr, long n, void *f);
290 void (*close)(void *f);
291
292 See fnptr.txt for help with function pointers such as these.
293
294 Your 'open' function should open the file specified and return a pointer
295 to a struct representing the open file. This pointer will be passed to
296 your other functions as 'f'. Your 'close' function should close the file
297 and free all memory pointed to by 'f'. Note that the 'close' operation
298 should never be able to fail; if you are calling a function with a return
299 value, you can generally ignore it.
300
301 Your 'getc' function should read one byte from the file and return its
302 value in the range 0 to 255. If an error occurs, you should return -1. Do
303 not worry about remembering that an error has occurred; DUMB will do that
304 for you.
305
306 'skip' is for skipping parts of the file, and should skip n bytes,
307 returning 0 on success or any other number on failure. 'getnc' should read
308 n bytes from the file, store them at 'ptr', and return the number of bytes
309 read (n on success, fewer on failure). However, these two functions are
310 optional, and you should only provide them if the operations can be done
311 more efficiently than with repeated calls to your 'getc' function. If this
312 is not the case, specify NULL for 'skip', 'getnc' or both, and DUMB will
313 use your 'getc' function to do the work.
314
315 Once you have written all your functions, you need to create a
316 DUMBFILE_SYSTEM struct to hold them, and pass its pointer to
317 register_dumbfile_system().
318
319 The DUMBFILE_SYSTEM struct must be permanent. In other words, it must be
320 either global or static, and you should not modify it later. DUMB will not
321 make its own copy.
322
323 You will most likely create your own struct to represent the open file,
324 but do not be tempted to specify that struct in the function prototypes
325 and pacify the compiler warnings by casting your function pointers. There
326 exist computer systems where a (void *) pointer and a (MY_STRUCT *)
327 pointer are represented differently in memory, and a cast of such a
328 pointer causes a tangible conversion to take place. If you cast the
329 function pointers, the computer cannot know when such a conversion is
330 necessary. Instead, use the following structure:
331
332 int myskip(void *f, long n)
333 {
334 FILE *file = f;
335 /* Do some stuff with 'file' */
336 return something;
337 }
338
339 If you need examples, have a look at the two existing DUMBFILE systems in
340 dumb/src/core/stdfile.c and dumb/src/allegro/packfile.c.
341
342
343DUMBFILE *dumbfile_open(const char *filename);
344
345 Open the specified file for input. You must pass the DUMBFILE pointer
346 whenever you wish to operate on this file. When you have finished with the
347 file, you must pass it to dumbfile_close().
348
349 Before you use this function, make sure you have registered a DUMBFILE
350 system. See register_dumbfile_system(), dumb_register_stdfiles() and
351 dumb_register_packfiles().
352
353 You must check the return value from this function. If it is NULL, the
354 file could not be opened, and you must not pass the DUMBFILE to any other
355 function. The debugging library will abort if you get this wrong; the
356 optimised library will act weird.
357
358
359DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs);
360
361 This function is provided for more specialised use. You should create a
362 DUMBFILE_SYSTEM specially for the purpose. Its 'open' field is irrelevant;
363 for neatness, set it to NULL, unless you are using this DUMBFILE_SYSTEM
364 with register_dumbfile_system() as well.
365
366 When you have called this function, the DUMBFILE struct it returned can be
367 used as normal. The specified DUMBFILE_SYSTEM will be used for all input,
368 with 'file' passed to your 'skip', 'getc' and 'getnc' functions as 'f'.
369 This can be used, for example, to read from an already open file.
370
371 Note that the position will always be initialised to 0 for this DUMBFILE.
372 This means for example that offsets in the file do not need adjusting when
373 embedding data in a larger file.
374
375 There are two ways to use this function. If you want 'file' to persist
376 after using a DUMBFILE returned by this function, you should make sure the
377 'close' field in the DUMBFILE is set to NULL. When the DUMBFILE is closed,
378 'file' will be left alone, and you can and should deal with it yourself
379 when the DUMBFILE has been closed.
380
381 Alternatively, you can provide a 'close' function to get rid of 'file' for
382 you when the DUMBFILE is closed. If you do this, you should not otherwise
383 use 'file' after a call to this function.
384
385 If dumbfile_open_ex() has to return NULL, owing to lack of memory, then
386 your 'close' function will be called if provided. In other words, if you
387 have provided a 'close' function, then you no longer need to worry about
388 'file' whether this function succeeds or not.
389
390 See dumb/src/helpers/stdfile.c and dumb/src/allegro/packfile.c for
391 examples of how to use this function. Neither provides a 'close' function,
392 so I hope my explanation here will suffice. If not, please feel free to
393 contact me so I can make the explanation clearer and help you do what you
394 want to do. Contact details are at the end of this file.
395
396
397long dumbfile_pos(DUMBFILE *f);
398
399 Returns the number of bytes read from the DUMBFILE (or skipped) since it
400 was opened, or -1 if an error has occurred while reading.
401
402
403int dumbfile_skip(DUMBFILE *f, long n);
404
405 Skips n bytes of the specified DUMBFILE. Returns zero on success.
406
407
408int dumbfile_getc(DUMBFILE *f);
409
410 Reads one byte from the DUMBFILE and returns it in unsigned format (from 0
411 to 255). If an error occurs, or occurred before, this function returns -1.
412
413
414int dumbfile_igetw(DUMBFILE *f);
415
416 Reads two bytes from the DUMBFILE and combines them into a word ranging
417 from 0 to 65535. The first byte read is the least significant byte, as
418 with Intel processors. This function returns -1 on error.
419
420
421int dumbfile_mgetw(DUMBFILE *f);
422
423 Reads two bytes from the DUMBFILE and combines them into a word ranging
424 from 0 to 65535. The first byte read is the most significant byte, as
425 with the Apple Macintosh. This function returns -1 on error.
426
427
428long dumbfile_igetl(DUMBFILE *f);
429
430 Reads four bytes from the DUMBFILE and combines them into a long integer
431 ranging from -2147483648 to 2147483647. The first byte read is the least
432 significant byte, as with Intel processors. This function returns -1 on
433 error, but -1 is also a valid return value. After a call to this function,
434 you can use dumbfile_error() to find out if an error occurred.
435
436
437long dumbfile_mgetl(DUMBFILE *f);
438
439 Reads four bytes from the DUMBFILE and combines them into a long integer
440 ranging from -2147483648 to 2147483647. The first byte read is the most
441 significant byte, as with the Apple Macintosh. This function returns -1 on
442 error, but -1 is also a valid return value. After a call to this function,
443 you can use dumbfile_error() to find out if an error occurred.
444
445
446unsigned long dumbfile_cgetul(DUMBFILE *f);
447
448 Reads an unsigned (nonnegative) integer from the DUMBFILE. The integer is
449 stored in a condensed format where smaller numbers use less space:
450
451 0 to 127 1 byte
452 128 to 16383 2 bytes
453 16384 to 2097151 3 bytes
454 2097152 to 268435455 4 bytes
455 268435456 to 4294967295 5 bytes
456
457 This format is the same as that used for the times between notes in MIDI
458 files.
459
460 If an error occurs, this function returns (unsigned long)(-1), but that
461 may be a valid return value. After a call to this function, you can use
462 dumbfile_error() to find out if an error occurred.
463
464
465signed long dumbfile_cgetsl(DUMBFILE *f);
466
467 Reads a signed integer from the DUMBFILE. The integer is stored in a
468 condensed format where numbers closer to zero use less space:
469
470 -64 to 63 1 byte
471 -8192 to 8191 2 bytes
472 -1048576 to 1048575 3 bytes
473 -134217728 to 134217727 4 bytes
474 -2147483648 to 2147483647 5 bytes
475
476 If an error occurs, this function returns -1, but -1 is also a valid
477 return value. After a call to this function, you can use dumbfile_error()
478 to find out if an error occurred.
479
480
481long dumbfile_getnc(char *ptr, long n, DUMBFILE *f);
482
483 Reads n bytes from the DUMBFILE and stores them at 'ptr'. Note that the
484 pointer is to a series of chars. You may also use this function to read in
485 a series of signed chars or unsigned chars (which are both officially
486 distinct types from char), but do not use this to read ints, structs or
487 any other data type from the file. Integers must be read one at a time
488 using dumbfile_igetl(), dumbfile_cgetul(), etc. To load a struct in, you
489 must read each field separately using an appropriate function for each
490 one. For complicated data types, you can simplify this process by writing
491 a function for each struct.
492
493 dumbfile_getnc() returns the number of bytes successfully read, which will
494 be less than n if an error occurs, and may be as low as zero. If
495 dumbfile_getnc() returns -1, that means an error occurred on this DUMBFILE
496 earlier, before this function was called.
497
498
499int dumbfile_error(DUMBFILE *f);
500
501 This function returns -1 if an error has occurred with the specified
502 DUMBFILE, or 0 if all is well.
503
504
505int dumbfile_close(DUMBFILE *f);
506
507 This function closes the DUMBFILE, after which the pointer will be
508 invalid. dumbfile_close() returns the value that dumbfile_error() would
509 have returned, which is -1 if an error occurred while reading or 0
510 otherwise. Regardless of the return value, the file will always be closed
511 properly.
512
513
514*******************************
515*** stdio File Input Module ***
516*******************************
517
518
519void dumb_register_stdfiles(void);
520
521 This function registers the stdio file input module for use by DUMBFILEs.
522 FILE structs and their corresponding functions, as defined by the ANSI C
523 header stdio.h, will be used internally for all DUMBFILE input (unless
524 opened with dumbfile_open_ex()).
525
526 This must be called before dumbfile_open() is used, or else an alternative
527 system must be registered (see register_dumbfile_system() and
528 dumb_register_packfiles()).
529
530
531DUMBFILE *dumbfile_open_stdfile(FILE *p);
532
533 If you have a stdio FILE struct representing an open file, you can call
534 this if you wish to read from it using a DUMBFILE. This is useful when you
535 need to pass a DUMBFILE struct to a library function, to read an embedded
536 music file for example. When you close the DUMBFILE, you can continue
537 using the FILE struct to read what follows the embedded data.
538
539
540********************************
541*** Memory File Input Module ***
542********************************
543
544
545DUMBFILE *dumbfile_open_memory(const char *data, long size);
546
547 This function is useful if you have an image of a music file in memory.
548 You might have such an image if you use dat2s to encode a datafile
549 directly into the executable. Pass a pointer to the start of the memory,
550 and the size of the image to make sure DUMB doesn't overrun the buffer.
551 The resulting DUMBFILE will feed the contents of the image to you.
552
553 Note that the pointer is of type 'char *'. Files are series of chars, and
554 interpreting them directly as anything else isn't portable.
555
556
557**********************
558*** DUH Management ***
559**********************
560
561
562void unload_duh(DUH *duh);
563
564 Removes a DUH from memory. You must call this for all DUHs you load,
565 making sure they're not playing at the time.
566
567
568long duh_get_length(DUH *duh);
569
570 Returns the length of a DUH; 65536 represents one second. This value is
571 calculated when the DUH is created, and this function simply lifts it from
572 the struct. It may not truly correspond to the time for which the DUH will
573 generate sound. For module files, it will represent the point at which the
574 module first loops (or, in the case of some XM and MOD files, freezes).
575 Any add-ons to DUMB will provide their own code for calculating this.
576
577 The algorithm for calculating the length of a module file can be fooled,
578 but only by very deliberate methods. In the early days, when modules could
579 only be played by their editors and had to be exported to .wav or similar
580 in order to be used elsewhere, musicians would sometimes make the player
581 think it was looping when it wasn't in order to prevent their music from
582 being exported properly. If the length of a module seems a lot less than
583 it should be, the module is probably protected in this way.
584
585 Getting around this protection reliably would be extremely difficult, but
586 after considering it for a while I decided it would be better not to. The
587 musician has a right to protect his or her music in this way, and I have
588 no interest in actively breaking that protection.
589
590 (On the other hand, some musicians were just showing off!)
591
592
593***********************************
594*** IT, XM, S3M and MOD Support ***
595***********************************
596
597
598int dumb_it_max_to_mix;
599
600 Specifies the maximum number of samples DUMB will mix at any one time. The
601 default number is 64. Regardless of this value, all samples will continue
602 to be processed up to an internal maximum of 256 (roughly speaking; in
603 fact it will process one sample for each channel plus up to 192 extra
604 samples that are continuing to play owing to Impulse Tracker's New Note
605 Actions), and samples that have been cut will sound again as soon as the
606 congestion clears. Samples are given priority according to their final
607 volume after all factors affecting the volume of a sample have been
608 considered.
609
610 If you play two or more modules at once, this value represents the
611 maximum number of samples for each one. You will have to reduce it further
612 if your computer cannot keep up.
613
614 Despite the name, this variable controls XM, S3M and MOD files as well as
615 IT files.
616
617
618DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh);
619
620 This function attempts to retrieve the DUMB_IT_SIGDATA struct from a DUH.
621 This struct will exist for any IT, XM, S3M or MOD file, and you can use it
622 to obtain or override module-specific information. If 'duh' is NULL, or if
623 the DUH you pass contains something other than a music module, then this
624 function will return NULL (which can safely be passed to any other
625 function).
626
627
628DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer);
629
630 This function attempts to retrieve the DUMB_IT_SIGRENDERER struct from a
631 DUH_SIGRENDERER. This struct will exist for any currently playing IT, XM,
632 S3M or MOD file, and you can use it to obtain or override information
633 specific to module playback. If 'sigrenderer' is NULL, or if the
634 DUH_SIGRENDERER you pass is rendering something other than a music module,
635 then this function will return NULL (which can safely be passed to any
636 other function).
637
638
639DUH_SIGRENDERER *dumb_it_start_at_order
640 (DUH *duh, int n_channels, int startorder);
641
642 This function, given a DUH containing an IT, XM, S3M or MOD file, will
643 start playing it at the specified order. If the DUH does not contain a
644 module, this function will fail and return NULL.
645
646 Note that starting at an arbitrary order may result in missing notes or
647 other playback oddities. It should be used primarily for modules that
648 contain multiple songs that start on different orders. If you wish just to
649 start some music in the middle, consider using duh_start_sigrenderer() or
650 al_start_duh() with the pos parameter set appropriately.
651
652
653void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer,
654 int (*callback)(void *data), void *data);
655
656 Installs a callback which will be called every time the module loops. You
657 can pass any data pointer you like, and it will be passed to the callback
658 for you. DUMB considers a file to loop when it reaches the end, or when a
659 'Jump to order' effect (Bxx in both IT/S3M and XM/MOD) jumps to the same
660 order or a preceding order. This can result in the loop callback being
661 called when the module isn't really looping, but this only happens if the
662 module has a very deliberate design. See duh_get_length() for further
663 musings on this subject.
664
665 If your callback returns nonzero, the music will stop abruptly. Samples
666 will be cut, and the main program will be notified that the
667 DUH_SIGRENDERER has ended.
668
669 Alternatively, if you pass the DUMB_IT_SIGRENDERER for 'data', or
670 otherwise arrange for it to be available to the callback, then you can
671 call:
672
673 dumb_it_sr_set_speed(sigrenderer, 0);
674
675 from inside the callback, and this will cause the music to freeze but
676 samples will be able to continue playing. The xm_speed_zero callback will
677 NOT be called in this case (see below for information on this callback).
678 Note also that setting the speed in this way will work equally for IT and
679 S3M files, even though a 'speed zero' effect can only exist in XM and MOD
680 files. Beware when using this method; samples might not fade at all!
681
682 A helper callback, dumb_it_callback_terminate(), is provided; installing
683 this will cause the music to terminate when it tries to loop for the first
684 time.
685
686 Pass NULL to remove the callback function; the module will then loop as
687 normal.
688
689
690void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer,
691 int (*callback)(void *data), void *data);
692
693 Installs a callback which is in many ways similar to the loop callback
694 (see dumb_it_set_loop_callback()). This callback will be called whenever
695 an F00 effect is encountered in a MOD or XM file, setting the speed to
696 zero. If the callback returns nonzero, the music will terminate. If not,
697 any currently playing samples will continue to play. You can pass any data
698 pointer you like to this function, and it will be passed to your callback
699 for you.
700
701 The helper callback, dumb_it_callback_terminate(), will also work here;
702 installing it will cause the music to terminate as soon as an F00 effect
703 is encountered.
704
705 Pass NULL to remove the callback function.
706
707
708void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer,
709 int (*callback)(void *data, int channel, unsigned char byte),
710 void *data);
711
712 Installs a callback function which will be called whenever MIDI data are
713 generated by an IT file. (No other module formats are capable of
714 generating MIDI data, so your callback will never be called.)
715
716 Zxx macros will generate MIDI data. These are most often used to set the
717 parameters for IT's low-pass resonant filters, and DUMB will handle these
718 messages by itself by default. See Impulse Tracker's documentation for
719 the MIDI messages that control filters. However, Zxx macros can be used
720 to send any kind of MIDI data.
721
722 If you wish to interpret MIDI messages yourself, you can use this
723 callback. Note that the only MIDI messages generated by DUMB at present
724 are from Zxx macros; there are no messages for note start, stop, or
725 anything else.
726
727 If you return 1 from this callback, DUMB will subsequently ignore the byte
728 of MIDI data. You can use this to prevent Zxx macros from controlling the
729 filters, useful if they were intended to do something else. Note that this
730 is NOT an effective way to disable filters, since instruments can have
731 filter envelopes and initial filter parameters. DUMB provides no means to
732 disable filters, as any IT file that uses them will sound wrong without
733 them. If you want lower processor consumption, use a different piece of
734 music.
735
736 A helper callback, dumb_it_callback_midi_block(), is provided for blocking
737 all MIDI messages and making Zxx macros do nothing.
738
739 Pass NULL to remove the callback.
740
741
742int dumb_it_callback_terminate(void *data);
743
744 This is a helper callback that can be installed with both
745 dumb_it_set_loop_callback() and dumb_it_set_xm_speed_zero_callback(). In
746 each case it will cause the music to terminate abruptly.
747
748
749int dumb_it_callback_midi_block(void *data, int channel, unsigned char byte);
750
751 This helper callback, for use with dumb_it_set_midi_callback(), will
752 absorb all MIDI messages, returning 1 to prevent DUMB from interpreting
753 them itself.
754
755
756DUH *dumb_load_it(const char *filename);
757
758 Loads the specified Impulse Tracker file, encapsulating it in a DUH
759 struct. Once the file is loaded, it can be treated exactly the same as any
760 other DUH in memory. If this fails it will return NULL, but you can safely
761 pass this NULL value to DUMB's other functions, so you do not need to
762 check the return value explicitly.
763
764
765DUH *dumb_read_it(DUMBFILE *f);
766
767 Reads an Impulse Tracker file from an already open DUMBFILE. This leaves
768 the DUMBFILE open, but the DUMBFILE may not be positioned at the end of
769 the IT data. If you are embedding an IT in another file, you are advised
770 to store the size of the IT file and make up for it at the end using
771 dumbfile_pos().
772
773 Otherwise, this function is identical to dumb_load_it().
774
775 WARNING: The behaviour of this function is undefined if you pass a
776 DUMBFILE from which data have already been read; it is likely not
777 to work. This oversight will be fixed in future releases.
778
779
780DUH *dumb_load_xm(const char *filename);
781
782 Loads the specified Fast Tracker II file, encapsulating it in a DUH
783 struct. Once the file is loaded, it can be treated exactly the same as any
784 other DUH in memory. If this fails it will return NULL, but you can safely
785 pass this NULL value to DUMB's other functions, so you do not need to
786 check the return value explicitly.
787
788
789DUH *dumb_read_xm(DUMBFILE *f);
790
791 Reads a Fast Tracker II file from an already open DUMBFILE. This leaves
792 the DUMBFILE open, but the DUMBFILE may not be positioned at the end of
793 the XM data. If you are embedding an XM in another file, you are advised
794 to store the size of the XM file and make up for it at the end using
795 dumbfile_pos().
796
797 Otherwise, this function is identical to dumb_load_xm().
798
799 WARNING: The behaviour of this function is undefined if you pass a
800 DUMBFILE from which data have already been read; it is likely not
801 to work. This oversight will be fixed in future releases.
802
803
804DUH *dumb_load_s3m(const char *filename);
805
806 Loads the specified Scream Tracker 3 file, encapsulating it in a DUH
807 struct. Once the file is loaded, it can be treated exactly the same as any
808 other DUH in memory. If this fails it will return NULL, but you can safely
809 pass this NULL value to DUMB's other functions, so you do not need to
810 check the return value explicitly.
811
812
813DUH *dumb_read_s3m(DUMBFILE *f);
814
815 Reads a Scream Tracker 3 file from an already open DUMBFILE. This leaves
816 the DUMBFILE open, but the DUMBFILE may not be positioned at the end of
817 the S3M data. If you are embedding an S3M in another file, you are advised
818 to store the size of the S3M file and make up for it at the end using
819 dumbfile_pos().
820
821 Otherwise, this function is identical to dumb_load_s3m().
822
823 WARNING: The behaviour of this function is undefined if you pass a
824 DUMBFILE from which data have already been read; it is likely not
825 to work. This oversight will be fixed in future releases.
826
827
828DUH *dumb_load_mod(const char *filename);
829
830 Loads the specified Amiga module file, encapsulating it in a DUH struct.
831 Once the file is loaded, it can be treated exactly the same as any other
832 DUH in memory. If this fails it will return NULL, but you can safely pass
833 this NULL value to DUMB's other functions, so you do not need to check the
834 return value explicitly.
835
836
837DUH *dumb_read_mod(DUMBFILE *f);
838
839 Reads an Amiga module file from an already open DUMBFILE. This leaves the
840 DUMBFILE open, but the DUMBFILE may not be positioned at the end of the
841 MOD data. If you are embedding a MOD in another file, you are advised to
842 store the size of the MOD file and make up for it at the end using
843 dumbfile_pos().
844
845 Otherwise, this function is identical to dumb_load_mod().
846
847 WARNING: The behaviour of this function is undefined if you pass a
848 DUMBFILE from which data have already been read; it is likely not
849 to work. This oversight will be fixed in future releases.
850
851
852int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd);
853
854 This function returns the number of orders in the module.
855
856
857int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd);
858void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv);
859
860 These functions obtain and set the initial global volume for the module.
861 This value ranges from 0 to 128 inclusive. The module can set the global
862 volume itself during playback, so your change may not last throughout the
863 playback.
864
865
866int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd);
867void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv);
868
869 These functions obtain and set the mixing volume for the module. This
870 value ranges from 0 to 128 inclusive, and does not change during playback.
871 IT files have the mixing volume stored in them; for other formats it is
872 set to 48 on loading.
873
874
875int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd);
876void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed);
877int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd);
878void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo);
879
880 These functions obtain and set the initial speed and tempo for the module.
881 During module playback, everything happens on a tick. If a beat is 24
882 ticks, then the tempo is measured in beats per second. The speed is then
883 the number of ticks per row. With a speed of 6, a beat is then four rows.
884
885 Modules can set these values during playback, so your change may not last
886 throughout the playback. MOD files have to set the speed and tempo on the
887 first row if they want anything other than the default 6/125, so your
888 change may not be noticed at all!
889
890
891int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel);
892void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel,
893 int volume);
894
895 These functions obtain and set the initial volume for the specified
896 channel. The channel parameter is 0-based (contrary to the display in most
897 trackers so be careful), and can range from 0 to DUMB_IT_N_CHANNELS - 1,
898 i.e. from 0 to 63.
899
900 Modules can set their channel volumes during playback, so your changes may
901 not last throughout the playback.
902
903
904int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr);
905int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr);
906
907 These functions return the current order and row of playback. Both are
908 0-based. If the DUMB_IT_SIGRENDERER is invalid, or has been terminated
909 by a callback (see dumb_it_set_loop_callback() and
910 dumb_it_set_xm_speed_zero_callback()), these functions will both return
911 -1.
912
913
914int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr);
915void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv);
916
917 These functions obtain and set the current global volume for the module.
918 This value ranges from 0 to 128 inclusive. The module can set the global
919 volume itself during playback, so your change may not last.
920
921
922int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr);
923void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo);
924int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr);
925void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed);
926
927 These functions obtain and set the current speed and tempo of the module.
928 See the dumb_it_sd_*() equivalents of these functions for details on what
929 the speed and tempo mean.
930
931 Modules can set these values during playback, so your change may not last.
932
933
934int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel);
935void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel,
936 int volume);
937
938 These functions obtain and set the current volume for the specified
939 channel. The channel parameter is 0-based (contrary to the display in most
940 trackers so be careful), and can range from 0 to DUMB_IT_N_CHANNELS - 1,
941 i.e. from 0 to 63.
942
943 Modules can set their channel volumes during playback, so your changes may
944 not last.
945
946
947void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel,
948 DUMB_IT_CHANNEL_STATE *state);
949
950 Returns the current playback state of the given channel. If you pass a
951 channel in the range 0 to DUMB_IT_N_CHANNELS-1 (0 to 63), you will get the
952 state of the most recently played note on that physical channel, if it is
953 still playing. For MOD, S3M and XM files, that's all there is to it.
954
955 IT files can have more than one note playing on a single channel, courtesy
956 of New Note Actions. This function also lets you query all the notes that
957 have been forced into the background and are still playing. For this, set
958 'channel' to a value from DUMB_IT_N_CHANNELS to DUMB_IT_TOTAL_CHANNELS-1.
959 DUMB_IT_TOTAL_CHANNELS is defined as follows:
960
961 #define DUMB_IT_TOTAL_CHANNELS \
962 (DUMB_IT_N_CHANNELS + DUMB_IT_N_NNA_CHANNELS)
963
964 Querying these background channels for MOD, S3M and XM files will not do
965 any harm; the function will report that these channels are inactive. For
966 all files, be sure not to query any channel numbers greater than or equal
967 to DUMB_IT_TOTAL_CHANNELS.
968
969 You must provide a pointer to a preallocated DUMB_IT_CHANNEL_STATE struct.
970 The easiest way to do this is as follows:
971
972 DUMB_IT_CHANNEL_STATE state;
973 dumb_it_sr_get_channel_state(sr, channel, &state);
974
975 or:
976
977 DUMB_IT_CHANNEL_STATE state[IT_TOTAL_CHANNELS];
978 dumb_it_sr_get_channel_state(sr, channel, &state[channel]);
979
980 This struct contains the following fields:
981
982 int channel;
983 int sample;
984 int freq;
985 float volume;
986 unsigned char pan;
987 signed char subpan;
988 unsigned char filter_cutoff;
989 unsigned char filter_subcutoff;
990 unsigned char filter_resonance;
991
992 The first field to check is 'sample'; if this is 0, then the channel is
993 inactive and the other fields are undefined. Otherwise, it is the index of
994 the currently playing sample, and is 1-based.
995
996 The channel number is returned, 0-based. This will be the same as the
997 channel number you passed, unless you are querying a background channel in
998 which case it will represent the channel the note originated on.
999
1000 The freq field is the current playback frequency, taking into account all
1001 phenomena such as slides, vibrato and arpeggio.
1002
1003 The volume field ranges from 0.0f to 1.0f. In practical terms, it will
1004 rarely reach 1.0f; if it does, the module is probably clipping a lot. This
1005 takes mixing volume into account, along with all the other volume
1006 phenomena in the IT file. The only one it doesn't take into account is the
1007 one you pass to duh_render() or duh_sigrenderer_get_samples(), or the one
1008 you passed to al_start_duh() (these are in fact the same thing).
1009
1010 The pan field ranges from 0 to 64 for a normally panned sample, but will
1011 be 100 if the sample is playing using IT's surround mode where the right-
1012 hand channel is inverted. If you want a more accurate pan reading, use one
1013 of the following to get one:
1014
1015 int scaled_pan = ((int)state.pan << 8) + state.subpan;
1016 float float_pan = state.pan + state.subpan / 256.0f;
1017
1018 The first will give a scaled value ranging (strictly) from 0 to 64*256.
1019 The second will give a floating-point value whose scale corresponds to
1020 that of the pan field. These results will only be valid if surround mode
1021 is off, so you should check that pan <= 64 before using the above
1022 expressions. At the time of writing, pitch-pan separation and panning
1023 envelopes take advantage of the extra accuracy offered by subpan.
1024
1025 Note that subpan is signed. This means applications that only look at the
1026 pan field will get an unbiased reading.
1027
1028 The filter cut-off and resonance both range from 0 to 127. If the cut-off
1029 is 127 and the resonance is 0, then no filters are applied. These
1030 parameters only ever change from the default values for IT files.
1031
1032 While IT allows you to set 127 different filter cut-off levels in the
1033 patterns and as a default value per instrument, it also allows you to
1034 create a filter envelope, which will result in an actual cut-off somewhere
1035 between 0 and the first-mentioned value. By the time this has been
1036 calculated, the actual cut-off may lie in between two levels on the
1037 original scale. If this is the case, filter_subcutoff will be nonzero and
1038 you can combine it with filter_cutoff. Typically you will want to use one
1039 of the following:
1040
1041 int scaled_cutoff = ((int)state.filter_cutoff << 8) +
1042 state.filter_subcutoff;
1043
1044 float float_cutoff = state.filter_cutoff +
1045 state.filter_subcutoff / 256.0f;
1046
1047 The first will give you a scaled value whose maximum is 127*256. The
1048 second will give you a floating-point value whose scale corresponds to the
1049 scale used by filter_cutoff. These match the expressions given further up
1050 for pan and subpan, but in this case, filter_subcutoff is unsigned.
1051
1052 Note that filter_subcutoff will always be zero if filter_cutoff is 127, so
1053 you need not check it if you simply wish to determine whether filters are
1054 being applied.
1055
1056
1057*******************************
1058*** DUH Rendering Functions ***
1059*******************************
1060
1061
1062 Use these functions to generate samples from a DUH. First you call
1063 duh_start_sigrenderer() with the DUH, the number of channels you want and
1064 the position at which you want to start. Then you use duh_render() or
1065 duh_sigrenderer_get_samples() to generate the samples. You can call these
1066 functions as many times as you like, and they will generate as many or as
1067 few samples as you require. When you have finished, call
1068 duh_end_sigrenderer().
1069
1070
1071DUH_SIGRENDERER *duh_start_sigrenderer
1072 (DUH *duh, int sig, int n_channels, long pos);
1073
1074 Starts a DUH_SIGRENDERER off. This is the struct you can use to get
1075 samples from a DUH. This function does not generate any samples; you must
1076 pass the struct to duh_render() or duh_sigrenderer_get_samples() for that.
1077 When you have finished with it, you must pass it to duh_end_sigrenderer().
1078 You can use as many DUH_SIGRENDERER structs as you like at the same time.
1079
1080 Set sig to 0 for now. Currently, n_channels can only be 1 or 2, for
1081 monaural and stereo sound respectively. The debugging library will cause
1082 your program to abort if you pass anything else. Future versions will be
1083 enhanced to support more channels as soon as someone needs them.
1084
1085 When specifying the position, 0 represents the start of the DUH, and 65536
1086 represents one second. Unlike most other music systems, DUMB will always
1087 make sure every note is there right from the start (assuming you aren't
1088 using any broken add-ons). In other words, you can start a DUH at a point
1089 halfway through a long note, and you will still hear the long note.
1090
1091
1092void duh_sigrenderer_set_analyser_callback(DUH_SIGRENDERER *sigrenderer,
1093 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data);
1094
1095 Installs a callback function which will be called every time the given
1096 sigrenderer is used to generate some samples. This can be used to create
1097 an oscilloscope or spectrum analyser. DUH_SIGRENDERER_ANALYSER_CALLBACK is
1098 defined as follows:
1099
1100 typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data,
1101 const sample_t *const *samples, int n_channels, long length);
1102
1103 If the above confuses you, see fnptr.txt. As for the 'samples' parameter,
1104 the first 'const' says that the samples are read-only; the second says
1105 that each channel's sample pointer is also read-only. If you don't
1106 understand this, don't worry about it.
1107
1108 Beware: your callback function may occasionally be called with
1109 samples == NULL. This means the main program has decided to skip through
1110 the music without generating any data (see duh_sigrenderer_get_samples()).
1111 You should handle this case elegantly, typically by returning immediately,
1112 but you may wish to make a note of the fact that the music is being
1113 skipped, for whatever reason.
1114
1115 Beware again: if the main program ever calls duh_sigrenderer_get_samples()
1116 on a buffer that isn't all silence, this callback function will be passed
1117 the existing buffer after mixing, and thus it will include the original
1118 data. This will not be an issue if you stick to duh_render(), which always
1119 starts with a buffer filled with silence.
1120
1121 The samples array is two-dimensional. Refer to it as follows:
1122
1123 samples[channel_number][sample_position]
1124
1125 where 0 <= channel_number < n_channels,
1126 and 0 <= sample_position < length.
1127
1128 In addition you can pass any 'data' pointer you like to
1129 duh_sigrenderer_set_analyser_callback(), and this pointer will be relayed
1130 to your callback function each time.
1131
1132 To remove the callback function, pass NULL to
1133 duh_sigrenderer_set_analyser_callback().
1134
1135
1136int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer);
1137
1138 Tells you how many channels a DUH_SIGRENDERER is set up to generate, or 0
1139 if it is invalid (perhaps owing to lack of memory). This will be 1 for
1140 monaural sound or 2 for stereo, in this release.
1141
1142
1143long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer);
1144
1145 Tells you what position a DUH_SIGRENDERER is up to, or -1 if it is invalid
1146 (perhaps owing to lack of memory). As usual, 65536 is one second.
1147
1148
1149long duh_sigrenderer_get_samples(DUH_SIGRENDERER *sigrenderer,
1150 float volume, float delta,
1151 long size, sample_t **samples);
1152
1153 Generates some samples in DUMB's internal 32-bit format (see sample_t; see
1154 also duh_render()). The samples buffer is a two-dimensional array, and can
1155 be allocated with create_sample_buffer(); see
1156 duh_sigrenderer_set_analyser_callback() for details.
1157 duh_sigrenderer_get_samples() mixes sample data with what's already in the
1158 buffer, so you have to call dumb_silence() first.
1159
1160 The volume is a float. 1.0f is the pseudo-maximum. If you pass 1.0f, any
1161 properly designed DUH will play nice and loud, but will not clip. You can
1162 pass a greater volume if you like, but be prepared for the possibility of
1163 distortion due to integer overflow. Of course you can pass smaller values
1164 to play the DUH more quietly, and this will also resolve clipping issues
1165 in badly designed DUHs.
1166
1167 Use delta to control the speed of the output signal. If you pass 1.0f, the
1168 resultant signal will be suitable for a 65536-Hz sampling rate (which
1169 isn't a commonly used rate). The most common sampling rates are 11025 Hz,
1170 22050 Hz, 44100 Hz and 48000 Hz. You can work out the required delta value
1171 as follows:
1172
1173 delta = 65536.0f / sampling_rate;
1174
1175 If you then increase this value, the DUH will speed up and increase in
1176 pitch. If you decrease it, the DUH will slow down and decrease in pitch.
1177
1178 This function will attempt to render 'size' samples. In most cases it will
1179 succeed. However, if the end of the DUH is reached, it may render fewer.
1180 The number of samples rendered will be returned. Therefore, if the return
1181 value is less than the value of 'size' passed, you know the DUH has
1182 finished. It is safe to continue calling duh_sigrenderer_get_samples() if
1183 you wish, and it will continually return 0.
1184
1185 If the DUH_SIGRENDERER is a null pointer, this function will generate
1186 precisely 0 samples. If you pass NULL for 'samples', the function will
1187 behave exactly the same as if you provided a sample buffer, except the
1188 samples won't be stored anywhere and the function will execute very
1189 quickly. This can be used to skip ahead in the audio.
1190
1191
1192long duh_render(DUH_SIGRENDERER *sigrenderer,
1193 int bits, int unsign,
1194 float volume, float delta,
1195 long size, void *sptr);
1196
1197 Generates some samples and converts them to an 8-bit or 16-bit format (see
1198 also duh_sigrenderer_get_samples()). Pass the DUH_SIGRENDERER as returned
1199 by duh_start_sigrenderer(). Pass the number of bits, which should be 8 or
1200 16. If unsign is nonzero, the samples will be unsigned (centred on 0x80 or
1201 0x8000 for 8 bits and 16 bits respectively). If unsign is zero, the
1202 samples will be signed.
1203
1204 Allegro's audio streams always take unsigned samples. 8-bit .wav files
1205 always take unsigned samples. 16-bit .wav files always take signed
1206 samples.
1207
1208 The volume and delta parameters work the same as for
1209 duh_sigrenderer_get_samples().
1210
1211 This function will attempt to render 'size' samples. In most cases it will
1212 succeed. However, if the end of the DUH is reached, it may render fewer.
1213 The number of samples rendered will be returned. Therefore, if the return
1214 value is less than the value of 'size' passed, you know the DUH has
1215 finished. It is safe to continue calling duh_render() if you wish, and it
1216 will continually return 0. However, if you wish to do this, you will
1217 probably have to fill the rest of the buffer with silence, which is 0 for
1218 signed, 0x80 for 8-bit unsigned or 0x8000 for 16-bit unsigned.
1219
1220 The samples will be placed at sptr. Use an array of chars for 8 bits or an
1221 array of shorts for 16 bits. Stereo samples will be interleaved, left
1222 first. Your array should contain at least (size * n_channels) elements of
1223 the appropriate bit resolution.
1224
1225 From an aesthetic standpoint if nothing else, it is wise to use the C
1226 qualifiers 'signed' or 'unsigned' depending on whether the samples are
1227 signed or unsigned. This is also convenient if you wish to process the
1228 samples further yourself.
1229
1230 If the DUH_SIGRENDERER is a null pointer, this function will generate
1231 precisely 0 samples. Unlike with duh_sigrenderer_get_samples(), you must
1232 specify a sample buffer.
1233
1234
1235void duh_end_sigrenderer(DUH_SIGRENDERER *dr);
1236
1237 Terminates a DUH_SIGRENDERER. Be sure to call this when you've finished
1238 with one. You can safely pass a null pointer.
1239
1240
1241********************************
1242*** Allegro Packfile Support ***
1243********************************
1244
1245
1246void dumb_register_packfiles(void);
1247
1248 This function registers the Allegro PACKFILE input module for use by
1249 DUMBFILEs. PACKFILE structs and their corresponding functions, as defined
1250 by Allegro's header file allegro.h, will be used internally for all
1251 DUMBFILE input (unless opened with dumbfile_open_ex()).
1252
1253 This must be called before dumbfile_open() is used, or else an alternative
1254 system must be registered (see register_dumbfile_system() and
1255 dumb_register_stdfiles()). Note that you don't have to call this function
1256 in order to load datafiles that contain music.
1257
1258
1259DUMBFILE *dumbfile_open_packfile(PACKFILE *p);
1260
1261 If you have an Allegro PACKFILE struct representing an open file, you can
1262 call this if you wish to read from it using a DUMBFILE. This is useful
1263 when you need to pass a DUMBFILE struct to a library function, to read an
1264 embedded music file for example. When you close the DUMBFILE, you can
1265 continue using the PACKFILE struct to read what follows the embedded data.
1266
1267
1268DUMBFILE *dumbfile_from_packfile(PACKFILE *p);
1269
1270 This function is the same as dumbfile_open_packfile(), except it will
1271 check if p is NULL, and arrange for pack_fclose() to be called on the
1272 PACKFILE when you close the DUMBFILE. It can be seen as a function for
1273 converting a PACKFILE to a DUMBFILE, but it will only work for a PACKFILE
1274 you obtained with pack_fopen(), not pack_fopen_chunk(). If this function
1275 fails, which may happen if memory is short, then the PACKFILE will be
1276 closed immediately, so you need not worry about potential memory leaks or
1277 files being left open when this happens.
1278
1279 The following is typical usage, and will open the compressed file foo.bin:
1280
1281 DUMBFILE *f = dumbfile_from_packfile(pack_fopen("foo.bin",
1282 F_READ_PACKED));
1283
1284 This differs from calling dumb_register_packfiles() and dumbfile_open() in
1285 that the latter will only read uncompressed files (and is thus a method
1286 suitable for reading music modules).
1287
1288
1289***********************************************
1290*** Allegro Datafile Registration Functions ***
1291***********************************************
1292
1293
1294void dumb_register_dat_it(long type);
1295
1296 If you wish to embed an IT file in an Allegro datafile, it is recommended
1297 that you use "IT " for the type. The grabber will have a box for the type
1298 when you insert a new object. The grabber will treat the IT file as binary
1299 data, which means the datafile will contain an exact copy of the IT file
1300 on disk.
1301
1302 You must then call dumb_register_dat_it(DUMB_DAT_IT) in your program
1303 before you load the datafile. Once you've done this, you'll be able to
1304 access the DUH using the usual datafile[n].dat notation. You do not need
1305 to call unload_duh() on this DUH; unload_datafile() will do that for you.
1306
1307 If you are using a different type for whatever reason, you can use
1308 Allegro's DAT_ID() macro for encoding it and passing it to this function.
1309 For example:
1310
1311 dumb_register_dat_it(DAT_ID('B','L','A','H'));
1312
1313 Assuming you used the recommended type, the following example iterates
1314 through all the ITs in disan.dat:
1315
1316 DATAFILE *dat;
1317 int n;
1318
1319 dumb_register_dat_it();
1320 dat = load_datafile("disan.dat");
1321
1322 for (n = 0; dat[n].type != DAT_END; n++) {
1323 if (dat[n].type == DUMB_DAT_IT) {
1324 DUH *duh = dat[n].dat;
1325 /* Insert code here to play 'duh' or whatever you want to do. */
1326 }
1327 }
1328
1329 unload_datafile(dat);
1330
1331
1332void dumb_register_dat_xm(long type);
1333
1334 Inserting an XM file in an Allegro datafile is the same as inserting an IT
1335 file, except that the recommended type is "XM ", the registration
1336 function is dumb_register_dat_xm(), and the macro DUMB_DAT_XM is provided
1337 for the type. The intuitive process of substituting XM for IT in the above
1338 method will work.
1339
1340
1341void dumb_register_dat_s3m(long type);
1342
1343 Inserting an S3M file in an Allegro datafile is the same as inserting an
1344 IT file, except that the recommended type is "S3M ", the registration
1345 function is dumb_register_dat_s3m(), and the macro DUMB_DAT_S3M is
1346 provided for the type. The intuitive process of substituting S3M for IT in
1347 the above method will work.
1348
1349
1350void dumb_register_dat_mod(long type);
1351
1352 Inserting a MOD file in an Allegro datafile is the same as inserting an IT
1353 file, except that the recommended type is "MOD ", the registration
1354 function is dumb_register_dat_mod(), and the macro DUMB_DAT_MOD is
1355 provided for the type. The intuitive process of substituting MOD for IT in
1356 the above method will work.
1357
1358
1359****************************************
1360*** Sample Buffer Allocation Helpers ***
1361****************************************
1362
1363
1364 Many parts of DUMB require sample buffers allocated in a special way. A
1365 pointer to one looks like this:
1366
1367 sample_t **samples;
1368
1369 and it can be indexed as follows:
1370
1371 samples[channel_number][sample_position]
1372
1373 where 0 <= channel_number < n_channels
1374 and 0 <= sample_position < length.
1375
1376 The following helpers will allocate and deallocate such buffers for you.
1377 They will not initialise them, and DUMB always writes into these buffers
1378 by adding to what's already there, so you will generally have to call
1379 dumb_silence() too.
1380
1381
1382sample_t **create_sample_buffer(int n_channels, long length);
1383
1384 This will allocate a sample buffer to hold the specified number of samples
1385 for the specified number of channels. Don't forget to check the return
1386 value!
1387
1388 You will generally have to initialise the buffer by calling
1389 dumb_silence(); the channels will be stored consecutively in memory, so
1390 the following technique is officially supported:
1391
1392 dumb_silence(samples[0], n_channels * length);
1393
1394 See dumb_silence() for general information on what this function does.
1395
1396
1397void destroy_sample_buffer(sample_t **samples);
1398
1399 This function does the obvious: it frees up a sample buffer when you've
1400 finished with it. It is safe to pass a null pointer to this function.
1401
1402
1403************************
1404*** Silencing Helper ***
1405************************
1406
1407
1408void dumb_silence(sample_t *samples, long length);
1409
1410 This function simply stores 'length' samples' worth of silence in the
1411 array. It is typically used straight after allocating a sample buffer with
1412 create_sample_buffer().
1413
1414
1415**************************
1416*** Resampling Helpers ***
1417**************************
1418
1419
1420 Please forgive the odd section name; it has to do with DUMB's internal
1421 structure and the fact that the resampling algorithm is there not just for
1422 use in rendering module files but for use anywhere that a waveform needs
1423 resampling. Unfortunately DUMB's resampling algorithm is not ready to be
1424 documented and used yet. However, one thing can be documented, and that's
1425 the global variable controlling the resampling quality.
1426
1427 (Ironically, even this variable has changed! See deprec.txt for
1428 information on what it used to do.)
1429
1430
1431int dumb_resampling_quality;
1432
1433 Allows you to control the quality of all resampling that takes place. This
1434 may be set to any DUMB_RQ_* constant (except DUMB_RQ_N_LEVELS). Higher
1435 values will sound better, but lower values will use up less processor
1436 time. You may compare any two DUMB_RQ_* constants or values using the
1437 integer inequalities <, <=, > and >=; higher numbers represent higher-
1438 quality algorithms.
1439
1440 #define DUMB_RQ_ALIASING
1441
1442 | --___ 'Aliasing' has very noticeable and usually unwanted
1443 |__--- __ overtones. It will occasionally produce acceptable
1444 | ___-- results for noisy (impure) samples (or for cheap
1445 speakers!), but usually you will want to pay for
1446 the extra processor time, which isn't much, and go for linear
1447 interpolation.
1448
1449 #define DUMB_RQ_LINEAR
1450
1451 | __ Linear interpolation is a pretty good algorithm in most
1452 | / \ /\ cases. When resampling down a few octaves, however, you
1453 |/ \/ \__ may begin to notice unwanted high frequencies. You can
1454 reduce these by switching to cubic interpolation, but it
1455 will cost you some processor time.
1456
1457 #define DUMB_RQ_CUBIC
1458
1459 Cubic interpolation looks like a smooth curve to the eye, and will
1460 produce good results in most cases. At present this is the highest
1461 quality offered by DUMB, and also the default. While this may seem
1462 extravagant, GCC 3.x and an AthlonXP handle it quite well - and the
1463 general trend is for processors to get better!
1464
1465 #define DUMB_RQ_N_LEVELS
1466
1467 This represents the number of resampling quality levels DUMB provides.
1468 Values of dumb_resampling_quality from 0 to DUMB_RQ_N_LEVELS - 1 are
1469 valid. You can use this constant if you wish to offer the resampling
1470 quality as an option for the user.
1471
1472
1473*************************************
1474*** Allegro DUH Playing Functions ***
1475*************************************
1476
1477
1478 The functions in this section allow you to play back a DUH through
1479 Allegro's sound system. You must call Allegro's install_sound() function
1480 before you use them.
1481
1482
1483AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos,
1484 float volume, long bufsize, int freq);
1485
1486 Starts playing the specified DUH.
1487
1488 An AL_DUH_PLAYER represents one instance of the DUH playing. If you wish,
1489 you can have two or more AL_DUH_PLAYERs going at the same time, for the
1490 same DUH or for different ones. Each uses one of Allegro's audio streams
1491 and hence one voice. The voice will be given priority 255 initially, so a
1492 build-up of sound effects will not cause your music streams to cut off (as
1493 long as you don't give all your sound effects priority 255!). You can
1494 change the priority of a stream with al_duh_set_priority(). See Allegro's
1495 documentation for more information on how voice priorities work.
1496
1497 At present, n_channels can either be 1 or 2 for monaural or stereo
1498 respectively. If you use the debugging library, your program will abort if
1499 other values are passed; otherwise weird things will happen.
1500
1501 The DUH will start playing from position 'pos'. 0 represents the start of
1502 the DUH, and 65536 represents one second. Unlike other music systems, DUMB
1503 will always make sure every note is there right from the start. In other
1504 words, you can start a DUH at a point halfway through a long note, and you
1505 will still hear the long note.
1506
1507 The volume is a float. 1.0f is the pseudo-maximum. If you pass 1.0f, any
1508 properly designed DUH file will play nice and loud, but will not clip. You
1509 can pass a greater volume if you like, but be prepared for clipping to
1510 occur. Of course you can pass smaller values to play the DUH more quietly,
1511 and this will also resolve clipping issues in badly designed DUH files.
1512
1513 You will need to pass the AL_DUH_PLAYER to other functions when you need
1514 to stop or pause the DUH, change its volume, or otherwise modify the way
1515 it is playing. You will also need to pass it to al_poll_duh() at regular
1516 intervals; if the sound is choppy, try calling al_poll_duh() more often.
1517
1518 'bufsize' is the number of samples that will be rendered at once. 1024 is
1519 a suitable value for most purposes. The greater this is, the less often
1520 you will have to call al_poll_duh() - but when al_poll_duh() decides to
1521 fill the buffer, it will take longer doing so. If your game exhibits
1522 regular brief freezes, try reducing the buffer size. If the sound is
1523 choppy, however, you may have to increase it.
1524
1525 'freq' specifies the sampling frequency at which the DUH should be
1526 rendered. At present there is no (official and portable) way of knowing
1527 the frequency at which Allegro is mixing - but if you do know that
1528 frequency, passing it here will give the highest quality sound. If you
1529 reduce it, the DUH will sound less crisp but use less processor time.
1530
1531 When you have finished, you must pass the AL_DUH_PLAYER to al_stop_duh()
1532 to free up memory. Do not destroy the DUH beforehand.
1533
1534 There is no real need to check the return value from this function. The
1535 other functions can be called safely with null pointers, so if there is a
1536 problem, your music will simply not play.
1537
1538
1539void al_stop_duh(AL_DUH_PLAYER *dp);
1540
1541 This will stop an AL_DUH_PLAYER. You must call this when you have finished
1542 with it, before destroying the DUH. The pointer will no longer be valid on
1543 return from this function.
1544
1545
1546void al_pause_duh(AL_DUH_PLAYER *dp);
1547
1548 This will pause an AL_DUH_PLAYER. Use al_resume_duh() when you want it to
1549 continue. You can safely call al_poll_duh() while the music is paused, and
1550 it will do nothing.
1551
1552
1553void al_resume_duh(AL_DUH_PLAYER *dp);
1554
1555 Causes a paused AL_DUH_PLAYER to resume playing (see al_pause_duh()).
1556
1557
1558void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority);
1559
1560 This will set the priority of the audio stream underlying an
1561 AL_DUH_PLAYER. The priority is an integer ranging from 0 to 255. When
1562 too many samples play at the same time, those with lower priorities will
1563 be cut. 128 is the usual default with Allegro, but DUMB overrides the
1564 default for all AL_DUH_PLAYER structs: they will be set up initially with
1565 priority 255, so your music won't be cut (unless you play too many other
1566 streams or samples with priority 255). See Allegro's documentation for
1567 more information on priorities.
1568
1569
1570void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume);
1571
1572 This will set the volume of an AL_DUH_PLAYER. See al_start_duh() for
1573 details on the volume parameter.
1574
1575
1576int al_poll_duh(AL_DUH_PLAYER *dp);
1577
1578 An AL_DUH_PLAYER is not interrupt-driven. That means it will not play by
1579 itself. You must keep it alive from your main program. Call this function
1580 at regular intervals. If the sound crackles, try calling it more often.
1581 (There is nothing you can do if Windows decides to play with the hard
1582 disk; that will make your sound crackle no matter what you do.)
1583
1584 Normally this function will return zero. However, if it returns nonzero,
1585 that means the AL_DUH_PLAYER will not generate any more sound. Indeed the
1586 underlying audio stream and DUH_SIGRENDERER have been destroyed. When this
1587 happens, you can call al_stop_duh() whenever you wish - but you do not
1588 have to. Note that this function will wait two buffers' worth of samples
1589 before taking this action, allowing Allegro to mix the trailing sound
1590 before the audio stream is destroyed. This is an attempt to make sure your
1591 music does not get cut off prematurely, and it should work when using
1592 Allegro's mixer (the only option on DOS, the default on Linux as far as I
1593 know, but not the default on Windows). That said, if you immediately call
1594 Allegro's remove_sound() or exit your program, the music may get cut off.
1595 If you are using another mixer and experience problems, let me know (but I
1596 don't guarantee to be able to come up with an elegant solution, i.e. it
1597 might not get fixed).
1598
1599 In case you were wondering, it is not safe on all platforms to call
1600 al_poll_duh() from an interrupt context (that means an Allegro timer
1601 handler). Not only is no part of DUMB locked in memory, but many parts of
1602 DUMB allocate and free their memory on a call-by-call basis! Remember that
1603 any disk access that occurs in interrupt context is likely to crash the
1604 machine; this is explained more fully in howto.txt. This limitation only
1605 applies to DOS at present, and is due to the fact that the DOS file access
1606 functions are not re-entrant.
1607
1608 Multitasking systems are generally safe. If you are sure you don't want to
1609 target DOS, you can call al_poll_duh() from inside a timer handler, but I
1610 recommend including a construction like the following!
1611
1612 #ifdef ALLEGRO_DOS
1613 #error calling al_poll_duh() from a timer handler will not work in DOS!
1614 #endif
1615
1616 Furthermore, if you call al_poll_duh() from inside a timer handler, you
1617 must use a semaphore or other threading mechanism to make sure it is not
1618 executing when you call al_stop_duh(). If you don't know what a semaphore
1619 is, for Heaven's sake follow my advice and call al_poll_duh() from your
1620 main loop!
1621
1622
1623long al_duh_get_position(AL_DUH_PLAYER *dp);
1624
1625 Tells you what position an AL_DUH_PLAYER is up to, or -1 if it is invalid
1626 (perhaps owing to lack of memory). As usual, 65536 is one second. Note
1627 that this is a whole number, whereas a fractional part is stored
1628 internally; the sample will not be continuous if you terminate the
1629 AL_DUH_PLAYER and then reinitiate it with the same position. Furthermore,
1630 note that Allegro will not have mixed in all the sound up to this point;
1631 if you wait for this to reach a certain position and then terminate the
1632 AL_DUH_PLAYER, the sound will cut off too early. Please contact me if you
1633 need to get around this.
1634
1635
1636AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer
1637 (DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq);
1638
1639 If you have a DUH_SIGRENDERER, and would like to start playing music from
1640 it through an Allegro audio stream, use this function. Beware that it may
1641 return NULL, in which case you will have to call duh_end_sigrenderer()
1642 yourself instead of relying on the encapsulating AL_DUH_PLAYER to do it
1643 for you.
1644
1645
1646DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp);
1647
1648 This returns the DUH_SIGRENDERER contained in an AL_DUH_PLAYER, useful for
1649 controlling playback, installing callbacks, etc.
1650
1651
1652DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp);
1653
1654 This destroys an AL_DUH_PLAYER, but preserves the DUH_SIGRENDERER it
1655 contains, and returns it to you. You can then continue rendering samples
1656 from the DUH_SIGRENDERER and do whatever you like with them.
1657
1658
1659*********************
1660*** Thread Safety ***
1661*********************
1662
1663
1664The following points should pretty much sum up the essence of DUMB's thread
1665safety. If I haven't covered the one thing you'd like to do, please don't
1666hesitate to ask about it.
1667
1668DOs:
1669
1670- You may load and use multiple DUHs in separate threads.
1671
1672- You may change dumb_resampling_quality and dumb_it_max_to_mix while another
1673 thread is generating samples.
1674
1675DON'Ts:
1676
1677- You may not generate samples from the same DUH in multiple threads, even if
1678 you are using separate DUH_RENDERERs (separate AL_DUH_PLAYERS).
1679
1680
1681******************
1682*** Conclusion ***
1683******************
1684
1685
1686"DUMB is the bestest music player in the world because ..."
1687
1688Complete this sentence in fifteen words or fewer and receive a free copy of
1689DUMB! (Your Internet Service Provider may issue charges for your connection,
1690required for download of the Product. Your electricity supplier may issue
1691charges for the electricity consumed in writing the Product to a Permanent
1692Storage Device. You may have been charged for a Permanent Storage Device on
1693which to store the Product.)
1694
1695
1696Ben Davis
1697entheh@users.sf.net
1698IRC EFnet #dumb
1699See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/faq.txt b/apps/codecs/dumb/docs/faq.txt
new file mode 100644
index 0000000000..48b5ef3fff
--- /dev/null
+++ b/apps/codecs/dumb/docs/faq.txt
@@ -0,0 +1,263 @@
1TO DO: add question regarding set_close_button_callback vs set_window_close_hook
2
3/* _______ ____ __ ___ ___
4 * \ _ \ \ / \ / \ \ / / ' ' '
5 * | | \ \ | | || | \/ | . .
6 * | | | | | | || ||\ /| |
7 * | | | | | | || || \/ | | ' ' '
8 * | | | | | | || || | | . .
9 * | |_/ / \ \__// || | |
10 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
11 * / \
12 * / . \
13 * faq.txt - Frequently Asked Questions. / / \ \
14 * | < / \_
15 * This file covers some of the common problems | \/ /\ /
16 * and misconceptions people have with DUMB. If \_ / > /
17 * your problem is not covered here, please | \ / /
18 * contact me. I'll do my best to help - but | ' /
19 * don't be offended if I just direct you to the \__/
20 * manual!
21 */
22
23
24*****************************************************************************
25* I get a lot of strange warnings and errors when I compile my projects *
26* with this release of DUMB. They work with older versions! What happened? *
27*****************************************************************************
28
29 Some parts of DUMB's API have been deprecated. See docs/deprec.txt for
30 full details, including an explanation as to why your compiler warnings
31 and errors are so unfriendly, and information on how to fix each warning
32 or error.
33
34
35*****************************************************************************
36* When I try to compile DUMB with Allegro, it complains that it cannot find *
37* 'internal/alconfig.h'! What's wrong? *
38*****************************************************************************
39
40 In Allegro 4.0.1, and quite likely some other versions of Allegro, the
41 msvcmake batch file does not install Allegro properly. I believe this was
42 fixed in Allegro 4.0.2, but don't take my word for it. Some include files
43 are neglected, including alconfig.h. The fix is quite easy; you need to
44 copy all of Allegro's include files to your compiler's directory. The
45 following should do this for you (alter it accordingly depending on where
46 MSVC and Allegro are installed):
47
48 cd\progra~1\msvc\include
49 xcopy/s \allegro\include\*.*
50
51 You can safely tell it to overwrite all files.
52
53
54*****************************************************************************
55* When I build a project that uses DUMB, I get an error that it doesn't *
56* find -laldmbd! What's wrong? *
57*****************************************************************************
58
59 See the notes for DUMB v0.8 in release.txt; the existence of libaldmbd.a
60 in DUMB v0.7 was due to a mistake in the makefiles. It should be
61 libaldmd.a, in order to maintain DOS compatibility. All subsequent
62 releases get it right, but you will have to change your project files to
63 allow for the change. If this is someone else's project, please let them
64 know that it needs changing.
65
66
67*****************************************************************************
68* When I build a project that uses DUMB, I get some linker errors about *
69* _free, _malloc, etc. already being defined in LIBC.lib! What's wrong? *
70*****************************************************************************
71
72 MSVC offers three different implementations of the standard libraries.
73 When you link statically with a library, you have to use the same
74 implementation that the library uses. You need the multithreaded DLL
75 implementation, which you can select by passing /MD when you compile (not
76 when you link). See howto.txt for details.
77
78
79*****************************************************************************
80* I created an IT file with Impulse Tracker, but DUMB won't play it! Why? *
81*****************************************************************************
82
83 You probably created some patterns but didn't give any information on the
84 order in which they should be played. Impulse Tracker will also fail to
85 play your music if you press F5. Press F11 and you will have an
86 opportunity to create an order list, required for playback.
87
88
89*****************************************************************************
90* I created an IT file with ModPlug Tracker and I have it fading out at the *
91* end. Why won't it loop when I play it with DUMB? *
92*****************************************************************************
93
94 It loops at zero volume. This is what Impulse Tracker itself does. Fix the
95 IT file by setting the global volume explicitly (Vxx in the effects
96 column), either at the start, or right at the end before looping. Also see
97 the next two questions.
98
99
100*****************************************************************************
101* My module plays too loud and distorts badly with DUMB! What can I do? *
102*****************************************************************************
103
104 This problem is most often caused by ModPlug Tracker, which has a complete
105 lack of regard for the playback volume of the original tracker. See the
106 next question for DUMB's official position with regard to ModPlug Tracker.
107 If you wrote your module with ModPlug Tracker, please try loading it with
108 the original tracker and see if it distorts there too. If it does, reduce
109 the volume. If not, then it's a problem with DUMB; please let me know.
110
111 If for whatever reason you cannot modify the module file itself, you can
112 make it sound better by reducing the volume passed to al_start_duh().
113
114
115*****************************************************************************
116* I created a music module with ModPlug Tracker, and DUMB doesn't play it *
117* right! *
118*****************************************************************************
119
120 DUMB cannot and will not support ModPlug Tracker. Please see
121 docs/modplug.txt for details. The original trackers, which DUMB is
122 designed to mimic as closely as possible, are listed in readme.txt.
123 If you find DUMB plays your module differently from the original tracker,
124 then please contact me.
125
126
127*****************************************************************************
128* My program crashes as soon as I try to load anything with DUMB! *
129*****************************************************************************
130
131 Please take my advice and use the debugging build of DUMB, not the
132 optimised build. Then you'll probably find it aborts instead of crashing.
133 In this case you probably forgot to register a DUMBFILE system; this is
134 necessary for loading stand-alone files, though not for loading Allegro
135 datafiles with embedded music. Follow the instructions in docs/howto.txt
136 carefully and you shouldn't have this problem.
137
138 If DUMB crashes with a specific music module, please let me know.
139
140
141*****************************************************************************
142* I want to use the stdio file access functions to load stand-alone music *
143* files, but I also want to load datafiles containing music files. The docs *
144* say I shouldn't call both dumb_register_stdfiles() and *
145* dumb_register_packfiles(). What shall I do? *
146*****************************************************************************
147
148 When you register a DUMBFILE system, it only applies to files opened with
149 dumbfile_open(), i.e. separate files. When a file is embedded in a
150 datafile, dumbfile_open_ex() is used to read it, enabling it to use
151 PACKFILEs regardless of which DUMBFILE system is registered. In short, you
152 do not need to call dumb_register_packfiles() in order to load datafiles
153 with embedded music. See the section on "Sequential File Input" in
154 docs/dumb.txt if you're interested in how all this works.
155
156
157*****************************************************************************
158* I want to read a specific object in a datafile using Allegro's *
159* "demo.dat#MY_MUSIC" syntax. Why won't it work? *
160*****************************************************************************
161
162 Did you call dumb_register_packfiles(), or did you call
163 dumb_register_stdfiles()? It will only work if you use the former.
164
165
166*****************************************************************************
167* My program runs, but no music plays! What am I doing wrong? *
168*****************************************************************************
169
170 There are a number of possible causes for this. The most likely reason is
171 that you aren't calling al_poll_duh(); see docs/howto.txt for further
172 information.
173
174 Other possible causes are as follows:
175
176 - The speakers are turned down (duh)
177 - The volume of some system mixer is turned down
178 - Another program is using the sound card (not a problem for most modern
179 systems)
180 - You didn't initialise Allegro's sound system; see install_sound() in
181 Allegro's docs
182 - Allegro's drivers don't work on your system and chosen platform
183
184 In order to narrow down the cause, consider the following:
185
186 - Do you get any other sound from your program?
187 - Do other Allegro+DUMB programs generate sound?
188 - Do other Allegro programs generate sound?
189 - Do other non-Allegro programs generate sound?
190 - Does your program fail only on a specific platform (e.g. DOS but not
191 Windows)?
192
193 This problem is highly system-specific; please try hard to solve it by
194 yourself before contacting me. However, if you think this problem could
195 affect other people, please let me know what the problem is and how you
196 fixed it, if you did. Be as specific as possible.
197
198
199*****************************************************************************
200* The music stutters! What can I do? *
201*****************************************************************************
202
203 If you have an older computer, it may not be able to cope with the load.
204 Try reducing quality options; look up dumb_resampling_quality and
205 dumb_it_max_to_mix in docs/dumb.txt, and consider changing the frequency
206 you pass to al_start_duh().
207
208 Stuttering may not be caused by excessive load. To find out, try
209 increasing the buffer size passed to al_start_duh(). Beware of making it
210 too big though; older systems will freeze periodically if it's too big,
211 because they render larger chunks less frequently. The timing of callbacks
212 will also be less accurate, if you are using those.
213
214 If you're using the 'dumbplay' example, you can control these parameters
215 by editing dumb.ini.
216
217
218*****************************************************************************
219* Why does DUMB use so much processor time compared with other players? *
220*****************************************************************************
221
222 This should be less so in this release than in previous releases; the
223 resampling and filtering algorithms have been optimised.
224
225 By default, DUMB uses the most expensive resampling quality option. I've
226 found on an AthlonXP 1800+ and on a Pentium 233 that it typically uses
227 about twice as much processor time as the least expensive option.
228
229 Try setting dumb_resampling_quality to DUMB_RQ_ALIASING or DUMB_RQ_LINEAR.
230 See dumb.txt for more information. If you're using the example programs,
231 you can control this variable by editing dumb.ini.
232
233 DUMB uses 32-bit ints for mixing. Some players use 16-bit ints, and are
234 therefore marginally faster (not much!) and lower quality. So you can't
235 expect DUMB to beat these players. Furthermore, DUMB is currently written
236 entirely in C. GCC does an impressive job on the C code, but that's not to
237 say some custom-written assembly language couldn't beat it ...
238
239
240*****************************************************************************
241* Why does DUMB generate so much background noise? *
242*****************************************************************************
243
244 You're probably using the DOS build on a system with bad Sound Blaster
245 compatibility (most Windows XP systems fall in this category). This would
246 mean DUMB could only access an 8-bit driver. The Windows build will almost
247 certainly give better results. Your DOS binary will still give good
248 results on systems with better compatibility (like my Windows 98 system).
249
250
251*****************************************************************************
252* I e-mailed you and you replied with "RTFM"! What does that mean? *
253*****************************************************************************
254
255 Read The Manual. If it's a specific problem, I'll probably be kind and
256 tell you where to look in the manual. However, if I get the impression you
257 haven't even looked for a solution in the manual, expect no mercy ...
258
259
260Ben Davis
261entheh@users.sf.net
262IRC EFnet #dumb
263See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/fnptr.txt b/apps/codecs/dumb/docs/fnptr.txt
new file mode 100644
index 0000000000..a5fb216822
--- /dev/null
+++ b/apps/codecs/dumb/docs/fnptr.txt
@@ -0,0 +1,113 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * fnptr.txt - Function pointer explanation. / / \ \
12 * | < / \_
13 * | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21C allows you to create and use function pointers. A function pointer is a
22variable that points to a function, and you can use it to call that function.
23Why is this useful?
24
25Function pointers can be passed as parameters. As an example, here's a
26function from Allegro:
27
28 void create_light_table(COLOR_MAP *table, const PALETTE pal, int r, g, b,
29 void (*callback)(int pos));
30
31Don't worry about the syntax just yet, but the last parameter, 'callback', is
32a pointer to a function that takes an int parameter. create_light_table() can
33take some time to complete its work, and you may want to display a progress
34indicator. So you write a function to draw the progress indicator, and then,
35for 'callback', you specify a pointer to your function. This will enable
36create_light_table() to call your function at intervals during its
37processing. (If you don't want to use the callback, you can pass NULL, but
38this only works because create_light_table() checks actively for NULL. You
39can't always specify NULL when you want nothing to happen.)
40
41There are many other uses. In addition to using function pointers as
42parameters, Allegro has some global function pointers you can set to point to
43your functions. Function pointers can also be used in structs, and this is
44where DUMB makes the most use of them.
45
46So how are they used?
47
48 void bar(void) { ... } /* Here's a function */
49 void (*foo)(void) = &bar; /* Take a pointer */
50 (*foo)(); /* Call the function */
51
52 char *baz(float a) { ... } /* Here's another function */
53 char *(*foobarbaz)(float a) = &baz; /* Take a pointer */
54 char *rv = (*foobarbaz)(0.1); /* Call the function */
55
56In both these cases, note how the statement for calling the pointed-to
57function (third line) resembles the definition of the function pointer
58(second line). This is true of any variable in C, and can lead to some truly
59obfuscated definitions if you are that way inclined. Such definitions can be
60clarified with typedefs, but before you use those, it is important you
61understand how the above statements work. I speak from experience: function
62pointer notation looks random and scary, until you understand why it's the
63way it is; then it makes perfect sense.
64
65(It is actually permissible to omit the & when taking a pointer and to write
66e.g. foobarbaz(0.1) instead of (*foobarbaz)(0.1). However, I recommend not
67doing this, since the syntax for using the pointer no longer resembles the
68definition. Writing e.g. (*foobarbaz)(0.1) also makes a clear distinction
69between function pointer calls and ordinary function calls, which makes code
70more readable.)
71
72Note that function pointers have the return value and parameter list
73specified. A function pointer can only point to a function with a matching
74return value and matching parameters. (You can break this rule by casting the
75pointer explicitly, but there is no situation where doing so is portable to
76all computers, and I strongly advise against it unless you're writing system
77code. If you're not sure whether you're writing system code or not, then
78you're not.)
79
80The parameter names need not match (although the types must). If you wish to
81rename a parameter in your function, you do not have to change the function
82pointer accordingly. In fact, when you define a function pointer, you don't
83even have to specify the names of parameters if you don't want to. I normally
84do so for clarity.
85
86It is possible to typedef a function pointer. In order to typedef a function
87pointer, you start by declaring the pointer as a variable:
88
89 void (*myfunc)(void);
90
91Then you write 'typedef' before it and replace the variable name, which is
92myfunc, with the type name (this rule can be applied to any variable when you
93want to use typedef):
94
95 typedef void (*MYTYPE)(void);
96
97Now 'MYTYPE' represents a pointer to a function with no parameters and no
98return value. The following two lines are completely equivalent:
99
100 MYTYPE myfunc;
101 void (*myfunc)(void);
102
103Note that we use MYTYPE without an asterisk (*), since it is already a
104pointer.
105
106That's it. If you feel anything should be explained better here, or if you
107feel something should be added, please don't hesitate to let me know!
108
109
110Ben Davis
111entheh@users.sf.net
112IRC EFnet #dumb
113See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/howto.txt b/apps/codecs/dumb/docs/howto.txt
new file mode 100644
index 0000000000..0e7057da2c
--- /dev/null
+++ b/apps/codecs/dumb/docs/howto.txt
@@ -0,0 +1,845 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * howto.txt - How To Use DUMB. / / \ \
12 * | < / \_
13 * See readme.txt for general information on | \/ /\ /
14 * DUMB and how to set it up. \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21********************
22*** Introduction ***
23********************
24
25
26Welcome to the DUMB How-To! It is assumed here that you have already set DUMB
27up on your system, with or without Allegro. If not, please see readme.txt.
28
29
30*********************************
31*** Adding music to your game ***
32*********************************
33
34
35These instructions will help you add a piece of music to your game, assuming
36your music is stored in a stand-alone IT, XM, S3M or MOD file. If you wish to
37use a different method (such as putting the music file in an Allegro
38datafile), please follow these instructions first, test your program, and
39then follow the instructions further down for adapting your code.
40
41
421. You need to include DUMB's header file. If you have Allegro, add the
43 following line to the top of your source file (or at the top of each file
44 where you wish to use DUMB):
45
46 #include <aldumb.h>
47
48 If you do not have Allegro or do not wish to use it, use dumb.h instead.
49
50
512. You need to link with DUMB's library file or files. If you are compiling
52 with GCC from a command line on any platform, you need to add the
53 following to the command line:
54
55 If you are using Allegro: -laldmd -ldumbd
56 If you are not using Allegro: -ldumbd
57
58 If you are using MSVC from the command line:
59
60 If you are using Allegro: /link aldmd.lib dumbd.lib
61 If you are not using Allegro: /link dumbd.lib
62
63 With MSVC, you must also add /MD to the command line when compiling (not
64 when linking).
65
66 Note that -laldmd or aldmd.lib must PRECEDE alleg.lib, -lalleg_s,
67 `allegro-config --libs`, or whatever you are already using to link with
68 Allegro. For MSVC users, the /MD flag selects the multithreaded DLL
69 implementation of the standard libraries; since DUMB is statically linked,
70 you have to use the same library DUMB uses. You would also need this flag
71 to link statically with Allegro; if you already have it, there's no need
72 to put it twice.
73
74 (If anyone would like to contribute instructions for doing the above using
75 MSVC's IDE, please contact me. Contact details are at the end of this
76 file.)
77
78 If you are using RHIDE, go to Options -> Libraries. You will need to type
79 'aldmd' and 'dumbd' in two boxes, making sure 'aldmd' comes above whatever
80 you are using to link with Allegro (or just put 'dumbd' if you are not
81 using Allegro). Make sure the box next to each of these libraries is
82 checked.
83
84 The above are the debugging libraries. It is VERY HIGHLY RECOMMENDED that
85 you use the debugging libraries at first. The reason is as follows.
86 Although DUMB is supposedly robust against corrupt music files and things
87 like lack of memory, it will NOT tolerate programmer error. If you write
88 faulty code, DUMB will probably crash rather than returning an error code
89 for you. However, the debugging libraries will abort in many cases,
90 enabling you to find out what the cause is.
91
92 Once your program is up and running reliably, you can replace 'aldmd' with
93 'aldmb' and 'dumbd' with 'dumb'. Don't forget to do this, or DUMB will be
94 a lot slower than it should be!
95
96
973. As you use DUMB, it may claim system resources (memory in particular). You
98 will need to arrange for these resources to be freed at the end. Doing so
99 is very easy. Simply write the following line at the top of your main
100 function, but below allegro_init() if you are using Allegro:
101
102 atexit(&dumb_exit);
103
104 This arranges for the function dumb_exit() to be called when your program
105 exits; you do not need to call dumb_exit() yourself. This method is
106 preferable to calling dumb_exit() manually, as it will free resources even
107 if your program aborts unexpectedly.
108
109 If you are happy with this, please skip ahead to Step 4. If you are
110 interested in alternative methods, read on, but read on carefully.
111
112 In fact it mostly doesn't matter where you put the above atexit() line,
113 provided it gets called only once, and before you do anything with DUMB.
114 If you are using DUMB with Allegro, it is recommended that you write the
115 functions in this order:
116
117 allegro_init();
118 atexit(&dumb_exit);
119
120 And then you must NOT call allegro_exit() yourself (because it has to be
121 called after dumb_exit()). Alternatively, if you prefer not to use
122 atexit() (or you cannot), you will have to do the following before
123 exiting:
124
125 dumb_exit();
126 allegro_exit();
127
128
1294. DUMB does not automatically do any of its own file input. You have to tell
130 it how to read files. Don't worry, it's easy. Simply call the following
131 function near the beginning of your program, after your atexit() call:
132
133 dumb_register_stdfiles();
134
135 This tells DUMB to use ordinary stdio FILE structs for reading and writing
136 files. If you are using Allegro and would rather DUMB used PACKFILEs, call
137 the following function INSTEAD:
138
139 dumb_register_packfiles();
140
141 In the latter case, DUMB will be affected by any password you set with
142 packfile_password() in the same way that other PACKFILEs are.
143
144 Note that the procedure for loading datafiles with embedded music is
145 independent of these two functions; even if you will be loading datafiles,
146 you can use either of these functions. If you are loading datafiles, your
147 executable might be slightly smaller if you use dumb_register_packfiles().
148 On the other hand, dumb_register_stdfiles() will probably be faster. If
149 you are only ever going to load datafiles and never stand-alone files, you
150 can actually leave this step out; but I would recommend you put this in,
151 test your code with a stand-alone file, then follow the instructions in
152 the next section in order to adapt your code to use the datafile (you will
153 be reminded that you can remove the function call).
154
155
1565. If you are using Allegro, you'll have to initialise Allegro's sound
157 system. In most cases the following line will do the job:
158
159 install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
160
161 You may like to initialise a MIDI driver though; see Allegro's docs for
162 details. Put this line after allegro_init().
163
164
1656. All pieces of music are stored in memory in DUH structs. To handle these,
166 you must define pointers to them. Such pointers look like this:
167
168 DUH *myduh;
169
170 You can of course replace 'myduh' with anything you like. If you are
171 unfamiliar with pointers, please see ptr.txt. It is very important that
172 you understand these if you wish to use DUMB correctly.
173
174 You do not have direct access to the contents of a DUH struct, so do not
175 try. DUMB's functions provide everything you need; if you disagree, please
176 let me know and I shall see what I can do. Contact details are at the end
177 of this file.
178
179 Given the above definition, you can load a piece of music using one of the
180 following lines, depending on what file format you want to load:
181
182 myduh = dumb_load_it("a_one.it");
183 myduh = dumb_load_xm("a_two.xm");
184 myduh = dumb_load_s3m("a_one_two.s3m");
185 myduh = dumb_load_mod("three_four.mod");
186
187 Obviously you can use relative or absolute paths as normal. You should
188 always use forward slash (/), not backslash (\), when coding in C and
189 similar languages.
190
191 Every piece of music you load must be unloaded when you've finished with
192 it. When you type the above line in, it is good practice to type the
193 following line in at the same time, but put it at the end of the program:
194
195 unload_duh(myduh);
196
197 You will now be able to use the DUH struct anywhere in between the two
198 lines you just added. There is no need to check the return value; if the
199 DUH failed to load for one reason or another (this could be due to lack of
200 memory as well as the file not being there), then DUMB will do nothing -
201 safely.
202
203
2047. From this step onwards, it will be assumed you're using Allegro. If not,
205 please read these steps anyway, and then see the section entitled
206 "Rendering music into a buffer". You will have to write your own playback
207 code using whatever sound output system is available. Alternatively you
208 may like to write data to a file (especially if you have a file that
209 consumes a lot of processor time), but beware that any streaming audio
210 format is likely to be substantially larger than the module file you
211 generate it from, and formats like MP3 will be lower quality. You might
212 not be able to hear the difference between the MP3 and the original, but
213 many people can and don't like it, so please consider them. I'm one of
214 them. If you really want to use a lossy compression format, I highly
215 recommend Ogg Vorbis:
216
217 http://www.vorbis.com/
218
219 But I digress.
220
221 In order to play the DUH you loaded, you need to define a pointer to an
222 AL_DUH_PLAYER struct:
223
224 AL_DUH_PLAYER *dp;
225
226 Two of the functions you will need are prototyped as follows:
227
228 AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos,
229 float volume, long bufsize, int freq);
230
231 void al_stop_duh(AL_DUH_PLAYER *dp);
232
233 As you can see, al_start_duh() returns a pointer to an AL_DUH_PLAYER
234 struct when you call it. You then pass this pointer to all the other
235 functions. Again, if it is a NULL pointer for whatever reason (usually
236 lack of memory), DUMB will safely do nothing. When you call al_stop_duh(),
237 the pointer becomes invalid and you should not use it again; if there's
238 any risk of the pointer being used again, it is wise to set it to NULL at
239 this point. You can reassign the variable with a new call to
240 al_start_duh() of course.
241
242 Set 'n_channels' to 1 or 2 for mono or stereo respectively. Note that this
243 parameter has nothing to do with the number of samples that can play at
244 once in a music module. Set 'pos' to 0 to play from the beginning; each
245 time you add 65536, you will have advanced one second into the piece. As a
246 general rule, set the volume to 1.0f and adjust it later if the music is
247 too loud or too quiet - but see Allegro's set_volume_per_voice() function
248 first.
249
250 'bufsize' can generally be set to 4096. If your music stutters, try
251 increasing it; if your game freezes periodically, try reducing it. Find a
252 happy medium. Set 'freq' to 48000 for the best quality, though 44100 will
253 do in most cases. 22050 will be fine for a lot of music, though 11025 may
254 sound muffled. You can choose any other value, higher, lower or in
255 between. If your music stutters, and increasing 'bufsize' doesn't fix it,
256 try reducing this value.
257
258 Once you have put in a call to al_start_duh(), it is good practice to
259 insert the call to al_stop_duh() at the same time. You must call
260 al_stop_duh() before the DUH is unloaded (unload_duh(), Step 6 above).
261
262 Don't get impetuous, your program is not ready yet! Proceed to Step 8.
263
264
2658. DUMB does not play music in the background for you; if you were expecting
266 it to do so, please see the explanation at the end of this step. For your
267 music to be played, you have to call another function at regular
268 intervals. Here is its prototype:
269
270 int al_poll_duh(AL_DUH_PLAYER *dp);
271
272 Do NOT call this function from inside a timer function unless you really
273 know what you are doing. The reasons why this is bad are explained
274 further down. You should call it from your main program.
275
276 Simply writing the following line will be sufficient in general, if you
277 have a variable 'dp' that points to your AL_DUH_PLAYER struct.
278
279 al_poll_duh(dp);
280
281 As a general rule, calling this once for each logic update will do the
282 trick. If, however, you are executing time-consuming algorithms such as
283 software 3D rendering, you may wish to insert calls to this function in
284 the middle of those algorithms. You cannot call this function too often
285 (within reason); if it has nothing to do it will return immediately.
286
287 Exactly how often you need to call the function depends on the values for
288 'bufsize' and 'freq' that you passed to al_start_duh():
289
290 n = freq / bufsize;
291
292 You have to call al_poll_duh() at least n times a second. Do not hesitate
293 to call it more often for safety; if the sound stutters, you may need to
294 do just that. (Or you may need to increase the buffer size or reduce the
295 quality settings; the only way to find out is to try.)
296
297 For now, don't worry about al_poll_duh()'s return value. As soon as you
298 need it, it will be explained.
299
300 If you are happy, please skip to Step 9. If you were expecting DUMB to
301 play your music in the background, please read on.
302
303 The natural way to play music in the background on most operating systems
304 nowadays is to use threads. DOS was not built with multithreading in mind,
305 and its system operations (notably disk access) assume they will only be
306 used from a single thread.
307
308 Interrupts are the next best thing to threads. A DOS hardware interrupt
309 could be triggered at any moment, and a handler function will be called.
310 This is how Allegro's timer functions work. Unfortunately, what you can do
311 inside an interrupt handler is very limited. For one thing, all code and
312 data used by the handler must be locked in memory; if not, it could get
313 written to disk (virtual memory). If the main program was accessing the
314 disk when it got interrupted, the system would then die a horrible death.
315 This precludes the possibility of allocating extra memory inside the
316 handler, and DUMB does a lot of that in al_poll_duh().
317
318 Given DUMB's architecture, which cannot change for reasons which will
319 become apparent in future versions, this renders it impossible to come up
320 with a portable solution for making DUMB play music in the background.
321 Having said that, if you wish to write your own wrapper for al_poll_duh()
322 and use it in a thread, there is nothing stopping you. If you do do this,
323 you will have to be very careful when stopping the music; see the
324 description of al_poll_duh() in dumb.txt for more information.
325
326 So why not kill DOS? It is all too common a practice among programmers to
327 quote the phrase, "DOS is as dead as the dodo." Despite being a decidedly
328 derisible demonstation of the dreary device of alliteration, it shows a
329 distinct lack of experience. Many embedded systems still use DOS because
330 it provides hardware access capabilities and real-time possibilities
331 unparalleled by any current multitasking operating system. For an argument
332 closer to home, I used to use RHIDE for DOS before I switched to Linux,
333 and I have not found a single Freeware Windows IDE that measures up to
334 RHIDE. I'm sure many people are in the same boat, and really appreciate
335 DUMB's DOS port.
336
337 We will not be removing DOS support from DUMB. Any blind suggestions to do
338 so will be met with fiery flames. You have been warned.
339
340
3419. Test your program!
342
343 If you have trouble, check through the above steps to make sure you didn't
344 miss one out. Refer to faq.txt to see if your problem is addressed there.
345 If you still have trouble, contact me; details are at the end of this
346 file.
347
348
349**********************************
350*** Controlling music playback ***
351**********************************
352
353
354Here I describe some common operations you may wish to perform. The method
355for doing so will seem a bit strange sometimes, as will the names of the
356structs. However, there is a reason behind everything. If you would like to
357do more exotic things, or better understand some of the methods used here,
358then see dumb.txt, which covers everything from the ground up.
359
360
361To control playback quality:
362
363 #define DUMB_RQ_ALIASING
364 #define DUMB_RQ_LINEAR
365 #define DUMB_RQ_CUBIC
366 #define DUMB_RQ_N_LEVELS
367 extern int dumb_resampling_quality;
368 extern int dumb_it_max_to_mix;
369
370 Please note that dumb_resampling_quality has changed in DUMB v0.9.2. See
371 deprec.txt for more details on the change.
372
373 dumb_resampling_quality can be set to any of the DUMB_RQ_* constants
374 (except DUMB_RQ_N_LEVELS; see below). Resampling is the term given to the
375 process of adjusting a sample's pitch (in this context).
376 dumb_resampling_quality defaults to DUMB_RQ_CUBIC, which sounds nice but
377 takes a lot of processor power. Try reducing it if you have an older
378 computer or if you are trying to mix an insane number of samples (or
379 both!). See dumb.txt for details on what the different values actually do.
380
381 If you wish to give this option to your user, you can use
382 DUMB_RQ_N_LEVELS. All the values from 0 to DUMB_RQ_N_LEVELS - 1 will be
383 valid resampling levels. If a value outside this range is chosen, it is
384 not the end of the world; DUMB will behave as if you had chosen the value
385 at whichever extreme you went beyond.
386
387 dumb_it_max_to_mix, defaulting to 64, is the maximum number of samples
388 DUMB will ever mix together when playing an IT, XM, S3M or MOD file.
389 Unlike many other music systems, DUMB will still keep track of all samples
390 (up to a fixed maximum of 256 of them, roughly speaking), and then will
391 just render as many of them as this variable permits, starting with the
392 loudest ones. When samples are cut or come back in, the exact timings will
393 not generally be predictable - but nor will they be important.
394
395 dumb_it_max_to_mix applies to each currently playing module file
396 independently. So if you set it to 64, but render two modules
397 simultaneously, DUMB could end up mixing up to 128 samples.
398
399
400To pause and resume playback, set the volume, get the current playback
401position, or get the length of time a DUH will play for before either looping
402or freezing (effect F00 in XM and MOD files, which means no new notes will be
403played but any existing notes will continue):
404
405 void al_pause_duh(AL_DUH_PLAYER *dp);
406 void al_resume_duh(AL_DUH_PLAYER *dp);
407 void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume);
408 long al_duh_get_position(AL_DUH_PLAYER *dp);
409
410 long duh_get_length(DUH *duh);
411
412 These functions are pretty self-explanatory. The volume passed to
413 al_duh_set_volume() and the position returned by al_duh_get_position() are
414 in the same units as those you passed to al_start_duh(). The length
415 returned by duh_get_length() is in the same units as the aforementioned
416 position; see dumb.txt for more information on this function. Be careful
417 with al_duh_get_position(); it will return a position slightly ahead of
418 what you can hear, because the system has to keep ahead slightly to avoid
419 stuttering.
420
421
422To prevent the music from looping and/or freezing:
423
424 DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp);
425 DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer);
426
427 void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer,
428 int (*callback)(void *data), void *data);
429 void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer,
430 int (*callback)(void *data), void *data);
431
432 int dumb_it_callback_terminate(void *data);
433
434 If you are unfamiliar with function pointers, please see fnptr.txt.
435
436 Note that these functions apply to IT, XM, S3M and MOD files - not just to
437 IT files. This holds true throughout DUMB, for all functions with "it" in
438 the name. The xm_speed_zero event can only occur with XM and MOD files.
439
440 The first two functions will return a pointer to a struct contained by the
441 struct you pass. This system is necessary to ensure that these operations
442 are possible when not using Allegro. Typically you would write the
443 following code:
444
445 {
446 DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp);
447 DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sigrenderer);
448 dumb_it_set_loop_callback(itsr, &dumb_it_callback_terminate, NULL);
449 dumb_it_set_xm_speed_zero_callback
450 (itsr, &dumb_it_callback_terminate, NULL);
451 }
452
453 Once you have done this, the return value of al_poll_duh() becomes
454 significant. It will be 0 as long as the music is playing. When the music
455 stops, al_poll_duh() will return nonzero. You can call al_stop_duh() and
456 do something else as soon as you wish, but calling al_poll_duh() some more
457 will not do any harm.
458
459 al_poll_duh() will also return 1 if the music could not be loaded, or if
460 memory was short when trying to play it, or if it was a quirky music file
461 with no music in it (technically one with an empty order list). This
462 happens regardless of whether or not you execute the above code to disable
463 looping. Normally you shouldn't need to worry about this.
464
465 To undo the above and make DUMB loop or freeze again, pass NULL instead of
466 &dumb_it_callback_terminate. If you would like to fade on looping, or loop
467 a finite number of times, or display a message when looping, or whatever,
468 you will have to write your own callback function. In this case, please
469 see dumb.txt.
470
471 Note that the above code can safely be applied for a DUH that doesn't
472 contain a music module but contains some other kind of music.
473 duh_get_it_sigrenderer() will return NULL, and the code will do nothing.
474
475
476To analyse the audio as it's generated:
477
478 typedef int sample_t;
479
480 typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data,
481 const sample_t *const *samples, int n_channels, long length);
482
483 void duh_sigrenderer_set_analyser_callback(DUH_SIGRENDERER *sigrenderer,
484 DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data);
485
486 If the above confuses you, see fnptr.txt. These functions, along with
487 al_duh_get_sigrenderer() from the last section, enable you to register a
488 callback function. Every time some samples are generated, they will be
489 passed to this function. This enables you to display an oscilloscope or
490 spectrum analyser, for example.
491
492 Beware: your callback function may occasionally be called with
493 samples == NULL. This means the main program has decided to skip through
494 the music without generating any data. You should handle this case
495 elegantly, typically by returning immediately, but you may wish to make a
496 note of the fact that the music is being skipped, for whatever reason.
497
498 Beware again: if the main program ever calls duh_sigrenderer_get_samples()
499 on a buffer that isn't all silence, this callback function will be passed
500 the existing buffer after mixing, and thus it will include the original
501 data. This will not be an issue if you stick to duh_render(), which always
502 starts with a buffer filled with silence.
503
504 The samples array is two-dimensional. Refer to it as follows:
505
506 samples[channel_number][sample_position]
507
508 where 0 <= channel_number < n_channels,
509 and 0 <= sample_position < length.
510
511 In addition you can pass any 'data' pointer you like to
512 duh_sigrenderer_set_analyser_callback(), and this pointer will be relayed
513 to your callback function each time.
514
515 To remove the callback function, pass NULL to
516 duh_sigrenderer_set_analyser_callback().
517
518
519Everything below this point assumes some knowledge of how a music module is
520constructed. If you do not have this knowledge, talk to whoever is writing
521music for you, or download a tracking program and play with it (see
522readme.txt).
523
524
525To start playing an IT, XM, S3M or MOD from an arbitrary order number (the
526default being 0, the beginning of the song), use the following:
527
528 DUH_SIGRENDERER *dumb_it_start_at_order
529 (DUH *duh, int n_channels, int startorder);
530 AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer
531 (DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq);
532
533 The usage of these functions is as follows:
534
535 {
536 DUH_SIGRENDERER *sr = dumb_it_start_at_order
537 (duh, n_channels, startorder);
538 dp = al_duh_encapsulate_sigrenderer(sr, volume, bufsize, freq);
539 }
540
541 Replace 'dp' with whatever your AL_DUH_PLAYER pointer is. You also need
542 to insert suitable values for n_channels, startorder, volume, bufsize and
543 freq. These have the same meaning as those passed to al_start_duh().
544
545 WARNING: after passing a pointer to an "encapsulate" function, do not use
546 that pointer again. (More specifically, do not use it again if
547 the function returns NULL, because the function will have
548 destroyed the pointer if this happens, to help prevent memory
549 leaks.) There will be a "get" function with which you can obtain
550 the original pointer if it is still valid, or NULL otherwise.
551
552 The above functions will fail (safely) if you try to use them with a DUH
553 that contains a different type of music.
554
555 Notice that there is no 'pos' parameter. If you would like to skip through
556 the music, you can use this function:
557
558 long duh_sigrenderer_get_samples(
559 DUH_SIGRENDERER *sigrenderer,
560 float volume, float delta,
561 long size, sample_t **samples
562 );
563
564 Pass 0 for volume and NULL for samples, and this function will skip
565 through the music nice and quickly. So insert the following between the
566 two above statements:
567
568 duh_sigrenderer_get_samples(sr, 0, 65536.0f / freq, pos, NULL);
569
570 Substitute for 'freq' and 'pos'. An explanation of the 'delta' parameter
571 can be found further down in this file.
572
573 Finally, note that duh_get_length() is only meaningful when you start
574 playing music from order 0.
575
576
577If an IT file contains Zxx effects, DUMB will generate MIDI messages, which
578will control the low-pass resonant filters unless the IT file actively
579specifies something else. In rare cases this may not be what the Zxx effects
580were intended to do; if this is the case, you can block the MIDI messages as
581follows. Note that this does NOT mean filters are disabled; if an instrument
582specifies initial cut-off and resonance values, or has a filter envelope,
583then filters will be applied. It only makes sense to use this procedure at
584the beginning of playback.
585
586 void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer,
587 int (*callback)(void *data, int channel, unsigned char byte),
588 void *data);
589
590 int dumb_it_callback_midi_block(void *data, int channel,
591 unsigned char byte);
592
593 Using some functions described in the previous section, we arrive at the
594 following code:
595
596 {
597 DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp);
598 DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sigrenderer);
599 dumb_it_set_midi_callback(itsr, &dumb_it_callback_midi_block, NULL);
600 }
601
602DUMB offers no way of disabling filters completely. Disabling filters is not
603recommended as a means to reduce processor usage, as it will completely
604damage any piece of music that uses the filters. If you want lower processor
605consumption, use a piece of music that does not use filters.
606
607
608Finally, DUMB offers a myriad of functions for querying and adjusting
609module playback. Those beginning with "dumb_it_sd" operate on the
610DUMB_IT_SIGDATA struct, which represents the piece of music before it starts
611to play. Those beginning with "dumb_it_sr" operate on the DUMB_IT_SIGRENDERER
612struct, which represents a currently playing instance of the music. Note that
613duh_get_length(), described above, becomes meaningless after some of these
614functions are used.
615
616The method for getting a DUMB_IT_SIGRENDERER struct has already been given,
617but the function prototypes are repeated here for convenience:
618
619 DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp);
620 DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer);
621
622Getting a DUMB_IT_SIGDATA struct is simpler:
623
624 DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh);
625
626For a list of dumb_it_sd_*() and dumb_it_sr_*() functions, please see
627dumb.txt. These functions are new, and may not provide exactly what you need;
628if not, please let me know.
629
630
631**************************************************
632*** Embedding music files in Allegro datafiles ***
633**************************************************
634
635
636In this section it is assumed you are already reasonably familiar with how
637Allegro datafiles are used. If not, please refer to Allegro's documentation.
638At the time of writing, the documentation you need is off the beaten track,
639so to speak, in allegro/tools/grabber.txt.
640
641To add a piece of music to a datafile, you need to create an object of type
642"IT ", "XM ", "S3M " or "MOD " (note the spaces used as padding, although
643you do not need to type these into the grabber). Then grab the piece of music
644in. The grabber will treat it as a binary object. Save the datafile as usual.
645
646
647To use a piece of music you added to the datafile, follow these steps:
648
649
6501. Before loading the datafile, call one or more of these functions,
651 depending on which music format or formats you'd like to support:
652
653 dumb_register_dat_it(DUMB_DAT_IT);
654 dumb_register_dat_xm(DUMB_DAT_XM);
655 dumb_register_dat_s3m(DUMB_DAT_S3M);
656 dumb_register_dat_mod(DUMB_DAT_MOD);
657
658 Remember, do not call multiple functions unless you want to support
659 multiple formats. Calling more functions will add unused code to your
660 executable.
661
662 It is important that you make call these before loading the datafile,
663 since they tell Allegro how to load the respective files straight from
664 datafiles in the future. They will not help Allegro interpret any module
665 files that have already been loaded as binary objects (but if you really
666 need to interpret a module that has been loaded in this fashion, have a
667 look at dumbfile_open_memory() in dumb.txt).
668
669 If for whatever reason your music objects are identified by a different
670 type in the datafile, you can tell DUMB what that type is by changing the
671 parameter to the registration function above. Use Allegro's DAT_ID()
672 macro, e.g. DAT_ID('B','L','A','H'). This is not really recommended
673 though, since it would prevent a hypothetical grabber plug-in from being
674 able to play your music files. Use the above types if possible.
675
676
6772. Whenever you need a pointer to a DUH struct, simply use the 'dat' field.
678 Do this in the same way you would for a pointer to a BITMAP struct or
679 anything else. If it makes you feel more comfortable, you can extract the
680 pointer in advance:
681
682 DATAFILE *dat = load_datafile("smurf.dat");
683 if (!dat) abort(); /* There are much nicer ways of handling failure! */
684 DUH *myduh = (DUH *)dat[GAME_MUSIC].dat;
685
686 Note that the explicit (DUH *) cast is only necessary for C++, not for C.
687 However, it does no harm.
688
689 Be sure that you do NOT call unload_duh() for anything stored in the
690 datafile. These DUHs will be freed when you call unload_datafile(), and
691 freeing them twice is practically guaranteed to crash your program.
692
693
6943. If you only ever load music as part of a datafile, and you never load any
695 stand-alone music files, you do not need to register a file input system
696 for DUMB to use. If you followed the instructions for the first section
697 you will have one of these two lines in your program:
698
699 dumb_register_stdfiles();
700 dumb_register_packfiles();
701
702 You can safely delete this line - but only if you never load any
703 stand-alone music files. The debugging library will bale you out if you
704 delete it when you shouldn't; the optimised library won't.
705
706
707*************************************
708*** Rendering music into a buffer ***
709*************************************
710
711
712NOTE: much of the API formerly described in this section has been deprecated,
713 and you will need to alter your code. See deprec.txt for details. If
714 you are reading this section for the first time, you can ignore this
715 note.
716
717Rendering to a buffer is similar to playing using an AL_DUH_PLAYER. However,
718you must use a DUH_SIGRENDERER struct instead. Here are the functions:
719
720 DUH_SIGRENDERER *duh_start_sigrenderer
721 (DUH *duh, int sig, int n_channels, long pos);
722
723 int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer);
724 long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer);
725
726 long duh_sigrenderer_get_samples(DUH_SIGRENDERER *sigrenderer,
727 float volume, float delta, long size, sample_t **samples);
728
729 long duh_render(DUH_SIGRENDERER *sigrenderer,
730 int bits, int unsign, float volume, float delta, long size, void *sptr);
731
732 void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer);
733
734The parameters to duh_start_sigrenderer() have the same meanings as those to
735al_start_duh(). However, note that the volume is not set at this stage. You
736pass the desired volume each time you want to render a block. The 'sig'
737parameter should be set to 0 for now.
738
739Notice that there are two rendering functions. duh_sigrenderer_get_samples()
740will generate samples in the internal 32-bit format, with a normal range from
741-0x800000 to 0x7FFFFF and with each channel in a separate array; duh_render()
742will convert to 8 or 16 bits, signed or unsigned, with stereo samples
743interleaved, left first.
744
745When you call duh_render(), pass 8 or 16 for 'bits'. If you pass 8, 'sptr' is
746expected to be an array of chars. If you pass 16, 'sptr' is expected to be an
747array of shorts. Endianness therefore depends on the platform, and you should
748not try to interpret 16-bit wave data as an array of chars (unless you're
749writing highly system-specific code anyway). Because DUMB renders internally
750with 32 bits, there is no significant speed increase in rendering an 8-bit
751stream.
752
753If you are rendering in stereo, make sure your 'sptr' array is twice as big!
754
755If you set 'unsign' to a nonzero value, then the samples generated will be
756centred on 0x80 or 0x8000, suitably stored in an array of unsigned chars or
757unsigned shorts. If 'unsign' is zero, the samples will be centred on 0,
758suitably stored in an array of signed chars or signed shorts. Note that 8-bit
759WAV files are unsigned while 16-bit WAV files are signed. This convention was
760used by the SoundBlaster 16 when receiving samples to be sent to the
761speakers. If you wish to write 16-bit sample data to a WAV file, don't use
762fwrite(); instead, take the shorts one at a time, split them up into chars as
763follows, and write the chars to the file.
764
765 short sptr[n];
766 char lsb = (char)sptr[n];
767 char msb = (char)(sptr[n] >> 8);
768
769For a 16-bit WAV file, write the LSB (less significant byte) first.
770
771The following applies equally to duh_render() and
772duh_sigrenderer_get_samples(), except where otherwise stated.
773
774If you set 'delta' to 1.0f, the sound generated will be suitable for playback
775at 65536 Hz. Increasing 'delta' causes the wave to speed up, given a constant
776sampling rate for playback. Supposing you want to vary the playback sampling
777rate but keep the pitch constant, here's the equation for 'delta':
778
779 delta = 65536.0f / sampling_rate;
780
781'size' is the number of samples you want rendered. For duh_render(), they
782will be rendered into an array which you pass as 'sptr'. Note that stereo
783samples count as one; so if you set n_channels to 2, your array must contain
784(2 * size) elements.
785
786For duh_sigrenderer_get_samples() you will have to use the following
787functions:
788
789 sample_t **create_sample_buffer(int n_channels, long length);
790 void destroy_sample_buffer(sample_t **samples);
791
792 void dumb_silence(sample_t *samples, long length);
793
794create_sample_buffer() allocates the channels sequentially in memory, so the
795following technique is valid:
796
797 sample_t **samples = create_sample_buffer(n_channels, length);
798 dumb_silence(samples[0], n_channels * length);
799
800It is necessary to fill the buffer with silence like this because
801duh_sigrenderer_get_samples() mixes what it renders with the existing
802contents of the buffer.
803
804The return values from duh_render() and duh_sigrenderer_get_samples() tell
805you how many samples were actually generated. In most cases, this will be the
806same as the 'size' parameter. However, if you reach the end of the DUH (which
807will happen if you disable looping or freezing as described further up), this
808function will return less. When that happens, you can assume the stream has
809finished. In the case of duh_render(), the remainder of the array will not
810have been initialised, so you either have to initialise it yourself or avoid
811using it.
812
813If for whatever reason duh_start_sigrenderer() returns NULL, then
814duh_render() and duh_sigrenderer_get_samples() will generate exactly 0
815samples, duh_sigrenderer_get_n_channels() will return 0,
816duh_sigrenderer_get_position() will return -1, and duh_end_sigrenderer() will
817safely do nothing.
818
819
820*********************
821*** Miscellaneous ***
822*********************
823
824
825Please see dumb.txt for an API reference and for information on thread safety
826with DUMB. The API reference has been stripped down, since some functions and
827variables are subject to change. If something does not appear in dumb.txt,
828please do not use it.
829
830
831******************
832*** Conclusion ***
833******************
834
835
836If you have any difficulties, or if you use DUMB successfully, please don't
837hesitate to contact me (see below).
838
839Enjoy!
840
841
842Ben Davis
843entheh@users.sf.net
844IRC EFnet #dumb
845See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/modplug.txt b/apps/codecs/dumb/docs/modplug.txt
new file mode 100644
index 0000000000..a02ddd8bdd
--- /dev/null
+++ b/apps/codecs/dumb/docs/modplug.txt
@@ -0,0 +1,137 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * modplug.txt - Our official position regarding / / \ \
12 * compatibility with ModPlug | < / \_
13 * Tracker. | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21********************
22*** Introduction ***
23********************
24
25ModPlug Tracker is a very popular tracker for Windows. Its popularity is due
26to the intuitive interface and its many advanced features. The author has
27done a good job with this piece of software, but sadly in doing so he has
28desecrated the IT file format.
29
30I am not against ModPlug Tracker being used to write music modules. As
31already stated, it has some very advanced and convenient features; I use it
32myself. However, I believe its users should be aware of the entire situation
33before using it for any serious work.
34
35 ModPlug Tracker - http://www.modplug.com/
36
37
38*************************
39*** Incompatibilities ***
40*************************
41
42There are a few situations in which ModPlug Tracker misinterprets the
43original module formats. I shall list the five I am most aware of, from least
44to most annoying:
45
465. Create a multisample instrument, for example a piano. Play a low note.
47 Then go up the scale, but in the pattern data, make sure the instrument
48 column is blank; put in only the notes. Play this with ModPlug Tracker,
49 and play it with Impulse Tracker. Impulse Tracker changes sample as you go
50 up the scale; ModPlug Tracker does not.
51
524. Arpeggio and Retrigger Note effects behave badly when combined with
53 Portamento, which can appear in the volume column. While Retrigger Note
54 isn't too bad, Arpeggio sounds completely wrong. Try it and see what
55 happens. Then repeat the experiment in Impulse Tracker.
56
573. The filter algorithm is incorrect, in more ways than one. When Jeffrey Lim
58 programmed the low-pass resonant filters into Impulse Tracker, he used a
59 standard filter algorithm with a slight modification to achieve greater
60 resonance. ModPlug Tracker does not incorporate this modification.
61 Furthermore, ModPlug Tracker uses integer arithmetic with nowhere near
62 enough precision; the wave output is really poor in some cases. I don't
63 doubt it damages the acoustic properties of the filters in subtle ways.
64
652. When looping, ModPlug Tracker resets all variables. The original trackers
66 do not do this.
67
681. Worst of all, ModPlug Tracker has no regard for playback volume, and
69 generally has a much lower output level than the original trackers.
70
71Cases 3, 2 and 1 lead people to write IT files that play badly in the
72original trackers. If some of these problems could be fixed, I'd be all for
73it - but these problems have been reported to the author and he had no
74motivation to fix them. ModPlug Tracker has been around long enough that
75fixing 3, 2 and 1 would be detrimental to too many people's music.
76
77
78******************
79*** Extensions ***
80******************
81
82Worse than the incompatibilities are the extensions ModPlug Tracker makes,
83mostly to the IT format. DUMB currently supports one of these extensions,
84namely stereo samples, but supporting the others is not high on my list of
85priorities.
86
87Other extensions ModPlug Tracker has provided mostly take the form of extra
88effects. For instance, S98 and S99 can be used to enable or disable reverb. I
89believe the latest versions of ModPlug Tracker offer alternative types of
90filter, such as high-pass and band-pass. As soon as an IT file uses any of
91these features, it will play incorrectly with Impulse Tracker.
92
93By far the most evil extension provided by ModPlug Tracker is the effect
94plug-ins. These enable IT files to use VST effects. I recently downloaded an
95IT file that uses some effects from a collection named "DirectX Media Audio
96Effects". When can we expect these effects to be ported to Linux?
97
98
99******************
100*** Conclusion ***
101******************
102
103ModPlug Tracker is trying to be two things at once. It wants to be an editor
104for the existing formats, but at the same time it wants to be proprietary,
105with all its own features and extensions. Unfortunately it is succeeding;
106there are many IT files out there that only play right in ModPlug Tracker. In
107my opinion, ModPlug Tracker should have come out with its own file format, in
108which all these extensions would have found a home.
109
110If you are going to use ModPlug Tracker's extensions, I recommend you
111ultimately convert your music to a streamed format such as Ogg Vorbis. (If
112you were thinking of using MP3, then don't - consider using Ogg Vorbis
113instead.) If you release IT files that use ModPlug Tracker's extensions,
114please state prominently that the files are designed to be played with
115ModPlug Tracker. Finally, don't ask me to support ModPlug Tracker's
116extensions; ModPlug Tracker's playback code is available for use in your
117games, so use that instead.
118
119 Ogg Vorbis - http://www.vorbis.com/
120
121Despite all the above problems, don't forget that ModPlug Tracker does have a
122lot of very useful features for editing files. These include a function for
123removing unused patterns, samples and instruments, drag-and-drop sample and
124instrument ripping, drop-down menus for selecting the effects by name without
125having to memorise the codes or refer to help, and lots of other nice things.
126I do recommend it as an editor, provided you make sure you are aware of the
127situation and do not use ModPlug Tracker's extensions or incompatibilities
128inadvertently.
129
130Oh, and by the way, save your final version with Impulse Tracker. Then the
131samples will be compressed for you!
132
133
134Ben Davis
135entheh@users.sf.net
136IRC EFnet #dumb
137See readme.txt for details on using IRC.
diff --git a/apps/codecs/dumb/docs/ptr.txt b/apps/codecs/dumb/docs/ptr.txt
new file mode 100644
index 0000000000..0eb42ccf02
--- /dev/null
+++ b/apps/codecs/dumb/docs/ptr.txt
@@ -0,0 +1,129 @@
1/* _______ ____ __ ___ ___
2 * \ _ \ \ / \ / \ \ / / ' ' '
3 * | | \ \ | | || | \/ | . .
4 * | | | | | | || ||\ /| |
5 * | | | | | | || || \/ | | ' ' '
6 * | | | | | | || || | | . .
7 * | |_/ / \ \__// || | |
8 * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
9 * / \
10 * / . \
11 * ptr.txt - Pointer explanation. / / \ \
12 * | < / \_
13 * | \/ /\ /
14 * \_ / > /
15 * | \ / /
16 * | ' /
17 * \__/
18 */
19
20
21A pointer is a small variable (often the same size as an int BUT NOT ALWAYS)
22that holds the address of something in memory. You create a pointer by adding
23a * to a variable, as follows:
24
25 int x, *y;
26
27 x = 5;
28 y = &x;
29
30The & means 'address of', so &x gives us a pointer to x. We are storing it in
31y.
32
33 (*y)++;
34
35The * here means 'value at'. It's known as the 'dereferencing' operator. When
36written before a pointer, as it is here, it allows you to treat the value
37like a normal variable. In this case we are incrementing the value. If we
38look at x, we'll find that it now contains 6, not 5.
39
40 y++;
41
42Here we are incrementing the pointer itself. This is useful for traversing
43through an array, but in this particular example it is not much use.
44
45 *y++;
46
47Beware; this will increment the pointer, not the value stored there. It will
48return the value stored at the pointer (before incrementing the pointer), so
49you can use this in a bigger expression. This is why we needed brackets in
50the first example.
51
52Note that you will not need these three examples when working with DUMB; they
53are simply to help illustrate the idea of pointers.
54
55Also be aware that when defining pointers you attach the * to the variable,
56not to the type. The following example will create a pointer and an int, not
57two pointers:
58
59 int *a, b;
60
61That is why I believe it's a good idea to put a space before the * and not
62after it, although programmers are divided on this.
63
64 y = 0;
65 y = NULL;
66
67These two statements are equivalent. 0, or NULL, is a special value that is
68guaranteed to have a different value from any valid pointer. This is most
69often used to indicate that something doesn't point anywhere. DUMB's
70functions may return it on occasion. However, in simple usage of DUMB, you
71will not actually need to check for it.
72
73Some of DUMB's functions return pointers to structs. (A struct is an
74aggregration of other variables, such as ints, pointers, or other structs.
75You can generally treat a struct as a single unit.) Here's an example of such
76a function:
77
78 DUH *dumb_load_it(const char *filename);
79
80You do not know what the DUH struct actually contains; dumb.h and aldumb.h
81only give the compiler enough information to deal with pointers to them. DUMB
82will take charge of everything that happens inside a DUH struct.
83
84The above function will create a DUH struct for you. First it allocates
85the memory it needs, then it fills the struct with data, then it returns a
86pointer. This DUH struct will contain the data necessary to play an IT file.
87You can define a suitable variable and store the pointer in it as follows:
88
89 DUH *duh = dumb_load_it("music.it");
90
91Or this can be split up:
92
93 DUH *duh;
94 duh = dumb_load_it("music.it");
95
96In order to use this DUH struct later, you must pass its pointer to other
97functions. To pass the pointer to a function, simply write 'duh' for the
98appropriate parameter.
99
100When you've finished with a DUH struct (this applies equally to the other
101structs DUMB deals with), you must pass it to an appropriate function for
102freeing up the memory:
103
104 unload_duh(duh);
105
106After you've done this, the memory will no longer be allocated, and the
107pointer will have no meaning. You may wish to set it to NULL at this point
108for safety. Alternatively just be sure not to use the present value of the
109pointer any more. You can of course assign a new value to the pointer, e.g.
110by calling dumb_load_it() again.
111
112Note the following:
113
114 DUH *duh2 = duh;
115
116This only duplicates the pointer, not the DUH itself. You still only have one
117copy of the DUH. There is no way of duplicating a DUH, short of loading it
118twice. This is not a problem, because DUMB can play it 'twice at the same
119time' anyway.
120
121That should be all you need to know about pointers in order to use DUMB. If
122there's anything you feel should be explained better here, or anything else
123that should be added, please don't hesitate to let me know!
124
125
126Ben Davis
127entheh@users.sf.net
128IRC EFnet #dumb
129See readme.txt for details on using IRC.