* CAUTION! This program is just an incompletely implemented version
* of the patch manager daemon for GUS. Using this program
* with the driver version 1.99.9 will hang your system
* completely (sooner or later).
* This program is for information only. The final
* implementation of the patch manager will not be
* compatible with this one.
#include <sys/soundcard.h>
#include <sys/ultrasound.h>
#define PATCH_PATH "/D/ultrasnd/midi"
{0}; /* 1 if the patch is already loaded */
unsigned char instruments
;
unsigned short nr_waveforms
;
unsigned short master_volume
;
unsigned short base_freq
;
unsigned char envelope_rate
[6];
unsigned char envelope_offset
[6];
unsigned char tremolo_sweep
;
unsigned char tremolo_rate
;
unsigned char tremolo_depth
;
unsigned char vibrato_sweep
;
unsigned char vibrato_rate
;
unsigned char vibrato_depth
;
unsigned short scale_factor
;
int seqfd
= 0, gus_dev
= -1;
struct patch_info
*patch
;
do_load_patch (struct patmgr_info
*rec
)
int i
, patfd
, pgm
, print_only
= 0;
struct pat_header header
;
struct sample_header sample
;
pgm
= rec
->data
.data8
[0];
return 0; /* Already loaded */
sprintf (name
, PATCH_PATH
"/%s.pat", patch_names
[pgm
]);
if ((patfd
= open (name
, O_RDONLY
, 0)) == -1)
if (read (patfd
, buf
, 0xef) != 0xef)
fprintf (stderr
, "%s: Short file\n", name
);
memcpy ((char *) &header
, buf
, sizeof (header
));
if (strncmp (header
.magic
, "GF1PATCH110", 12))
fprintf (stderr
, "%s: Not a patch file\n", name
);
if (strncmp (header
.version
, "ID#000002", 10))
fprintf (stderr
, "%s: Incompatible patch file version\n", name
);
header
.nr_waveforms
= *(unsigned short *) &buf
[85];
header
.master_volume
= *(unsigned short *) &buf
[87];
printf ("GUS: Loading: %s\n", name
);
for (i
= 0; i
< header
.nr_waveforms
; i
++)
if (lseek (patfd
, offset
, 0) == -1)
if (read (patfd
, &buf
, sizeof (sample
)) != sizeof (sample
))
fprintf (stderr
, "%s: Short file\n", name
);
memcpy ((char *) &sample
, buf
, sizeof (sample
));
* Since some fields of the patch record are not 32bit aligned, we must
sample
.low_note
= *(long *) &buf
[22];
sample
.high_note
= *(long *) &buf
[26];
sample
.base_note
= *(long *) &buf
[30];
sample
.detune
= *(short *) &buf
[34];
sample
.panning
= (unsigned char) buf
[36];
memcpy (sample
.envelope_rate
, &buf
[37], 6);
memcpy (sample
.envelope_offset
, &buf
[43], 6);
sample
.tremolo_sweep
= (unsigned char) buf
[49];
sample
.tremolo_rate
= (unsigned char) buf
[50];
sample
.tremolo_depth
= (unsigned char) buf
[51];
sample
.vibrato_sweep
= (unsigned char) buf
[52];
sample
.vibrato_rate
= (unsigned char) buf
[53];
sample
.vibrato_depth
= (unsigned char) buf
[54];
sample
.modes
= (unsigned char) buf
[55];
sample
.scale_frequency
= *(short *) &buf
[56];
sample
.scale_factor
= *(unsigned short *) &buf
[58];
printf ("\nSample: %03d / %s\n", i
, sample
.name
);
printf ("Len: %d, Loop start: %d, Loop end: %d\n", sample
.len
, sample
.loop_start
, sample
.loop_end
);
if (sample
.modes
& WAVE_16_BITS
)
if (sample
.modes
& WAVE_UNSIGNED
)
if (sample
.modes
& WAVE_LOOP_BACK
)
if (sample
.modes
& WAVE_BIDIR_LOOP
)
if (sample
.modes
& WAVE_LOOPING
)
if (sample
.modes
& WAVE_SUSTAIN_ON
)
if (sample
.modes
& WAVE_ENVELOPES
)
if (sample
.modes
& WAVE_ENVELOPES
)
printf ("Envelope info: ");
printf ("%d/%d ", sample
.envelope_rate
[i
],
sample
.envelope_offset
[i
]);
printf ("Tremolo: sweep=%d, rate=%d, depth=%d\n",
printf ("Vibrato: sweep=%d, rate=%d, depth=%d\n",
patch
= (struct patch_info
*) malloc (sizeof (*patch
) + sample
.len
);
patch
->device_no
= gus_dev
;
patch
->mode
= sample
.modes
| WAVE_TREMOLO
|
WAVE_VIBRATO
| WAVE_SCALE
;
patch
->loop_start
= sample
.loop_start
;
patch
->loop_end
= sample
.loop_end
;
patch
->base_note
= sample
.base_note
;
patch
->high_note
= sample
.high_note
;
patch
->low_note
= sample
.low_note
;
patch
->base_freq
= sample
.base_freq
;
patch
->detuning
= sample
.detune
;
patch
->panning
= (sample
.panning
- 7) * 16;
memcpy (patch
->env_rate
, sample
.envelope_rate
, 6);
memcpy (patch
->env_offset
, sample
.envelope_offset
, 6);
patch
->tremolo_sweep
= sample
.tremolo_sweep
;
patch
->tremolo_rate
= sample
.tremolo_rate
;
patch
->tremolo_depth
= sample
.tremolo_depth
;
patch
->vibrato_sweep
= sample
.vibrato_sweep
;
patch
->vibrato_rate
= sample
.vibrato_rate
;
patch
->vibrato_depth
= sample
.vibrato_depth
;
patch
->scale_frequency
= sample
.scale_frequency
;
patch
->scale_factor
= sample
.scale_factor
;
patch
->volume
= header
.master_volume
;
if (lseek (patfd
, offset
, 0) == -1)
if (read (patfd
, patch
->data
, sample
.len
) != sample
.len
)
fprintf (stderr
, "%s: Short file\n", name
);
if (write (seqfd
, patch
, sizeof (*patch
) + sample
.len
) == -1)
offset
= offset
+ sample
.len
;
main (int argc
, char *argv
[])
if ((seqfd
= open ("/dev/patmgr0", O_RDWR
, 0)) == -1)
fprintf (stderr
, "Cannot open\n");
if (ioctl (seqfd
, SNDCTL_SEQ_NRSYNTHS
, &n
) == -1)
perror ("NRSYNTH: /dev/patmgr0");
if (ioctl (seqfd
, SNDCTL_SYNTH_INFO
, &info
) == -1)
perror ("SYNTH_INFO: /dev/patmgr0");
if (info
.synth_type
== SYNTH_TYPE_SAMPLE
&& info
.synth_subtype
== SAMPLE_TYPE_GUS
)
fprintf (stderr
, "Error: Gravis Ultrasound not detected\n");
if (ioctl (seqfd
, SNDCTL_SEQ_RESETSAMPLES
, &gus_dev
) == -1)
for (i
= 0; i
< 256; i
++)
if (read (seqfd
, (char *) &inf
, sizeof (inf
)) != sizeof (inf
))
if (inf
.key
== PM_K_EVENT
)
if (ioctl (seqfd
, SNDCTL_SEQ_RESETSAMPLES
, &gus_dev
) == -1)
for (i
= 0; i
< 256; i
++)
printf ("Patch reset called\n");
for (i
= 0; i
< 256; i
++)
printf ("Patch loaded by client\n");
printf ("Unknown event %d\n", inf
.command
);
else if (inf
.key
== PM_K_COMMAND
)
if ((err
= do_load_patch (&inf
)))
if (ioctl (seqfd
, SNDCTL_SEQ_RESETSAMPLES
, &gus_dev
) == -1)
for (i
= 0; i
< 256; i
++)
err
= do_load_patch (&inf
);
printf("Error = %d\n", err
);
printf ("Unknown command %d\n", inf
.command
);
printf ("Unknown event %d/%d\n", inf
.key
, inf
.command
);
if (write (seqfd
, (char *) &inf
, sizeof (inf
)) != sizeof (inf
))