PageRenderTime 31ms CodeModel.GetById 2ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/project/jni/sdl_mixer/native_midi_gpl/emumidi.c

https://github.com/aichunyu/FFPlayer
C | 390 lines | 314 code | 29 blank | 47 comment | 143 complexity | d614e4d995abc61d57a31c397d15b771 MD5 | raw file
  1/************************************************************************
  2   emumidi.c  -- emulation of midi device for FM/OPL3/GUS
  3
  4   Copyright (C) 1994-1996 Nathan I. Laredo
  5
  6   This program is modifiable/redistributable under the terms
  7   of the GNU General Public Licence.
  8
  9   You should have received a copy of the GNU General Public License
 10   along with this program; if not, write to the Free Software
 11   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 12   Send your comments and all your spare pocket change to
 13   laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
 14   Kelly Drive, Lackland AFB, TX 78236-5128, USA.
 15 *************************************************************************/
 16/*    edited by Peter Kutak         */
 17/*    email : kutak@stonline.sk     */
 18
 19#if defined(linux) || defined(__FreeBSD__)
 20
 21#include "emumidi.h"
 22
 23SEQ_USE_EXTBUF();
 24
 25extern int seqfd, play_ext, play_gus, play_fm, play_awe;
 26extern int gus_dev, sb_dev, ext_dev, awe_dev;
 27extern struct synth_info card_info[MAX_CARDS];
 28extern int chanmask, perc, ticks, dochan, wantopl3, MT32;
 29extern int patchloaded[256], fmloaded[256], useprog[16];
 30int note_vel[16][128];
 31struct voicestate voice[2][36];
 32struct chanstate channel[16];
 33#define C_GUS 0
 34#define C_FM 1
 35#define CN (ISGUS(chn) ? C_GUS : C_FM)
 36#define CHANNEL (dochan ? chn : 0)
 37
 38void load_sysex(length, data, type)
 39int length;
 40unsigned char *data;
 41int type;
 42{
 43    unsigned long int i, j;
 44
 45    /*
 46     * If the system exclusive is for roland, evaluate it.  More than
 47     * roland could be evaluated here if i had documentation.  Please
 48     * submit patches for any other hardware to laredo@gnu.ai.mit.edu
 49     * Complete emulation of all GS sysex messages in the works....
 50     */
 51    if (length > 7 && data[0] == 0x41 && data[2] == 0x42 && data[3] == 0x12) {
 52	/* GS DATA SET MESSAGES */
 53	if (data[4] == 0x40 && (data[5] & 0xf0) == 0x10 && data[6] == 0x15) {
 54		/* USE RHYTHM PART */
 55		if (!(i = (data[5] & 0xf)))
 56		    i = 0x09;
 57		else if (i < 10)
 58		    i--;
 59		i = 1<<i;
 60		if (data[7])
 61		    perc |= i;
 62		else
 63		    perc &= ~i;
 64	}
 65	if ((data[4] == 0x40 || data[4] == 0) &&
 66	    data[5] == 0x00 && data[6] == 0x7f) { /* GS RESET */
 67		perc = 0x0200;	/* percussion in channel 10 only */
 68		for (i = 0; i < 16; i++) {	/* set state info */
 69		    for (j = 0; j < 128; j++)
 70			note_vel[i][j] = 0;
 71		    channel[i].bender = channel[i].oldbend = 8192;
 72		    channel[i].bender_range = channel[i].oldrange = 2;
 73		    channel[i].controller[CTL_PAN] = 64;
 74		    channel[i].controller[CTL_SUSTAIN] = 0;
 75    		}
 76	}
 77    }
 78    if (!play_ext)
 79	return;
 80    if (type == MIDI_SYSTEM_PREFIX)
 81	SEQ_MIDIOUT(ext_dev, MIDI_SYSTEM_PREFIX);
 82    for (i = 0; i < length; i++)
 83	SEQ_MIDIOUT(ext_dev, data[i]);
 84}
 85
 86int seq_set_patch(chn, pgm)
 87int chn, pgm;
 88{
 89    if (MT32 && pgm < 128)
 90	pgm = mt32pgm[pgm];
 91    if (useprog[chn])
 92	pgm = useprog[chn] - 1;
 93    if (ISMIDI(chn)) {
 94	SEQ_MIDIOUT(ext_dev, MIDI_PGM_CHANGE + CHANNEL);
 95	SEQ_MIDIOUT(ext_dev, pgm);
 96    } else if (ISAWE(chn)) {
 97	SEQ_SET_PATCH(awe_dev, chn, pgm);
 98    } else if (ISPERC(chn)) {
 99	if (ISGUS(chn) && patchloaded[pgm] != 1)
100	    return -1;
101	else if (ISFM(chn) && !fmloaded[pgm])
102	    return -1;
103    } else if (ISGUS(chn) && patchloaded[pgm] != 1)
104	/* find first loaded gus program to replace missing one */
105	for (pgm = 0; patchloaded[pgm] != 1; pgm++);
106    return (channel[chn].program = pgm);
107}
108
109/* finetune returns exact frequency with bender applied.  Not used */
110/*
111int finetune(chn, note)
112int chn, note;
113{
114    long int r, b, d;
115
116    r = channel[chn].bender_range;
117    b = channel[chn].bender - 8192;
118    if (!b || r + note > 127 || r - note < 0)
119	return n_freq[note];
120    r = n_freq[note + r] - n_freq[note - r];
121    d = b * r;
122    d /= 8192;
123    return n_freq[note] + d;
124
125}
126*/
127extern int _seqbufptr;
128
129void seq_stop_note(dev, chn, note, vel)
130int dev, chn, note, vel;
131{
132    int i, card = CN;
133
134    note_vel[chn][note] = 0;
135    if (ISMIDI(chn)) {
136	SEQ_MIDIOUT(dev, MIDI_NOTEOFF + CHANNEL);
137	SEQ_MIDIOUT(dev, note);
138	SEQ_MIDIOUT(dev, vel);
139    } else if (ISAWE(chn)) {
140	SEQ_STOP_NOTE(dev, chn, note, vel);
141    } else
142	for (i = 0; i < card_info[dev].nr_voices; i++)
143	    if (voice[card][i].channel == chn &&
144		voice[card][i].note == note) {
145		voice[card][i].dead = 1;
146		voice[card][i].timestamp /= 2;
147		if (!channel[chn].controller[CTL_SUSTAIN] && !ISPERC(chn))
148		    SEQ_STOP_NOTE(dev, i, note, vel);
149	    }
150}
151
152void seq_key_pressure(dev, chn, note, vel)
153int dev, chn, note, vel;
154{
155    int i, card = CN;
156
157    if (ISMIDI(chn)) {
158	SEQ_MIDIOUT(dev, MIDI_KEY_PRESSURE + CHANNEL);
159	SEQ_MIDIOUT(dev, note);
160	SEQ_MIDIOUT(dev, vel);
161    } else if (ISAWE(chn)) {
162	AWE_KEY_PRESSURE(dev, chn, note, vel);
163    } else
164	for (i = 0; i < card_info[dev].nr_voices; i++)
165	    if (voice[card][i].channel == chn &&
166		voice[card][i].note == note)
167		SEQ_KEY_PRESSURE(dev, i, note, vel);
168}
169
170int new_voice(dev, chn)
171int dev, chn;
172{
173    int i, oldest, last, card = CN;
174
175    if (ISFM(chn) && fmloaded[channel[chn].program] == OPL3_PATCH)
176	last = 6;		/* 4-op voice can only use first six voices */
177    else
178	last = card_info[dev].nr_voices;
179
180    for (i = oldest = 0; i < last; i++)
181	if (voice[card][i].timestamp < voice[card][oldest].timestamp)
182	    oldest = i;
183    return oldest;
184}
185
186void seq_start_note(dev, chn, note, vel)
187int dev, chn, note, vel;
188{
189    int v, c, card = CN;
190
191    note_vel[chn][note] = vel;
192    if (ISMIDI(chn)) {
193	SEQ_MIDIOUT(dev, MIDI_NOTEON + CHANNEL);
194	SEQ_MIDIOUT(dev, note);
195	SEQ_MIDIOUT(dev, vel);
196    } else if (vel == 0)
197	seq_stop_note(dev, chn, note, 64);
198    else if (ISAWE(chn)) {
199	SEQ_START_NOTE(dev, chn, note, vel);
200    } else {
201	v = new_voice(dev, chn);
202	SEQ_SET_PATCH(dev, v, channel[chn].program);
203	SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100));
204	SEQ_BENDER(dev, v, channel[chn].bender);
205	SEQ_CONTROL(dev, v, CTL_PAN,
206		    channel[chn].controller[CTL_PAN]);
207	SEQ_START_NOTE(dev, v, note, vel);
208	voice[card][v].note = note;
209	voice[card][v].channel = chn;
210	voice[card][v].timestamp = ticks;
211	voice[card][v].dead = 0;
212	if ((c = channel[chn].controller[CTL_CHORUS_DEPTH] * 8)) {
213	    if (channel[chn].bender_range)
214		c /= channel[chn].bender_range;
215	    v = new_voice(dev, chn);
216	    SEQ_SET_PATCH(dev, v, channel[chn].program);
217	    SEQ_BENDER_RANGE(dev, v, (channel[chn].bender_range * 100));
218	    if (channel[chn].bender + c < 0x4000) {
219		SEQ_BENDER(dev, v, channel[chn].bender + c);
220	    } else {
221		SEQ_BENDER(dev, v, channel[chn].bender - c);
222	    }
223	    /* put chorus note on the "extreme" side */
224	    c = channel[chn].controller[CTL_PAN];
225	    if (c < 64)
226		c = 0;
227	    else if (c > 64)
228		c = 127;
229	    SEQ_CONTROL(dev, v, CTL_PAN, c);
230	    SEQ_START_NOTE(dev, v, note, vel);
231	    voice[card][v].note = note;
232	    voice[card][v].channel = chn;
233	    /* allow chorus note to be stolen very quickly */
234	    voice[card][v].timestamp = ticks / 2;
235	    voice[card][v].dead = 0;
236	}
237    }
238}
239
240static int rpn1[16] =
241{127, 127, 127, 127, 127, 127, 127, 127,
242 127, 127, 127, 127, 127, 127, 127, 127};
243static int rpn2[16] =
244{127, 127, 127, 127, 127, 127, 127, 127,
245 127, 127, 127, 127, 127, 127, 127, 127};
246
247void seq_control(dev, chn, p1, p2)
248int dev, chn, p1, p2;
249{
250    int i, card = CN;
251
252    channel[chn].controller[p1] = p2;
253
254    if (ISMIDI(chn)) {
255	SEQ_MIDIOUT(dev, MIDI_CTL_CHANGE + CHANNEL);
256	SEQ_MIDIOUT(dev, p1);
257	SEQ_MIDIOUT(dev, p2);
258    }
259    if (p1 == 7 || p1 == 39)
260	return;
261    switch (p1) {
262    case CTL_SUSTAIN:
263	if (ISAWE(chn)) {
264	    SEQ_CONTROL(dev, chn, p1, p2);
265	} else if (!ISMIDI(chn))
266	    if (p1 == CTL_SUSTAIN && !p2) {
267		for (i = 0; i < card_info[card].nr_voices; i++)
268		    if (voice[card][i].channel == chn
269			&& voice[card][i].dead) {
270			SEQ_STOP_NOTE(dev, i, voice[card][i].note, 64);
271			voice[card][i].dead = 0;
272		    }
273	    }
274	break;
275    case CTL_REGIST_PARM_NUM_MSB:
276	rpn1[chn] = p2;
277	break;
278    case CTL_REGIST_PARM_NUM_LSB:
279	rpn2[chn] = p2;
280	break;
281    case CTL_DATA_ENTRY:
282	if (rpn1[chn] == 0 && rpn2[chn] == 0) {
283	    channel[chn].oldrange = channel[chn].bender_range;
284	    channel[chn].bender_range = p2;
285	    rpn1[chn] = rpn2[chn] = 127;
286	    if (ISAWE(chn)) {
287		SEQ_BENDER_RANGE(dev, chn, p2 * 100);
288	    } else if (!ISMIDI(chn))
289		for (i = 0; i < card_info[card].nr_voices; i++)
290		    SEQ_BENDER_RANGE(dev, i, p2 * 100);
291	}
292	break;
293    default:
294	/* sent on the off chance the sound driver is enhanced */
295	if (ISAWE(chn)) {
296	    SEQ_CONTROL(dev, chn, p1, p2);
297	} else if (!ISMIDI(chn) && (p1 < 0x10 || (p1 & 0xf0) == 0x50))
298	    for (i = 0; i < card_info[card].nr_voices; i++)
299		if (voice[card][i].channel == chn)
300		    SEQ_CONTROL(dev, i, p1, p2);
301	break;
302    }
303}
304
305void seq_chn_pressure(dev, chn, vel)
306int dev, chn, vel;
307{
308    int card = CN, i;
309
310    channel[chn].pressure = vel;
311    if (ISMIDI(chn)) {
312	SEQ_MIDIOUT(dev, MIDI_CHN_PRESSURE + CHANNEL);
313	SEQ_MIDIOUT(dev, vel);
314    } else if (ISAWE(chn)) {
315	AWE_CHN_PRESSURE(dev, chn, vel);
316    } else
317	for (i = 0; i < card_info[dev].nr_voices; i++)
318	    if (voice[card][i].channel == chn)
319		SEQ_KEY_PRESSURE(dev, i, voice[card][i].note, vel);
320}
321
322void seq_bender(dev, chn, p1, p2)
323int dev, chn, p1, p2;
324{
325    int card = CN, i, val;
326
327    val = (p2 << 7) + p1;
328    channel[chn].oldbend = channel[chn].bender;
329    channel[chn].bender = val;
330
331    if (ISMIDI(chn)) {
332	SEQ_MIDIOUT(dev, MIDI_PITCH_BEND + CHANNEL);
333	SEQ_MIDIOUT(dev, p1);
334	SEQ_MIDIOUT(dev, p2);
335    } else if (ISAWE(chn)) {
336	SEQ_BENDER(dev, chn, val);
337    } else
338	for (i = 0; i < card_info[dev].nr_voices; i++)
339	    if (voice[card][i].channel == chn)
340		SEQ_BENDER(dev, i, val);
341}
342
343void seq_reset()
344{
345    int i, j;
346
347    _seqbufptr = ticks = 0;
348    ioctl(seqfd, SNDCTL_SEQ_RESET);
349    for (i = 0; i < 16; i++) {
350	if (ISMIDI(i)) {
351	    seq_control(ext_dev,i,0,0);
352	    seq_control(ext_dev,i,32,0);
353	}
354	seq_set_patch(i, 0);
355	for (j = 0; j < 128; j++)
356	    note_vel[i][j] = 0;
357	channel[i].bender = channel[i].oldbend = 8192;
358	channel[i].bender_range = channel[i].oldrange = 2;
359	channel[i].controller[CTL_PAN] = 64;
360	channel[i].controller[CTL_SUSTAIN] = 0;
361    }
362    if (play_gus)
363	for (i = 0; i < card_info[gus_dev].nr_voices; i++) {
364	    SEQ_CONTROL(gus_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
365	    if (voice[0][i].note)
366		SEQ_STOP_NOTE(gus_dev, i, voice[0][i].note, 64);
367	    voice[0][i].dead = voice[0][i].timestamp = -1;
368	}
369    if (play_fm) {
370	if (wantopl3)
371	    ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &sb_dev);
372	for (i = 0; i < card_info[sb_dev].nr_voices; i++) {
373	    SEQ_CONTROL(sb_dev, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
374	    if (voice[1][i].note)
375		SEQ_STOP_NOTE(sb_dev, i, voice[1][i].note, 64);
376	    voice[1][i].dead = voice[1][i].timestamp = -1;
377	}
378    }
379    if (play_awe) {
380	AWE_SET_CHANNEL_MODE(awe_dev, 1);
381	AWE_DRUM_CHANNELS(awe_dev, perc);
382	AWE_TERMINATE_ALL(awe_dev);
383	for (i = 0; i < card_info[awe_dev].nr_voices; i++) {
384	    voice[0][i].dead = voice[0][i].timestamp = -1;
385	}
386    }
387    SEQ_DUMPBUF();
388}
389
390#endif /* linux || FreeBSD */