summaryrefslogtreecommitdiff
path: root/apps/codecs/dumb/docs/howto.txt
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/dumb/docs/howto.txt')
-rw-r--r--apps/codecs/dumb/docs/howto.txt845
1 files changed, 0 insertions, 845 deletions
diff --git a/apps/codecs/dumb/docs/howto.txt b/apps/codecs/dumb/docs/howto.txt
deleted file mode 100644
index 0e7057da2c..0000000000
--- a/apps/codecs/dumb/docs/howto.txt
+++ /dev/null
@@ -1,845 +0,0 @@
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.