patchload.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:10k
- /************************************************************************
- patchload.c -- loads patches for playmidi package
- Some of this code was adapted from code written by Hannu Solovainen
- Copyright (C) 1994-1996 Nathan I. Laredo
- This program is modifiable/redistributable under the terms
- of the GNU General Public Licence.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- Send your comments and all your spare pocket change to
- laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
- Kelly Drive, Lackland AFB, TX 78236-5128, USA.
- *************************************************************************/
- /* edited by Peter Kutak */
- /* email : kutak@stonline.sk */
- #if defined(linux) || defined(__FreeBSD__)
- #include "playmidi.h"
- #ifdef linux
- #include <linux/ultrasound.h>
- #else
- #include <machine/ultrasound.h>
- #endif
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include "gmvoices.h"
- SEQ_USE_EXTBUF();
- extern int play_gus, play_sb, play_ext, playing, verbose, force8bit;
- extern int reverb, fmloaded[256], patchloaded[256];
- extern int gus_dev, sb_dev, ext_dev, seqfd, wantopl3;
- extern struct synth_info card_info[MAX_CARDS];
- static int use8bit = 0;
- struct pat_header {
- char magic[12];
- char version[10];
- char description[60];
- unsigned char instruments;
- char voices;
- char channels;
- unsigned short nr_waveforms;
- unsigned short master_volume;
- unsigned int data_size;
- };
- struct sample_header {
- char name[7];
- unsigned char fractions;
- int len;
- int loop_start;
- int loop_end;
- unsigned short base_freq;
- int low_note;
- int high_note;
- int base_note;
- short detune;
- unsigned char panning;
- 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;
- char modes;
- short scale_frequency;
- unsigned short scale_factor;
- };
- struct patch_info *patch;
- int spaceleft, totalspace;
- void gus_reload_8_bit();
- void gus_load(pgm)
- int pgm;
- {
- int i, j, patfd, offset;
- struct pat_header header;
- struct sample_header sample;
- char buf[256], name[256];
- struct stat info;
- if (pgm < 0) {
- use8bit = force8bit;
- GUS_NUMVOICES(gus_dev, (card_info[gus_dev].nr_voices = 32));
- SEQ_DUMPBUF();
- for (i = 0; i < 256; i++)
- patchloaded[i] = 0;
- if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
- {
- /* error: should quit */
- }
- spaceleft = gus_dev;
- ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
- totalspace = spaceleft;
- }
- if (patchloaded[pgm] < 0)
- return;
- if (patchloaded[pgm] == 1)
- return;
- if (gmvoice[pgm] == NULL) {
- patchloaded[pgm] = -1;
- return;
- }
- sprintf(name, PATCH_PATH1 "/%s.pat", gmvoice[pgm]);
- if (stat(name, &info) == -1) {
- sprintf(name, PATCH_PATH2 "/%s.pat", gmvoice[pgm]);
- if (stat(name, &info) == -1)
- return;
- }
- if ((patfd = open(name, O_RDONLY, 0)) == -1)
- return;
- if (spaceleft < info.st_size) {
- if (!use8bit)
- gus_reload_8_bit();
- if (use8bit)
- if (spaceleft < info.st_size / 2) {
- close(patfd);
- patchloaded[pgm] = -1; /* no space for patch */
- return;
- }
- }
- if (read(patfd, buf, 0xef) != 0xef) {
- close(patfd);
- return;
- }
- memcpy((char *) &header, buf, sizeof(header));
- if (strncmp(header.magic, "GF1PATCH110", 12)) {
- close(patfd);
- return;
- }
- if (strncmp(header.version, "ID#000002", 10)) {
- close(patfd);
- return;
- }
- header.nr_waveforms = *(unsigned short *) &buf[85];
- header.master_volume = *(unsigned short *) &buf[87];
- offset = 0xef;
- for (i = 0; i < header.nr_waveforms; i++) {
- if (lseek(patfd, offset, 0) == -1) {
- close(patfd);
- return;
- }
- if (read(patfd, &buf, sizeof(sample)) != sizeof(sample)) {
- close(patfd);
- return;
- }
- memcpy((char *) &sample, buf, sizeof(sample));
- /*
- * Since some fields of the patch record are not 32bit aligned, we must
- * handle them specially.
- */
- sample.low_note = *(int *) &buf[22];
- sample.high_note = *(int *) &buf[26];
- sample.base_note = *(int *) &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];
- offset = offset + 96;
- patch = (struct patch_info *) malloc(sizeof(*patch) + sample.len);
- if (patch == NULL) {
- close(patfd);
- return;
- }
- patch->key = GUS_PATCH;
- patch->device_no = gus_dev;
- patch->instr_no = pgm;
- patch->mode = sample.modes | WAVE_TREMOLO |
- WAVE_VIBRATO | WAVE_SCALE;
- patch->len = (use8bit ? sample.len / 2 : sample.len);
- patch->loop_start =
- (use8bit ? sample.loop_start / 2 : sample.loop_start);
- patch->loop_end = (use8bit ? sample.loop_end / 2 : 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);
- for (j = 0; j < 6; j++) /* tone things down slightly */
- patch->env_offset[j] =
- (736 * sample.envelope_offset[j] + 384) / 768;
- if (reverb)
- if (pgm < 120)
- patch->env_rate[3] = (2 << 6) | (12 - (reverb >> 4));
- else if (pgm > 127)
- patch->env_rate[1] = (3 << 6) | (63 - (reverb >> 1));
- 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) {
- close(patfd);
- return;
- }
- if (read(patfd, patch->data, sample.len) != sample.len) {
- close(patfd);
- return;
- }
- if (patch->mode & WAVE_16_BITS && use8bit) {
- patch->mode &= ~WAVE_16_BITS;
- /* cut out every other byte to make 8-bit data from 16-bit */
- for (j = 0; j < patch->len; j++)
- patch->data[j] = patch->data[1 + j * 2];
- }
- SEQ_WRPATCH(patch, sizeof(*patch) + patch->len);
- free(patch);
- offset = offset + sample.len;
- }
- close(patfd);
- spaceleft = gus_dev;
- ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
- patchloaded[pgm] = 1;
- return;
- }
- void gus_reload_8_bit()
- {
- int i;
- if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
- {
- /* error: should quit */
- }
- spaceleft = gus_dev;
- ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
- totalspace = spaceleft;
- use8bit = 1;
- for (i = 0; i < 256; i++)
- if (patchloaded[i] > 0) {
- patchloaded[i] = 0;
- gus_load(i);
- }
- }
- void adjustfm(buf, key)
- char *buf;
- int key;
- {
- unsigned char pan = ((rand() % 3) + 1) << 4;
- if (key == FM_PATCH) {
- buf[39] &= 0xc0;
- if (buf[46] & 1)
- buf[38] &= 0xc0;
- buf[46] = (buf[46] & 0xcf) | pan;
- if (reverb) {
- unsigned val;
- val = buf[43] & 0x0f;
- if (val > 0)
- val--;
- buf[43] = (buf[43] & 0xf0) | val;
- }
- } else {
- int mode;
- if (buf[46] & 1)
- mode = 2;
- else
- mode = 0;
- if (buf[57] & 1)
- mode++;
- buf[50] &= 0xc0;
- if (mode == 3)
- buf[49] &= 0xc0;
- if (mode == 1)
- buf[39] &= 0xc0;
- if (mode == 2 || mode == 3)
- buf[38] &= 0xc0;
- buf[46] = (buf[46] & 0xcf) | pan;
- buf[57] = (buf[57] & 0xcf) | pan;
- if (mode == 1 && reverb) {
- unsigned val;
- val = buf[43] & 0x0f;
- if (val > 0)
- val--;
- buf[43] = (buf[43] & 0xf0) | val;
- val = buf[54] & 0x0f;
- if (val > 0)
- val--;
- buf[54] = (buf[54] & 0xf0) | val;
- }
- }
- }
- void loadfm()
- {
- int sbfd, i, n, voice_size, data_size;
- char buf[60];
- struct sbi_instrument instr;
- for (i = 0; i < 256; i++)
- fmloaded[i] = 0;
- srand(getpid());
- if (wantopl3) {
- voice_size = 60;
- sbfd = open(O3MELODIC, O_RDONLY, 0);
- } else {
- voice_size = 52;
- sbfd = open(SBMELODIC, O_RDONLY, 0);
- }
- if (sbfd == -1)
- {
- /* error: should quit */
- }
- instr.device = sb_dev;
- for (i = 0; i < 128; i++) {
- if (read(sbfd, buf, voice_size) != voice_size)
- {
- /* error: should quit */
- }
- instr.channel = i;
- if (strncmp(buf, "4OP", 3) == 0) {
- instr.key = OPL3_PATCH;
- data_size = 22;
- } else {
- instr.key = FM_PATCH;
- data_size = 11;
- }
- fmloaded[i] = instr.key;
- adjustfm(buf, instr.key);
- for (n = 0; n < 32; n++)
- instr.operators[n] = (n < data_size) ? buf[36 + n] : 0;
- SEQ_WRPATCH(&instr, sizeof(instr));
- }
- close(sbfd);
- if (wantopl3)
- sbfd = open(O3DRUMS, O_RDONLY, 0);
- else
- sbfd = open(SBDRUMS, O_RDONLY, 0);
- for (i = 128; i < 175; i++) {
- if (read(sbfd, buf, voice_size) != voice_size)
- {
- /* error: should quit */
- }
- instr.channel = i;
- if (strncmp(buf, "4OP", 3) == 0) {
- instr.key = OPL3_PATCH;
- data_size = 22;
- } else {
- instr.key = FM_PATCH;
- data_size = 11;
- }
- fmloaded[i] = instr.key;
- adjustfm(buf, instr.key);
- for (n = 0; n < 32; n++)
- instr.operators[n] = (n < data_size) ? buf[n + 36] : 0;
- SEQ_WRPATCH(&instr, sizeof(instr));
- }
- close(sbfd);
- }
- #endif /* linux || FreeBSD */