]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/allg_snd/sound/drv/gus.c
This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / arch / dos / allg_snd / sound / drv / gus.c
1 /*         ______   ___    ___ 
2  *        /\  _  \ /\_ \  /\_ \ 
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *
12  *       Stub GUS driver. This is just a placeholder: the real code isn't
13  *       written yet.
14  */
15
16
17 #ifndef DJGPP
18 #error This file should only be used by the djgpp version of Allegro
19 #endif
20
21 #include <stdlib.h>
22 #include <stdio.h>
23
24 #include "allegro.h"
25 #include "internal.h"
26
27
28 static char gus_desc[80] = "not initialised";
29
30 static int gus_detect();
31
32 static int gus_digi_init();
33 static void gus_digi_exit();
34
35
36 DIGI_DRIVER digi_gus =        /* GUS driver for playing digital sfx */
37 {
38    "Gravis Ultrasound", 
39    gus_desc,
40    0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX,
41    gus_detect,
42    gus_digi_init,
43    gus_digi_exit,
44    _dummy_mixer_volume,
45    _dummy_init_voice,
46    _dummy_noop1,
47    _dummy_noop1,
48    _dummy_noop1,
49    _dummy_noop2,
50    _dummy_get_position,
51    _dummy_noop2,
52    _dummy_get,
53    _dummy_noop2,
54    _dummy_noop3,
55    _dummy_noop1,
56    _dummy_get,
57    _dummy_noop2,
58    _dummy_noop3,
59    _dummy_noop1,
60    _dummy_get,
61    _dummy_noop2,
62    _dummy_noop3,
63    _dummy_noop1,
64    _dummy_noop3,
65    _dummy_noop3,
66    _dummy_noop3
67 };
68
69
70 static int gus_midi_init();
71 static void gus_midi_exit();
72 static int gus_load_patches(char *patches, char *drums);
73 static void gus_key_on(int inst, int note, int bend, int vol, int pan);
74 static void gus_key_off(int voice);
75 static void gus_set_volume(int voice, int vol);
76 static void gus_set_pitch(int voice, int note, int bend);
77
78
79 MIDI_DRIVER midi_gus =        /* GUS driver for playing MIDI music */
80 {
81    "Gravis Ultrasound", 
82    gus_desc,
83    0, 0, -1, 24, -1, -1,
84    gus_detect,
85    gus_midi_init,
86    gus_midi_exit,
87    NULL,
88    NULL,
89    gus_load_patches,
90    _dummy_adjust_patches,
91    gus_key_on,
92    gus_key_off,
93    gus_set_volume,
94    gus_set_pitch,
95    _dummy_noop2,
96    _dummy_noop2
97 };
98
99
100 static void gus_lock_data();
101
102
103
104 /* gus_detect:
105  *  GUS detection routine. Returns TRUE if a GUS exists, otherwise FALSE.
106  *  It shouldn't do anything that drastically alters the state of the
107  *  card, since it is likely to get called more than once.
108  */
109 static int gus_detect()
110 {
111    strcpy(allegro_error, "GUS driver not written yet");
112
113    /* if (no GUS present) */
114       return FALSE;
115
116    sprintf(gus_desc, "Some info about the GUS hardware");
117    return TRUE;
118 }
119
120
121
122 /* gus_digi_init:
123  *  Called once at startup to initialise the digital sample playing code.
124  */
125 static int gus_digi_init()
126 {
127    gus_lock_data();
128
129 #if GOT_SOME_GUS_CODE_TO_PUT_IN_HERE
130    /* Allocate conventional memory buffers for the DMA transfer. Pass the
131     * size of the buffer in bytes, an int pointer which will be set to the
132     * protected mode selector to free the buffer with, and a pointer to a
133     * long which will be set to the linear address of the buffer in 
134     * conventional memory.
135     */
136    if (_dma_allocate_mem(buffer_size, &(int)selector, &(long)address) != 0)
137       return -1;
138
139    /* Initialise the sample mixing module. Pass the size of each buffer
140     * (in samples, not bytes: if you pass 1024 for this parameter you would
141     * need a _dma_allocate_mem of 1024 bytes if you are using 8 bit data, but 
142     * of 2048 if in 16 bit mode. Don't double the size for stereo modes 
143     * though: in an 8 bit stereo mode passing 1024 will still cause it to
144     * mix 1024 bytes into each buffer, just the buffer will only last for
145     * half as long...). Also pass the sample frequency the GUS is running at,
146     * and whether you want stereo and/or 16 bit data.
147     */
148    if (_mixer_init(buffer_size, gus_frequency, stereo, 16bit) != 0)
149       return -1;
150
151    /*
152    Apart from those calls, do whatever GUS-type stuff you need to do, set
153    the dma transfer going (_dma_start(channel, addr, size, auto_init_flag)),
154    and whenever a buffer needs filling with some more samples, call
155    _mix_some_samples(linear_address_of_buffer_in_conventional_memory);
156    btw. the 16 bit sample mixing and 16 bit DMA transfer modes are not
157    tested, since I only have an 8 bit SB. If they don't work, it might well
158    be my fault :-)
159    */
160 #endif
161
162    return 0;
163 }
164
165
166
167 /* gus_digi_exit:
168  *  gus driver cleanup routine, removes ints, stops dma, frees buffers, etc.
169  */
170 static void gus_digi_exit()
171 {
172 #if GOT_SOME_GUS_CODE_TO_PUT_IN_HERE
173
174    _dma_stop(whatever_dma_channel_you_are_using);
175    __dpmi_free_dos_memory(the selector returned by _dma_allocate_mem());
176    _mixer_exit();
177
178    etc.
179
180 #endif
181 }
182
183
184
185 /* gus_midi_init:
186  *  Called once at startup to setup the GUS MIDI driver. 
187  */
188 static int gus_midi_init()
189 {
190    gus_lock_data();
191
192    /* etc */
193
194    return 0;
195 }
196
197
198
199 /* gus_midi_exit:
200  *  Cleanup the MIDI driver. I ought to have turned off all the active
201  *  voices by the time this gets called, but it wouldn't hurt to reset
202  *  them all anyway.
203  */
204 static void gus_midi_exit()
205 {
206 }
207
208
209
210 /* gus_load_patches:
211  *  Called before starting to play a MIDI file, to load all the patches it
212  *  uses into GUS ram. No MIDI voices will be active when this is called,
213  *  so you are free to unload whatever old data you want. Patches points
214  *  to an array of 128 flags indicating which GM sounds are used in the
215  *  piece, and drums to an array of 128 flags indicating which drum sounds
216  *  are used (the GM standard only defines drum sounds 35 (base drum) to
217  *  81 (open triangle), so flags outside that range are guarranteed to be
218  *  zero). Should return 0 for success, -1 on failure.
219  *
220  *  What should we do if there isn't enough GUS ram to load all the samples?
221  *  Return an error code and not play the midi file? Or replace some patches
222  *  with others? And if so, should this routine do those replacements, or
223  *  should you just return an error code to me, and me call you again with
224  *  a reduced list of requirements? If we are going to do patch replacements,
225  *  it would seem sensible to do it at a higher level than the GUS driver,
226  *  so at a later date any other wavetable drivers could use the same code.
227  *  What do you think?
228  */
229 static int gus_load_patches(char *patches, char *drums)
230 {
231    return 0;
232 }
233
234 static END_OF_FUNCTION(gus_load_patches);
235
236
237
238 /* gus_key_on:
239  *  Triggers the specified MIDI voice. The instrument is specified as a 
240  *  GM patch number. Drums are indicated by passing an instrument greater 
241  *  than 128, in which case you should trigger the GM percussion sound 
242  *  normally mapped to drum key (inst-128). Drum sounds can ignore the 
243  *  pitch, bend, and pan parameters, but should respond to volume. The 
244  *  pitch is a midi note number (60=middle C, I think...). Pan and 
245  *  volume are from 0 (left/min) to 127 (right/max). The bend isn't a midi 
246  *  pitch bend value: it ranges from 0 (normal pitch) to 0xFFF (just a 
247  *  fraction flatter than a semitone up).
248  */
249 static void gus_key_on(int inst, int note, int bend, int vol, int pan)
250 {
251    int voice = _midi_allocate_voice(-1, -1);
252    if (voice < 0)
253       return;
254
255    /* after you set the sample to play and trigger the note, this is pretty 
256     * much equivelant to:
257     */
258    gus_set_pitch(voice, note, bend);
259    gus_set_volume(voice, vol);
260 }
261
262 static END_OF_FUNCTION(gus_key_on);
263
264
265
266 /* gus_key_off:
267  *  Hey, guess what this does :-)
268  */
269 static void gus_key_off(int voice)
270 {
271    /* do something */
272 }
273
274 static END_OF_FUNCTION(gus_key_off);
275
276
277
278 /* gus_set_volume:
279  *  Alters the volume of the specified voice (vol range 0-127). Should only
280  *  ever be called while the voice is playing...
281  */
282 static void gus_set_volume(int voice, int vol)
283 {
284    /* do something */
285 }
286
287 static END_OF_FUNCTION(gus_set_volume);
288
289
290
291 /* gus_set_pitch:
292  *  Alters the pitch of the specified voice. Should only be called while
293  *  the voice is playing...
294  */
295 static void gus_set_pitch(int voice, int note, int bend)
296 {
297    /* do something */
298 }
299
300 static END_OF_FUNCTION(gus_set_pitch);
301
302
303
304 /*
305  *  Locks all the memory touched by parts of the GUS code that are executed
306  *  in an interrupt context.
307  */
308 static void gus_lock_data()
309 {
310    LOCK_VARIABLE(digi_gus);
311    LOCK_VARIABLE(midi_gus);
312    LOCK_FUNCTION(gus_load_patches);
313    LOCK_FUNCTION(gus_key_on);
314    LOCK_FUNCTION(gus_key_off);
315    LOCK_FUNCTION(gus_set_volume);
316    LOCK_FUNCTION(gus_set_pitch);
317 }
318