PageRenderTime 31ms CodeModel.GetById 5ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/project/jni/sdl_mixer/native_midi_gpl/patchload.c

https://github.com/aichunyu/FFPlayer
C | 412 lines | 332 code | 52 blank | 28 comment | 88 complexity | 5bce28ebb7f718e46d0c98659287f937 MD5 | raw file
  1/************************************************************************
  2   patchload.c  --  loads patches for playmidi package
  3   Some of this code was adapted from code written by Hannu Solovainen
  4
  5   Copyright (C) 1994-1996 Nathan I. Laredo
  6
  7   This program is modifiable/redistributable under the terms
  8   of the GNU General Public Licence.
  9
 10   You should have received a copy of the GNU General Public License
 11   along with this program; if not, write to the Free Software
 12   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 13   Send your comments and all your spare pocket change to
 14   laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
 15   Kelly Drive, Lackland AFB, TX 78236-5128, USA.
 16 *************************************************************************/
 17/*    edited by Peter Kutak            */
 18/*    email : kutak@stonline.sk        */
 19
 20#if defined(linux) || defined(__FreeBSD__)
 21
 22#include "playmidi.h"
 23#ifdef linux
 24#include <linux/ultrasound.h>
 25#else
 26#include <machine/ultrasound.h>
 27#endif
 28#include <sys/stat.h>
 29#include <fcntl.h>
 30#include <unistd.h>
 31#include "gmvoices.h"
 32
 33SEQ_USE_EXTBUF();
 34extern int play_gus, play_sb, play_ext, playing, verbose, force8bit;
 35extern int reverb, fmloaded[256], patchloaded[256];
 36extern int gus_dev, sb_dev, ext_dev, seqfd, wantopl3;
 37extern struct synth_info card_info[MAX_CARDS];
 38
 39static int use8bit = 0;
 40
 41struct pat_header {
 42    char magic[12];
 43    char version[10];
 44    char description[60];
 45    unsigned char instruments;
 46    char voices;
 47    char channels;
 48    unsigned short nr_waveforms;
 49    unsigned short master_volume;
 50    unsigned int data_size;
 51};
 52
 53struct sample_header {
 54    char name[7];
 55    unsigned char fractions;
 56    int len;
 57    int loop_start;
 58    int loop_end;
 59    unsigned short base_freq;
 60    int low_note;
 61    int high_note;
 62    int base_note;
 63    short detune;
 64    unsigned char panning;
 65
 66    unsigned char envelope_rate[6];
 67    unsigned char envelope_offset[6];
 68
 69    unsigned char tremolo_sweep;
 70    unsigned char tremolo_rate;
 71    unsigned char tremolo_depth;
 72
 73    unsigned char vibrato_sweep;
 74    unsigned char vibrato_rate;
 75    unsigned char vibrato_depth;
 76
 77    char modes;
 78
 79    short scale_frequency;
 80    unsigned short scale_factor;
 81};
 82
 83struct patch_info *patch;
 84int spaceleft, totalspace;
 85
 86void gus_reload_8_bit();
 87
 88void gus_load(pgm)
 89int pgm;
 90{
 91    int i, j, patfd, offset;
 92    struct pat_header header;
 93    struct sample_header sample;
 94    char buf[256], name[256];
 95    struct stat info;
 96
 97    if (pgm < 0) {
 98	use8bit = force8bit;
 99	GUS_NUMVOICES(gus_dev, (card_info[gus_dev].nr_voices = 32));
100	SEQ_DUMPBUF();
101	for (i = 0; i < 256; i++)
102	    patchloaded[i] = 0;
103	if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1)
104	{
105	    /* error: should quit */
106	}
107	spaceleft = gus_dev;
108	ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
109	totalspace = spaceleft;
110    }
111
112    if (patchloaded[pgm] < 0)
113	return;
114
115    if (patchloaded[pgm] == 1)
116	return;
117
118    if (gmvoice[pgm] == NULL) {
119	patchloaded[pgm] = -1;
120	return;
121    }
122    sprintf(name, PATCH_PATH1 "/%s.pat", gmvoice[pgm]);
123
124    if (stat(name, &info) == -1) {
125	sprintf(name, PATCH_PATH2 "/%s.pat", gmvoice[pgm]);
126	if (stat(name, &info) == -1)
127	    return;
128    }
129    if ((patfd = open(name, O_RDONLY, 0)) == -1)
130	return;
131    if (spaceleft < info.st_size) {
132	if (!use8bit)
133	    gus_reload_8_bit();
134	if (use8bit)
135	    if (spaceleft < info.st_size / 2) {
136		close(patfd);
137		patchloaded[pgm] = -1;	/* no space for patch */
138		return;
139	    }
140    }
141    if (read(patfd, buf, 0xef) != 0xef) {
142	close(patfd);
143	return;
144    }
145    memcpy((char *) &header, buf, sizeof(header));
146
147    if (strncmp(header.magic, "GF1PATCH110", 12)) {
148	close(patfd);
149	return;
150    }
151    if (strncmp(header.version, "ID#000002", 10)) {
152	close(patfd);
153	return;
154    }
155    header.nr_waveforms = *(unsigned short *) &buf[85];
156    header.master_volume = *(unsigned short *) &buf[87];
157
158    offset = 0xef;
159
160    for (i = 0; i < header.nr_waveforms; i++) {
161
162	if (lseek(patfd, offset, 0) == -1) {
163	    close(patfd);
164	    return;
165	}
166	if (read(patfd, &buf, sizeof(sample)) != sizeof(sample)) {
167	    close(patfd);
168	    return;
169	}
170	memcpy((char *) &sample, buf, sizeof(sample));
171
172	/*
173	 * Since some fields of the patch record are not 32bit aligned, we must
174	 * handle them specially.
175	 */
176	sample.low_note = *(int *) &buf[22];
177	sample.high_note = *(int *) &buf[26];
178	sample.base_note = *(int *) &buf[30];
179	sample.detune = *(short *) &buf[34];
180	sample.panning = (unsigned char) buf[36];
181
182	memcpy(sample.envelope_rate, &buf[37], 6);
183	memcpy(sample.envelope_offset, &buf[43], 6);
184
185	sample.tremolo_sweep = (unsigned char) buf[49];
186	sample.tremolo_rate = (unsigned char) buf[50];
187	sample.tremolo_depth = (unsigned char) buf[51];
188
189	sample.vibrato_sweep = (unsigned char) buf[52];
190	sample.vibrato_rate = (unsigned char) buf[53];
191	sample.vibrato_depth = (unsigned char) buf[54];
192	sample.modes = (unsigned char) buf[55];
193	sample.scale_frequency = *(short *) &buf[56];
194	sample.scale_factor = *(unsigned short *) &buf[58];
195
196	offset = offset + 96;
197	patch = (struct patch_info *) malloc(sizeof(*patch) + sample.len);
198
199	if (patch == NULL) {
200	    close(patfd);
201	    return;
202	}
203	patch->key = GUS_PATCH;
204	patch->device_no = gus_dev;
205	patch->instr_no = pgm;
206	patch->mode = sample.modes | WAVE_TREMOLO |
207	    WAVE_VIBRATO | WAVE_SCALE;
208	patch->len = (use8bit ? sample.len / 2 : sample.len);
209	patch->loop_start =
210	    (use8bit ? sample.loop_start / 2 : sample.loop_start);
211	patch->loop_end = (use8bit ? sample.loop_end / 2 : sample.loop_end);
212	patch->base_note = sample.base_note;
213	patch->high_note = sample.high_note;
214	patch->low_note = sample.low_note;
215	patch->base_freq = sample.base_freq;
216	patch->detuning = sample.detune;
217	patch->panning = (sample.panning - 7) * 16;
218
219	memcpy(patch->env_rate, sample.envelope_rate, 6);
220	for (j = 0; j < 6; j++)	/* tone things down slightly */
221	    patch->env_offset[j] =
222		(736 * sample.envelope_offset[j] + 384) / 768;
223
224	if (reverb)
225	    if (pgm < 120)
226		patch->env_rate[3] = (2 << 6) | (12 - (reverb >> 4));
227	    else if (pgm > 127)
228		patch->env_rate[1] = (3 << 6) | (63 - (reverb >> 1));
229
230	patch->tremolo_sweep = sample.tremolo_sweep;
231	patch->tremolo_rate = sample.tremolo_rate;
232	patch->tremolo_depth = sample.tremolo_depth;
233
234	patch->vibrato_sweep = sample.vibrato_sweep;
235	patch->vibrato_rate = sample.vibrato_rate;
236	patch->vibrato_depth = sample.vibrato_depth;
237
238	patch->scale_frequency = sample.scale_frequency;
239	patch->scale_factor = sample.scale_factor;
240
241	patch->volume = header.master_volume;
242
243	if (lseek(patfd, offset, 0) == -1) {
244	    close(patfd);
245	    return;
246	}
247	if (read(patfd, patch->data, sample.len) != sample.len) {
248	    close(patfd);
249	    return;
250	}
251	if (patch->mode & WAVE_16_BITS && use8bit) {
252	    patch->mode &= ~WAVE_16_BITS;
253	    /* cut out every other byte to make 8-bit data from 16-bit */
254	    for (j = 0; j < patch->len; j++)
255		patch->data[j] = patch->data[1 + j * 2];
256	}
257	SEQ_WRPATCH(patch, sizeof(*patch) + patch->len);
258	free(patch);
259	offset = offset + sample.len;
260    }
261    close(patfd);
262    spaceleft = gus_dev;
263    ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
264    patchloaded[pgm] = 1;
265    return;
266}
267
268void gus_reload_8_bit()
269{
270    int i;
271
272    if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1) 
273    {
274	/* error: should quit */
275    }
276    spaceleft = gus_dev;
277    ioctl(seqfd, SNDCTL_SYNTH_MEMAVL, &spaceleft);
278    totalspace = spaceleft;
279    use8bit = 1;
280    for (i = 0; i < 256; i++)
281	if (patchloaded[i] > 0) {
282	    patchloaded[i] = 0;
283	    gus_load(i);
284	}
285}
286
287void adjustfm(buf, key)
288char *buf;
289int key;
290{
291    unsigned char pan = ((rand() % 3) + 1) << 4;
292
293    if (key == FM_PATCH) {
294	buf[39] &= 0xc0;
295	if (buf[46] & 1)
296	    buf[38] &= 0xc0;
297	buf[46] = (buf[46] & 0xcf) | pan;
298	if (reverb) {
299	    unsigned val;
300	    val = buf[43] & 0x0f;
301	    if (val > 0)
302		val--;
303	    buf[43] = (buf[43] & 0xf0) | val;
304	}
305    } else {
306	int mode;
307	if (buf[46] & 1)
308	    mode = 2;
309	else
310	    mode = 0;
311	if (buf[57] & 1)
312	    mode++;
313	buf[50] &= 0xc0;
314	if (mode == 3)
315	    buf[49] &= 0xc0;
316	if (mode == 1)
317	    buf[39] &= 0xc0;
318	if (mode == 2 || mode == 3)
319	    buf[38] &= 0xc0;
320	buf[46] = (buf[46] & 0xcf) | pan;
321	buf[57] = (buf[57] & 0xcf) | pan;
322	if (mode == 1 && reverb) {
323	    unsigned val;
324	    val = buf[43] & 0x0f;
325	    if (val > 0)
326		val--;
327	    buf[43] = (buf[43] & 0xf0) | val;
328	    val = buf[54] & 0x0f;
329	    if (val > 0)
330		val--;
331	    buf[54] = (buf[54] & 0xf0) | val;
332	}
333    }
334}
335
336void loadfm()
337{
338    int sbfd, i, n, voice_size, data_size;
339    char buf[60];
340    struct sbi_instrument instr;
341
342    for (i = 0; i < 256; i++)
343	fmloaded[i] = 0;
344    srand(getpid());
345    if (wantopl3) {
346	voice_size = 60;
347	sbfd = open(O3MELODIC, O_RDONLY, 0);
348    } else {
349	voice_size = 52;
350	sbfd = open(SBMELODIC, O_RDONLY, 0);
351    }
352    if (sbfd == -1)
353    {
354        /* error: should quit */
355    }
356    instr.device = sb_dev;
357
358    for (i = 0; i < 128; i++) {
359	if (read(sbfd, buf, voice_size) != voice_size)
360	{
361	    /* error: should quit */
362	}
363	instr.channel = i;
364
365	if (strncmp(buf, "4OP", 3) == 0) {
366	    instr.key = OPL3_PATCH;
367	    data_size = 22;
368	} else {
369	    instr.key = FM_PATCH;
370	    data_size = 11;
371	}
372
373	fmloaded[i] = instr.key;
374
375	adjustfm(buf, instr.key);
376	for (n = 0; n < 32; n++)
377	    instr.operators[n] = (n < data_size) ? buf[36 + n] : 0;
378
379	SEQ_WRPATCH(&instr, sizeof(instr));
380    }
381    close(sbfd);
382
383    if (wantopl3)
384	sbfd = open(O3DRUMS, O_RDONLY, 0);
385    else
386	sbfd = open(SBDRUMS, O_RDONLY, 0);
387
388    for (i = 128; i < 175; i++) {
389	if (read(sbfd, buf, voice_size) != voice_size)
390	{
391	    /* error: should quit */
392	}
393	instr.channel = i;
394
395	if (strncmp(buf, "4OP", 3) == 0) {
396	    instr.key = OPL3_PATCH;
397	    data_size = 22;
398	} else {
399	    instr.key = FM_PATCH;
400	    data_size = 11;
401	}
402	fmloaded[i] = instr.key;
403
404	adjustfm(buf, instr.key);
405	for (n = 0; n < 32; n++)
406	    instr.operators[n] = (n < data_size) ? buf[n + 36] : 0;
407
408	SEQ_WRPATCH(&instr, sizeof(instr));
409    }
410    close(sbfd);
411}
412#endif /* linux || FreeBSD */