3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
10 * By Shawn Hargreaves,
16 * This file written by George Foot.
18 * AWE32/EMU8000 driver for the MIDI player.
20 * See readme.txt for copyright information.
25 #error This file should only be used by the djgpp version of Allegro
37 /* Variables from awedata.c, containing the envelope data from synthgm.sf2 */
38 extern short int _awe_sf_defaults[];
39 extern int _awe_sf_num_presets;
40 extern short int _awe_sf_presets[];
41 extern short int _awe_sf_splits[];
42 extern short int _awe_sf_gens[];
43 extern int _awe_sf_sample_data[];
45 /* external interface to the AWE32 driver */
46 static int awe32_detect();
47 static int awe32_init(int voices);
48 static void awe32_exit();
49 static void awe32_key_on(int inst, int note, int bend, int vol, int pan);
50 static void awe32_key_off(int voice);
51 static void _awe32_do_note(int inst, int note, int bend, int vol, int pan);
52 static void awe32_set_volume (int voice, int vol);
53 static void awe32_set_pitch (int voice, int note, int bend);
54 static void translate_soundfont_into_something_useful();
55 static void destroy_useful_version_of_soundfont();
57 static struct midi_preset_t { /* struct to hold envelope data for each preset */
58 int num_splits; /* number of splits in this preset */
59 struct envparms_t **split; /* array of num_splits pointers to envelope data */
60 } *midi_preset; /* global variable to hold the data */
62 static struct envparms_t **voice_envelope; /* array of pointers pointing at the envelope playing on each voice */
63 static int *exclusive_class_info; /* exclusive class information */
65 static char awe32_desc[256] = "not initialised";
67 MIDI_DRIVER midi_awe32 = {
68 "AWE32/EMU8000", /* name */
69 awe32_desc, /* desc */
70 32, 0, 32, 32, -1, -1, /* voices, basevoice, max_voices, def_voices, xmin, xmax */
71 awe32_detect, /* detect */
72 awe32_init, /* init */
73 awe32_exit, /* exit */
74 NULL, /* mixer_volume */
76 _dummy_load_patches, /* load_patches */
77 _dummy_adjust_patches, /* adjust_patches */
78 awe32_key_on, /* key_on */
79 awe32_key_off, /* key_off */
80 awe32_set_volume, /* set_volume */
81 awe32_set_pitch, /* set_pitch */
82 _dummy_noop2, /* set_pan */
83 _dummy_noop2 /* set_vibrato */
89 * Triggers the specified voice. The instrument is specified as a GM
90 * patch number, pitch as a midi note number, and volume from 0-127.
91 * The bend parameter is _not_ expressed as a midi pitch bend value.
92 * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp).
93 * Drum sounds are indicated by passing an instrument number greater than
94 * 128, in which case the sound is GM percussion key #(inst-128).
96 static void awe32_key_on(int inst, int note, int bend, int vol, int pan) {
97 if (inst > 127) { /* drum sound? */
98 _awe32_do_note (128,inst-128,bend,vol,pan);
99 } else { /* regular instrument */
100 _awe32_do_note (inst,note,bend,vol,pan);
103 static END_OF_FUNCTION(awe32_key_on);
108 * Actually plays the note as described above; the above function just remaps
111 static void _awe32_do_note(int inst, int note, int bend, int vol, int pan) {
119 /* EMU8000 pan is back-to-front and twice the scale */
121 if (pan>0xff) pan = 0xff;
122 if (pan<0x00) pan = 0x00;
124 for (i=0;i<midi_preset[inst].num_splits;i++) {
125 /* envelope for this split */
126 env=midi_preset[inst].split[i];
128 /* should we play this split? */
129 if ((note>=env->minkey)&&(note<=env->maxkey)&&( vol>=env->minvel)&&( vol<=env->maxvel)) {
131 /* get a voice (any voice) to play it on */
132 voice = _midi_allocate_voice (-1,-1);
134 /* did we get one? */
137 /* set the current envelope for this voice */
138 voice_envelope[voice]=env;
140 /* set pitch and velocity */
141 key = note*0x1000+bend;
144 /* override key and velocity if envelope says so */
145 if ((env->key>=0)&&(env->key<=127)) key=env->key*0x1000;
146 if ((env->vel>=0)&&(env->vel<=127)) vel=env->vel;
148 /* check key and velocity numbers are within range */
149 if (key>0x7ffff) key=0x7ffff;
151 if (vel>127) vel=127;
154 /* add one-off information to the envelope (these have no side-effects on the other voices using this envelope) */
155 env->ip=env->ipbase+(env->ipscale*key)/1200;
157 /* remap MIDI velocity to attenuation */
159 atten = env->atten + (-20/0.375*log(vel/127.0));
162 if (atten<0x00) atten = 0x00;
163 if (atten>0xff) atten = 0xff;
165 /* update it in the envelope */
166 env->ifatn=env->filter+atten;
168 /* modify pan with envelope's built-in pan */
170 pan_pos = (pan*env->pan)/0x80;
172 pan_pos = env->pan + (pan-0x80)*(256-env->pan)/0x80;
174 if (pan_pos<0x00) pan_pos=0x00;
175 if (pan_pos>0xff) pan_pos=0xff;
177 /* update pan in the envelope */
178 env->psst = (pan_pos<<24) + env->loopst;
180 /* test exclusive class */
181 exclusive_class_info[voice] = (inst << 8) + env->exc;
185 for (chan = 0; chan < 32; chan++)
186 if ((chan != voice) && (exclusive_class_info[chan] == exclusive_class_info[voice]))
187 emu8k_terminatesound (chan);
190 /* start the note playing */
191 emu8k_startsound(voice,env);
197 static END_OF_FUNCTION(_awe32_do_note);
202 * Modulation routines
204 static void awe32_set_volume (int voice, int vol) {
206 struct envparms_t *env;
208 /* get envelope in use on this voice */
209 env = voice_envelope[voice];
211 /* allow envelope to override new volume */
212 if ((env->vel>=0)&&(env->vel<=127)) vol=env->vel;
214 /* check velocity number is within range */
215 if (vol>127) vol=127;
218 /* remap MIDI velocity to attenuation */
220 atten = env->atten + (-20/0.375*log(vol/127.0));
223 if (atten<0x00) atten = 0x00;
224 if (atten>0xff) atten = 0xff;
226 emu8k_modulate_atten(voice,atten);
228 static END_OF_FUNCTION(awe32_set_volume);
232 static void awe32_set_pitch (int voice, int note, int bend) {
233 struct envparms_t *env;
236 /* get envelope in use on this voice */
237 env = voice_envelope[voice];
239 key = note*0x1000+bend;
241 /* override key if envelope says so */
242 if ((env->key>=0)&&(env->key<=127)) key=env->key*0x1000;
244 /* check key number is within range */
245 if (key>0x7ffff) key=0x7ffff;
248 ip=env->ipbase+(env->ipscale*key)/1200;
250 emu8k_modulate_ip(voice,ip);
252 static END_OF_FUNCTION (awe32_set_pitch);
257 * Hey, guess what this does :-)
259 static void awe32_key_off(int voice) {
260 emu8k_releasesound (voice,voice_envelope[voice]);
262 static END_OF_FUNCTION(awe32_key_off);
267 * AWE32/EMU8000 detection routine.
269 static int awe32_detect() {
270 if (emu8k_detect()) {
271 sprintf (awe32_desc,"SB AWE32/compatible on port 0x%04x",_emu8k_baseport);
274 sprintf(allegro_error, "AWE32 not detected");
282 * Locks required memory blocks
284 static void awe32_lockmem() {
287 LOCK_FUNCTION(awe32_key_on);
288 LOCK_FUNCTION(awe32_key_off);
289 LOCK_FUNCTION(_awe32_do_note);
290 LOCK_FUNCTION(awe32_set_volume);
291 LOCK_FUNCTION(awe32_set_pitch);
294 /* Most data is locked on allocation */
295 LOCK_VARIABLE(midi_preset);
296 LOCK_VARIABLE(voice_envelope);
297 LOCK_VARIABLE(exclusive_class_info);
298 LOCK_VARIABLE(midi_awe32);
300 /* Stuff in emu8k.c */
308 * Setup the AWE32/EMU8000 driver.
310 static int awe32_init(int voices) {
314 translate_soundfont_into_something_useful();
315 voice_envelope = (struct envparms_t **) _lock_malloc (32 * sizeof(struct envparms_t *));
316 exclusive_class_info = (int *) _lock_malloc (32 * sizeof (int));
319 for (chan = 0; chan < 32; chan++) {
320 voice_envelope[chan] = NULL;
321 exclusive_class_info[chan] = 0;
330 * Cleanup when we are finished.
332 static void awe32_exit() {
334 for (i=0;i<_emu8k_numchannels;i++) emu8k_terminatesound(i);
335 destroy_useful_version_of_soundfont();
336 free (voice_envelope);
337 free (exclusive_class_info);
342 /* translate_soundfont_into_something_useful:
343 * Like it says, translate the soundfont data into something we can use
344 * when playing notes.
346 static void translate_soundfont_into_something_useful() {
348 struct midi_preset_t *thing_to_write=NULL;
349 generators_t temp_gens;
350 int global_split=0,global_weirdo=0,num_weirdos;
352 midi_preset = (struct midi_preset_t *)_lock_malloc(129*sizeof(struct midi_preset_t));
353 for (p=0;p<_awe_sf_num_presets;p++) {
354 if (_awe_sf_presets[p*3+1]==0) {
355 thing_to_write = &midi_preset[_awe_sf_presets[p*3+0]];
356 } else if (_awe_sf_presets[p*3+1]==128) {
357 thing_to_write = &midi_preset[128];
359 thing_to_write = NULL;
361 if (thing_to_write) {
362 thing_to_write->num_splits=_awe_sf_presets[p*3+2];
363 thing_to_write->split=(struct envparms_t **)_lock_malloc(thing_to_write->num_splits*sizeof(struct envparms_t *));
364 for (s=0;s<thing_to_write->num_splits;s++) {
365 for (gen=0;gen<SOUNDFONT_NUM_GENERATORS-4;gen++) temp_gens[gen] = _awe_sf_defaults[gen];
366 num_weirdos = _awe_sf_splits[global_split];
367 for (weirdo=global_weirdo;weirdo<global_weirdo+num_weirdos;weirdo++) temp_gens[_awe_sf_gens[weirdo*2]] = _awe_sf_gens[weirdo*2+1];
368 global_weirdo+=num_weirdos;
369 for (gen=0;gen<4;gen++) temp_gens[gfgen_startAddrs+gen] = _awe_sf_sample_data[global_split*4+gen];
371 thing_to_write->split[s]=emu8k_createenvelope(temp_gens);
374 strcpy(allegro_error,"AWE32 driver: had trouble with the embedded data");
381 /* destroy_useful_version_of_soundfont:
382 * Destroys the data created by the above function
384 static void destroy_useful_version_of_soundfont() {
387 if (midi_preset[p].num_splits>0) {
388 for (s=0;s<midi_preset[p].num_splits;s++) emu8k_destroyenvelope(midi_preset[p].split[s]);
389 free(midi_preset[p].split);
397 * Allocates a locked memory block
399 void *_lock_malloc (size_t size) {
400 void *ret = malloc (size);
401 if (!ret) return NULL;
402 if (_go32_dpmi_lock_data (ret, size)) {