3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
10 * By Shawn Hargreaves,
16 * Digitized sample driver for the MIDI player.
18 * Based on code by Tom Novelli.
20 * See readme.txt for copyright information.
37 /* external interface to the Digmid driver */
38 static int digmid_detect();
39 static int digmid_init(int voices);
40 static void digmid_exit();
41 static int digmid_load_patches(char *patches, char *drums);
42 static void digmid_key_on(int inst, int note, int bend, int vol, int pan);
43 static void digmid_key_off(int voice);
44 static void digmid_set_volume(int voice, int vol);
45 static void digmid_set_pitch(int voice, int note, int bend);
48 MIDI_DRIVER midi_digmid =
51 "Software wavetable synth",
59 _dummy_adjust_patches,
72 typedef struct PATCH_EXTRA /* additional data for a Gravis PATCH */
87 typedef struct PATCH /* Gravis PATCH structure */
89 int samples; /* number of samples in this instrument */
90 SAMPLE *sample[MAX_LAYERS]; /* the waveform data */
91 PATCH_EXTRA *extra[MAX_LAYERS]; /* additional waveform information */
92 int master_vol; /* overall volume level */
97 static PATCH *patch[256];
100 /* frequency table (generated by digmid_init) */
101 static float ftbl[130];
104 /* stored information about active voices */
105 typedef struct DIGMID_VOICE
114 static DIGMID_VOICE digmid_voice[MIDI_VOICES];
119 * Frees a PATCH struct and all samples it contains.
121 static void destroy_patch(PATCH *pat)
126 for (i=0; i < pat->samples; i++) {
127 destroy_sample(pat->sample[i]);
129 _unlock_dpmi_data(pat->extra[i], sizeof(PATCH_EXTRA));
133 _unlock_dpmi_data(pat, sizeof(PATCH));
141 * Reads a GUS format patch file from disk.
143 static PATCH *load_patch(PACKFILE *f, int drum)
155 pack_fread(buf, 22, f); /* ID tag */
156 if (memcmp(buf, "GF1PATCH110\0", 12) || memcmp(buf+12, "ID#000002\0", 10))
159 p = malloc(sizeof(PATCH));
165 pack_fread(buf, 65, f); /* description */
166 p->master_vol = pack_igetw(f); /* volume */
168 pack_fread(buf, 109, f); /* skip */
170 p->samples = pack_getc(f); /* number of samples */
171 pack_fread(buf, 40, f); /* skip */
173 if (p->samples > MAX_LAYERS)
174 p->samples = MAX_LAYERS;
176 for (i=0; i<p->samples; i++) { /* for each sample... */
177 p->sample[i] = malloc(sizeof(SAMPLE));
185 p->extra[i] = malloc(sizeof(PATCH_EXTRA));
194 pack_fread(buf, 8, f); /* layer name */
196 p->sample[i]->len = pack_igetl(f); /* sample length */
197 p->sample[i]->loop_start = pack_igetl(f); /* loop start */
198 p->sample[i]->loop_end = pack_igetl(f); /* loop end */
199 p->sample[i]->freq = pack_igetw(f); /* sample frequency */
201 p->extra[i]->low_note = pack_igetl(f); /* key min */
202 p->extra[i]->high_note = pack_igetl(f); /* key max */
203 p->extra[i]->base_note = pack_igetl(f); /* base key */
204 trashtmp=pack_igetw(f); /* skip finetune */
206 p->extra[i]->pan = pack_getc(f) * 255/15; /* pan position */
208 for (j=0; j<6; j++) /* envelope rate */
209 env_rate[j] = pack_getc(f);
211 for (j=0; j<6; j++) /* envelope value */
212 env_offset[j] = pack_getc(f);
214 pack_fread(buf, 6, f); /* skip trem and vib */
216 mode = pack_getc(f); /* sample flags */
218 p->sample[i]->bits = (mode & 1) ? 16 : 8; /* how many bits? */
220 p->extra[i]->play_mode = 0; /* sort out loop flags */
223 p->extra[i]->play_mode |= PLAYMODE_LOOP;
226 p->extra[i]->play_mode |= (PLAYMODE_BIDIR | PLAYMODE_LOOP);
229 p->extra[i]->play_mode |= (PLAYMODE_BACKWARD | PLAYMODE_LOOP);
231 /* convert envelope rates (GUS uses a 2.6 floating point format) */
232 for (j=0; j<6; j++) {
233 static int vexp[4] = { 1, 8, 64, 512 };
234 int e = (env_rate[j] >> 6);
235 int m = (env_rate[j] & 0x3F);
236 env_rate[j] = ((65536 * vexp[e] / ((m) ? m : 1)) >> 12);
239 if ((mode & 32) && (!drum)) {
240 /* sustained volume envelope */
241 p->extra[i]->sustain_level = env_offset[2];
242 p->extra[i]->decay_time = 0;
244 diff = env_offset[0];
245 p->extra[i]->decay_time += env_rate[0] * diff / 256;
247 diff = ABS(env_offset[1] - env_offset[0]);
248 p->extra[i]->decay_time += env_rate[1] * diff / 256;
250 diff = ABS(env_offset[2] - env_offset[1]);
251 p->extra[i]->decay_time += env_rate[2] * diff / 256;
256 /* one-shot volume envelope */
257 p->extra[i]->decay_time = 0;
258 p->extra[i]->sustain_level = 0;
260 for (j=0; j<6; j++) {
261 diff = ABS(env_offset[j] - ((j) ? env_offset[j-1] : 0));
262 p->extra[i]->decay_time += env_rate[j] * diff / 256;
263 if (env_offset[j] < 16) {
270 /* measure release time */
271 p->extra[i]->release_time = 0;
274 diff = ABS(env_offset[j] - env_offset[j-1]);
275 p->extra[i]->release_time += env_rate[j] * diff / 256;
276 if (env_offset[j] < 16)
281 /* clamp very large/small sustain levels to zero or maximum */
282 if (p->extra[i]->sustain_level < 16)
283 p->extra[i]->sustain_level = 0;
284 else if (p->extra[i]->sustain_level > 192)
285 p->extra[i]->sustain_level = 255;
287 if (p->extra[i]->release_time < 10)
288 p->extra[i]->release_time = 0;
290 if ((p->extra[i]->sustain_level == 0) &&
291 (p->extra[i]->decay_time == 0)) {
292 p->extra[i]->sustain_level = 255;
293 p->extra[i]->play_mode &= ~PLAYMODE_LOOP;
296 p->extra[i]->scale_freq = pack_igetw(f); /* scale values */
297 p->extra[i]->scale_factor = pack_igetw(f);
299 pack_fread(buf, 36, f); /* skip reserved */
301 if (p->sample[i]->bits == 16) { /* adjust 16 bit loops */
302 odd_len = (p->sample[i]->len & 1);
303 p->sample[i]->len /= 2;
304 p->sample[i]->loop_start /= 2;
305 p->sample[i]->loop_end /= 2;
310 p->sample[i]->priority = 255; /* set some defaults */
311 p->sample[i]->param = -1;
313 p->sample[i]->data = malloc(p->sample[i]->len);
314 if (!p->sample[i]->data) {
323 if (p->sample[i]->bits == 8) {
324 /* read 8 bit sample data */
325 pack_fread(p->sample[i]->data, p->sample[i]->len, f);
327 /* signed data - convert to unsigned */
328 for (j=0; j<(int)p->sample[i]->len; j++)
329 ((unsigned char *)p->sample[i]->data)[j] ^= 0x80;
333 /* reduce 16 bits to 8 bit waveform */
334 for (j=0; j < (int)p->sample[i]->len; j++) {
335 ((unsigned char *)p->sample[i]->data)[j] = pack_igetw(f) >> 8;
338 /* signed data - convert to unsigned */
339 for (j=0; j<(int)p->sample[i]->len; j++)
340 ((unsigned char *)p->sample[i]->data)[j] ^= 0x80;
342 p->sample[i]->bits = 8;
350 /* lock the data into physical memory */
352 _go32_dpmi_lock_data(p, sizeof(PATCH));
354 for (i=0; i<p->samples; i++) {
355 lock_sample(p->sample[i]);
356 _go32_dpmi_lock_data(p->extra[i], sizeof(PATCH_EXTRA));
365 /* try_patch_location:
366 * Looks for a GUS patch set in the specified location, storing the dir
367 * and config file name if found.
369 static int try_patch_location(char *where, char *dir, char *file)
371 /* could it be a direct .cfg file reference? */
372 if (stricmp(get_extension(where), "cfg") == 0) {
373 if (!file_exists(where, FA_RDONLY | FA_ARCH, NULL))
376 *get_filename(dir) = 0;
377 strcpy(file, get_filename(where));
381 /* could it be a direct .dat file reference? */
382 if (stricmp(get_extension(where), "dat") == 0) {
384 strcat(dir, "#default_cfg");
385 if (!file_exists(dir, FA_RDONLY | FA_ARCH, NULL))
389 strcpy(file, "default_cfg");
393 /* could it be a directory containing default.cfg? */
396 strcat(dir, "default.cfg");
397 if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) {
400 strcpy(file, "default.cfg");
404 /* could it be a directory containing patches.dat? */
407 strcat(dir, "patches.dat#default_cfg");
408 if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) {
411 strcat(dir, "patches.dat#");
412 strcpy(file, "default_cfg");
416 /* could it be the root directory of midi/default.cfg? */
419 strcat(dir, "midi/default.cfg");
420 if (file_exists(dir, FA_RDONLY | FA_ARCH, NULL)) {
423 strcat(dir, "midi/");
424 strcpy(file, "default.cfg");
433 /* _digmid_find_patches:
434 * Tries to locate the GUS patch set directory and index file (default.cfg).
436 int _digmid_find_patches(char *dir, char *file)
438 char *name = get_config_string("sound", "patches", NULL);
441 /* look where the config file says */
442 if ((name) && (*name))
443 return try_patch_location(name, dir, file);
445 /* look in the same directory as the program */
446 strcpy(path, __crt0_argv[0]);
447 *get_filename(path) = 0;
449 if (try_patch_location(path, dir, file))
452 /* try the ALLEGRO environment variable */
453 s = getenv("ALLEGRO");
457 if (try_patch_location(path, dir, file))
461 /* try the ULTRASND environment variable */
462 s = getenv("ULTRASND");
466 if (try_patch_location(path, dir, file))
476 * Splits a string into component parts, storing them in the argv pointers.
477 * Returns the number of components.
479 static int parse_string(char *buf, char *argv[])
483 while ((*buf) && (c<16)) {
484 while ((*buf == ' ') || (*buf == '\t') || (*buf == '='))
493 while ((*buf) && (*buf != ' ') && (*buf != '\t') && (*buf != '='))
507 /* digmid_load_patches:
508 * Reads the patches that are required by a particular song.
510 static int digmid_load_patches(char *patches, char *drums)
513 char dir[256], file[256], buf[256], filename[256];
517 int patchnum, flag_num;
518 int drum_mode = FALSE;
519 int override_mode = FALSE;
526 if (!_digmid_find_patches(dir, file))
529 for (i=0; i<256; i++)
534 f = pack_fopen(buf, F_READ);
538 while (pack_fgets(buf, 255, f) != 0) {
539 argc = parse_string(buf, argv);
542 /* is first word all digits? */
544 for (i=0; i<(int)strlen(argv[0]); i++) {
545 if ((!isdigit(argv[0][i])) && (argv[0][i] != '-')) {
551 if ((flag_num) && (argc >= 2)) {
552 if (stricmp(argv[1], "begin_multipatch") == 0) {
553 /* start the block of percussion instruments */
554 drum_start = atoi(argv[0])-1;
557 else if (stricmp(argv[1], "override_patch") == 0) {
558 /* ignore patch overrides */
559 override_mode = TRUE;
561 else if (!override_mode) {
562 /* must be a patch number */
563 patchnum = atoi(argv[0]);
568 if ((patchnum >= 0) && (patchnum < 128) &&
569 (((drum_mode) && (drums[patchnum])) ||
570 ((!drum_mode) && (patches[patchnum])))) {
573 patchnum += drum_start;
575 if (!patch[patchnum]) {
576 /* need to load this sample */
577 strncpy(todo[patchnum], argv[1], 15);
578 todo[patchnum][15] = 0;
584 /* handle other keywords */
585 if (stricmp(argv[0], "end_multipatch") == 0) {
587 override_mode = FALSE;
596 if ((dir[0]) && (dir[strlen(dir)-1] == '#')) {
597 /* read from a datafile */
598 dir[strlen(dir)-1] = 0;
599 f = pack_fopen(dir, F_READ_PACKED);
603 type = pack_mgetl(f);
604 if (type != DAT_MAGIC) {
613 /* scan through the file */
614 while (!pack_feof(f)) {
615 type = pack_mgetl(f);
617 if (type == DAT_PROPERTY) {
618 type = pack_mgetl(f);
619 size = pack_mgetl(f);
620 if (type == DAT_ID('N','A','M','E')) {
621 /* store name property */
622 pack_fread(filename, size, f);
626 /* skip other properties */
630 else if (type == DAT_PATCH) {
631 /* do we want this patch? */
632 for (i=0; i<256; i++)
633 if ((todo[i][0]) && (stricmp(filename, todo[i]) == 0))
637 /* load this patch */
638 f = pack_fopen_chunk(f, FALSE);
639 patch[i] = load_patch(f, (i >= 128));
640 f = pack_fclose_chunk(f);
641 for (j=i+1; j<256; j++) {
642 /* share multiple copies of the instrument */
643 if (stricmp(todo[i], todo[j]) == 0) {
651 /* skip unwanted patch */
652 size = pack_mgetl(f);
653 pack_fseek(f, size+4);
657 /* skip unwanted object */
658 size = pack_mgetl(f);
659 pack_fseek(f, size+4);
666 /* read from regular disk files */
667 for (i=0; i<256; i++) {
669 strcpy(filename, dir);
670 strcat(filename, todo[i]);
671 if (*get_extension(filename) == 0)
672 strcat(filename, ".pat");
673 f = pack_fopen(filename, F_READ);
675 patch[i] = load_patch(f, (i >= 128));
679 for (j=i+1; j<256; j++) {
680 /* share multiple copies of the instrument */
681 if (stricmp(todo[i], todo[j]) == 0) {
696 * Helper for converting note numbers to sample frequencies.
698 static inline int digmid_freq(int inst, SAMPLE *s, PATCH_EXTRA *e, int note, int bend)
701 float sfreq = s->freq;
702 float base_note = e->base_note;
705 /* drums use a fixed frequency */
706 freq = ftbl[inst-128] * sfreq / base_note;
709 /* calculate frequency */
710 f1 = ftbl[note] * sfreq / base_note;
711 f2 = ftbl[note+1] * sfreq / base_note;
713 /* quick pitch bend method - ~.035% error - acceptable? */
714 freq = ((f1*(float)(4096-bend)) + (f2*(float)bend)) / 4096.0;
717 /* frequency scaling */
718 if (e->scale_factor != 1024) {
719 f1 = sfreq * e->scale_freq / 60;
721 freq = (freq * e->scale_factor) / 1024;
725 /* lower by an octave if we are going to overflow */
726 while (freq >= (1<<19)-1)
729 return (int)(freq+0.5);
735 * Helper for activating a specific sample layer.
737 static inline void digmid_trigger(int inst, int snum, int note, int bend, int vol, int pan)
744 voice = _midi_allocate_voice(-1, -1);
748 s = patch[inst]->sample[snum];
749 e = patch[inst]->extra[snum];
751 freq = digmid_freq(inst, s, e, note, bend);
756 /* store note information for later use */
757 info = &digmid_voice[voice - midi_digmid.basevoice];
764 reallocate_voice(voice, s);
765 voice_set_playmode(voice, e->play_mode);
766 voice_set_volume(voice, vol);
767 voice_set_frequency(voice, freq);
768 voice_set_pan(voice, pan);
770 if (e->sustain_level < 255)
771 voice_ramp_volume(voice, e->decay_time, e->sustain_level*vol/255);
779 * Triggers the specified voice. The instrument is specified as a GM
780 * patch number, pitch as a midi note number, and volume from 0-127.
781 * The bend parameter is _not_ expressed as a midi pitch bend value.
782 * It ranges from 0 (no pitch change) to 0xFFF (almost a semitone sharp).
783 * Drum sounds are indicated by passing an instrument number greater than
784 * 128, in which case the sound is GM percussion key #(inst-128).
786 static void digmid_key_on(int inst, int note, int bend, int vol, int pan)
794 /* quit if instrument is not available */
795 if ((!patch[inst]) || (patch[inst]->samples < 1))
798 /* adjust volume and pan ranges */
802 if (patch[inst]->samples == 1) {
803 /* only one sample to choose from */
804 digmid_trigger(inst, 0, note, bend, vol, pan);
807 /* find the sample(s) with best frequency range */
812 for (i=0; i<patch[inst]->samples; i++) {
814 e = patch[inst]->extra[i];
816 if ((freq >= e->low_note) && (freq <= e->high_note)) {
817 digmid_trigger(inst, i, note, bend, vol, pan);
823 diff = MIN(ABS(freq - e->low_note), ABS(freq - e->high_note));
824 if (diff < best_diff) {
831 if ((c <= 0) && (best >= 0))
832 digmid_trigger(inst, best, note, bend, vol, pan);
836 static END_OF_FUNCTION(digmid_key_on);
841 * Hey, guess what this does :-)
843 static void digmid_key_off(int voice)
845 DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice];
847 if (info->inst > 127)
850 if (info->e->release_time > 0)
851 voice_ramp_volume(voice, info->e->release_time, 0);
856 static END_OF_FUNCTION(digmid_key_off);
860 /* digmid_set_volume:
861 * Sets the volume of the specified voice (vol range 0-127).
863 static void digmid_set_volume(int voice, int vol)
865 DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice];
868 if (info->inst > 127)
873 if (info->e->sustain_level < 255) {
874 /* adjust for volume ramping */
875 int current = voice_get_volume(voice);
876 int target = info->e->sustain_level*info->vol/255;
877 int start = info->vol;
879 if (ABS(current - target) < 8) {
880 /* ramp has finished */
881 voice_set_volume(voice, vol*info->e->sustain_level/255);
884 /* in the middle of a ramp */
888 mu = MID(0, (current-target) * 256 / (start-target), 256);
892 v = mu+info->e->sustain_level*(256-mu)/256;
893 v = MID(0, vol*v/255, 255);
895 voice_set_volume(voice, v);
896 voice_ramp_volume(voice, info->e->decay_time*mu/256, info->e->sustain_level*vol/255);
901 voice_set_volume(voice, vol);
907 static END_OF_FUNCTION(digmid_set_volume);
912 * Sets the pitch of the specified voice.
914 static void digmid_set_pitch(int voice, int note, int bend)
916 DIGMID_VOICE *info = &digmid_voice[voice - midi_digmid.basevoice];
919 if (info->inst > 127)
922 freq = digmid_freq(info->inst, info->s, info->e, note, bend);
924 voice_set_frequency(voice, freq);
927 static END_OF_FUNCTION(digmid_set_pitch);
932 * Have we got a sensible looking patch set?
934 static int digmid_detect()
936 char dir[256], file[256];
938 if (!_digmid_find_patches(dir, file)) {
939 strcpy(allegro_error, "DIGMID patch set not found");
949 * Setup the digmid driver.
951 static int digmid_init(int voices)
955 for (i=0; i<256; i++)
958 midi_digmid.voices = voices;
960 /* create frequency table */
961 ftbl[129] = 14080000; /* A10 = 14080.000 hz */
962 for (i=128; i>=0; i--)
963 ftbl[i] = ftbl[i+1] / pow(2.0, 1.0/12.0);
965 LOCK_VARIABLE(midi_digmid);
966 LOCK_VARIABLE(patch);
968 LOCK_VARIABLE(digmid_voice);
969 LOCK_FUNCTION(digmid_key_on);
970 LOCK_FUNCTION(digmid_key_off);
971 LOCK_FUNCTION(digmid_set_volume);
972 LOCK_FUNCTION(digmid_set_pitch);
980 * Cleanup when we are finished.
982 static void digmid_exit()
986 for (i=0; i<256; i++) {
988 for (j=i+1; j<256; j++) {
989 if (patch[j] == patch[i])
992 destroy_patch(patch[i]);