1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: sequencer.c 1411 2018-07-19 02:51:45Z wesleyjohnson $
5 //
6 // Copyright (C) 1995-1996 Michael Heasley (mheasley@hmc.edu)
7 // GNU General Public License
8 // Portions Copyright (C) 1996-2016 by DooM Legacy Team.
9 // GNU General Public License
10 // Heavily modified for use with Doom Legacy.
11 // Removed wad search and Doom version dependencies.
12 // Is now dependent upon IPC msgs from the Doom program
13 // for all wad information, and the music lump id.
14
15 /*************************************************************************
16 * sequencer.c
17 *
18 * Copyright (C) 1995-1997 Michael Heasley (mheasley@hmc.edu)
19 *
20 * Portions Copyright (c) 1997 Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp)
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *************************************************************************/
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <sys/soundcard.h>
47 // synth_info
48 #include "musserver.h"
49
50 // Some synth, like TiMidity, do not implement all-off effectively.
51 // Take drastic measures to kill notes that drone on.
52 //#define ALL_OFF_FIX 1
53
54 // Some operations from soundcard.h cause messages about violating strict aliasing.
55 // This is due to an operation *(short *)&_seqbuf[_seqbufptr+6] = (w14).
56 // There is no good way to stop this, as long as -wstrict-aliasing is set.
57
58
59 #ifdef DEFAULT_AWE32_SYNTH
60 # define DEFAULT_DEV DVT_AWE32_SYNTH
61 #elif defined(DEFAULT_FM_SYNTH)
62 # define DEFAULT_DEV DVT_FM_SYNTH
63 #else
64 # define DEFAULT_DEV DVT_MIDI
65 #endif
66
67 // Arbitrary dev type value. The Midi dev types all seem to be 0.
68 #define DVT_TYPE_TIMIDITY 1001
69 #define DVT_TYPE_FLUIDSYNTH 1002
70
71 //#define SEQ_MIDIOUT(a,b) test(a,b)
72
73 #define MAX_SYNTH_INFO 8
74 #define MAX_MIDI_INFO 8
75
76 static struct synth_info sinfo[MAX_SYNTH_INFO];
77 // known fields:
78 // char name[]
79 // int device : 0..n, index to devices
80 // int synth_type
81 // SYNTH_TYPE_FM, SYNTH_TYPE_SAMPLE, SYNTH_TYPE_MIDI
82 // int synth_subtype
83 // FM_TYPE_ADLIB
84 // FM_TYPE_OPL3
85 // MIDI_TYPE_MPU401
86 // SAMPLE_TYPE_BASIC
87 // SAMPLE_TYPE_GUS
88 // SAMPLE_TYPE_WAVEFRONT
89 // int nr_voices
90 // int instr_bank_size
91 // uint capabilities : bit flags
92 // SYNTH_CAP_PERCMODE, SYNTH_CAP_OPL3, SYNTH_CAP_INPUT
93
94 static struct midi_info minfo[MAX_MIDI_INFO];
95 // known fields:
96 // char name[]
97 // int device : 0..n, index to devices
98 // uint capabilities (almost always 0, except for MPU401)
99 // MIDI_CAP_MPU401
100 // int dev_type (always 0)
101
102 // Selected device
103 static struct synth_info * synth_ip = NULL;
104 static struct midi_info * midi_ip = NULL;
105
106 static byte use_dvt = DVT_DEFAULT; // dvt_e
107 static int seq_dev = -1; // sound port, and index into sinfo or minfo
108
109 // Found devices, port nums.
110 static int awe_dev = -1;
111 static int fm_dev = -1;
112 static int timidity_dev = -1;
113 static int fluidsynth_dev = -1;
114 static int ext_midi_dev = -1;
115
116 static int seqfd;
117 static int mixfd;
118 static int synth_patches[16];
119 static int chanvol[16];
120 static int volscale = 100;
121 static byte fm_note12 = 0;
122 static synth_voice_t *voices;
123 static struct sbi_instrument fm_sbi[175];
124 opl_instr_t fm_instruments[175];
125
126
127 #if 0
128 // Indexed by synth_type
129 static const char * synth_type_txt[] = {
130 "FM", // SYNTH_TYPE_FM
131 "SAMPLE", // SYNTH_TYPE_SAMPLE
132 "MIDI", // SYNTH_TYPE_MIDI
133 };
134 #endif
135
136 // [WDJ] To make TiMidity dump midi commands to console 1,
137 // add switch "--verbose=3" to where it is started.
138 // Look in /etc/rc.d/rc.local.
139
140 SEQ_USE_EXTBUF();
141 SEQ_DEFINEBUF(2048);
142
143 int queue_size = 0;
144
145 // Write the output buffer to the port.
146 // This function is as specified in /usr/include/linux/soundcard.h
147 // to be used by the SEQ_ macros.
148 // This will sleep() if the sequencer buffer is full.
seqbuf_dump(void)149 void seqbuf_dump(void)
150 {
151 if (_seqbufptr)
152 {
153 if (write(seqfd, _seqbuf, _seqbufptr) == -1)
154 {
155 perror("write /dev/sequencer");
156 cleanup_exit(-1, "Seqbuf dump");
157 // NO RETURN
158 }
159 }
160 _seqbufptr = 0;
161 }
162
163
queue_free(void)164 int queue_free( void )
165 {
166 int queue_free;
167 // Update the queue status.
168 ioctl(seqfd, SNDCTL_SEQ_GETOUTCOUNT, &queue_free );
169 return queue_free;
170 }
171
172
173 // [WDJ] Notes on ioctrl:
174 // SNDCTL_SEQ_TESTMIDI: tests midi device for life.
175 // Returns EFAULT when user not allowed.
176 // Returns ENXIO when midi_dev is invalid.
177 // Returns open err, when fails to be opened.
178 // Returns 0 when passes.
179 // SNDCTL_SEQ_SYNC: attempts to sync queue
180 // Returns EINTR if fails to empty queue.
181 // This only flushes the music to the device or TiMidity,
182 // which has its own queue.
183 // Often hangs the musserver.
184 // SNDCTL_SEQ_GETOUTCOUNT:
185 // Put (MAX_QUEUE - qlen) to value.
186 // SNDCTL_SEQ_RESET: reset the sequencer
187 // Midi: sends all-notes-off to all channels of each midi that was written.
188 // SEQ_WAIT: Starts a sound timer, returns 1. Does not sleep or wait.
189 // SEQ_MIDIOUT: uses command MIDIPUTC to put bytes to a buffer.
190 // seqbuf_dump flushes the buffer to the sequencer device.
191 // During seqbuf_dump, if there is not enough space in queue, the
192 // write will sleep.
193 // SEQ_MIDIPUTC: Will start sound timer when buffer is full, and returns 2.
194 // This is not the device queue.
195
196 // dvt_type : dvt_e
197 // Return index to midi_info, -1 when fail.
find_midi(int dvt_type,int dev_type,int port_num)198 int find_midi(int dvt_type, int dev_type, int port_num)
199 {
200 int num_midi;
201 int m = 0;
202 int ior;
203
204 // Get the number of midi devices.
205 if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &num_midi) != 0)
206 return 0;
207
208 if( num_midi > MAX_MIDI_INFO )
209 num_midi = MAX_MIDI_INFO;
210
211 if( dvt_type != DVT_LIST && port_num >= 0 && port_num < num_midi )
212 {
213 // Get a specific port.
214 minfo[port_num].device = port_num;
215 ior = ioctl(seqfd, SNDCTL_MIDI_INFO, &minfo[port_num]);
216 if( ior == 0 )
217 return port_num;
218 }
219
220 for (m = 0; m < num_midi; m++)
221 {
222 // Set device, then ioctl fills in name, capabilities, dev_type.
223 minfo[m].device = m;
224 ior = ioctl(seqfd, SNDCTL_MIDI_INFO, &minfo[m]);
225 if( ior < 0 ) continue;
226 if( strstr( minfo[m].name, "TiMidi" ) )
227 {
228 minfo[m].dev_type = DVT_TYPE_TIMIDITY;
229 if( timidity_dev < 0 )
230 timidity_dev = m;
231 }
232 else if( strstr( minfo[m].name, "FLUID" ) )
233 {
234 minfo[m].dev_type = DVT_TYPE_FLUIDSYNTH;
235 if( fluidsynth_dev < 0 )
236 fluidsynth_dev = m;
237 }
238 else
239 {
240 if( ext_midi_dev < 0 )
241 ext_midi_dev = m;
242 }
243 if( dev_type >= 0 )
244 {
245 if(minfo[m].dev_type == dev_type)
246 return m;
247 }
248 }
249 return num_midi;
250 }
251
252 // dvt_type : dvt_e
253 // Return index to synth_info, -1 when fail.
find_synth(int dvt_type,int dev_type,int port_num)254 int find_synth(int dvt_type, int dev_type, int port_num)
255 {
256 int num_synth = 0;
257 int ior;
258 int s = 0;
259
260 if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &num_synth) == -1)
261 return -1;
262
263 if( num_synth > MAX_SYNTH_INFO )
264 num_synth = MAX_SYNTH_INFO;
265
266 if( dvt_type != DVT_LIST && port_num >= 0 && port_num < num_synth)
267 {
268 sinfo[port_num].device = port_num;
269 ior = ioctl(seqfd, SNDCTL_SYNTH_INFO, &sinfo[port_num]);
270 if( ior == 0 )
271 return port_num;
272 }
273
274 for (s = 0; s < num_synth; s++)
275 {
276 sinfo[s].device = s;
277 ior = ioctl(seqfd, SNDCTL_SYNTH_INFO, &sinfo[s]);
278 if( ior < 0 ) continue;
279 if (sinfo[s].synth_type == SYNTH_TYPE_SAMPLE)
280 {
281 #ifdef AWE32_SYNTH_SUPPORT
282 if (sinfo[s].synth_subtype == SAMPLE_TYPE_AWE32)
283 {
284 if( awe_dev < 0 )
285 awe_dev = s;
286 if ((dev_type == SYNTH_TYPE_SAMPLE) && (dvt_type == DVT_AWE32_SYNTH))
287 break;
288 }
289 #endif
290 }
291 else
292 {
293 if( fm_dev < 0 )
294 fm_dev = s;
295 if ((sinfo[s].synth_type == dev_type) && (dvt_type == DVT_FM_SYNTH))
296 break;
297 }
298 }
299 return num_synth;
300 }
301
302 #ifdef AWE32_SYNTH_SUPPORT
setup_awe(int awe_dev)303 void setup_awe(int awe_dev)
304 {
305 use_dvt = DVT_AWE32_SYNTH;
306 seq_dev = awe_dev;
307 synth_ip = & sinfo[awe_dev];
308
309 if (verbose)
310 printf("Using synth device number %d (%s)\n", seq_dev+1, synth_ip->name);
311 }
312 #endif
313
setup_midi(int midi_dev)314 void setup_midi(int midi_dev)
315 {
316 use_dvt = DVT_MIDI; // DVT_EXT_MIDI, DVT_TIMIDITY, DVT_FLUIDSYNTH
317 seq_dev = midi_dev;
318 midi_ip = & minfo[midi_dev];
319
320 if (verbose)
321 printf("Using midi device number %d (%s)\n", seq_dev+1, midi_ip->name);
322 }
323
setup_fm(int fm_dev)324 void setup_fm(int fm_dev)
325 {
326 char * fail_msg = NULL;
327 FILE *sndstat;
328 int num_voices;
329 int x;
330
331 use_dvt = DVT_FM_SYNTH;
332 seq_dev = fm_dev;
333 synth_ip = & sinfo[seq_dev];
334 fm_note12 = 0;
335
336 // Linux no longer has /dev/sndstat
337 sndstat = fopen("/dev/sndstat", "r");
338 if( sndstat )
339 {
340 char sndver[100];
341 char * snddate = NULL;
342
343 fgets(sndver, 100, sndstat);
344 fclose(sndstat);
345
346 if( verbose > 1 )
347 printf( "musserver: sndver=%s\n", sndver );
348
349 // [WDJ] Cannot fix this code properly because do not have the specific
350 // hardware they were detecting, and they did not leave comments.
351 // It does not exist on Linux 2.4 or Linux 2.6.
352 // Previous code was mostly extraneous.
353 snddate = strchr( sndver, '-' );
354 if( snddate && ( strncmp( snddate+1, "950728", 6 ) == 0) )
355 fm_note12 = 1;
356 }
357
358 num_voices = synth_ip->nr_voices;
359 voices = malloc( num_voices * sizeof(synth_voice_t));
360 for (x = 0; x < num_voices; x++)
361 {
362 voices[x].note = -1;
363 voices[x].channel = -1;
364 }
365 for (x = 0; x < 16; x++)
366 synth_patches[x] = -1;
367
368 mixfd = open("/dev/mixer", O_WRONLY, 0);
369 if( mixfd < 0 )
370 {
371 printf( "musserver: /dev/mixer: %s\n", strerror(errno) );
372 fail_msg = "Failed to open mixer";
373 goto fail_exit;
374 }
375
376 if (verbose)
377 printf("Using synth device number %d (%s)\n", seq_dev+1, synth_ip->name);
378 return;
379
380 fail_exit:
381 cleanup_exit(2, fail_msg );
382 return;
383 }
384
list_devs(void)385 void list_devs( void )
386 {
387 int n, num;
388
389 if ((seqfd = open("/dev/sequencer", O_WRONLY, 0)) < 0)
390 {
391 perror("open /dev/sequencer");
392 exit(1);
393 }
394
395 printf("Devices found\n");
396 num = find_midi(DVT_LIST, -1, -1);
397 for (n = 0; n < num; n++)
398 {
399 printf(" Port %2i: Midi device of type %d (%s)\n",
400 n, minfo[n].dev_type, minfo[n].name);
401 }
402 num = find_synth(DVT_LIST, -1, -1);
403 for (n = 0; n < num; n++)
404 {
405 printf(" Port %2i: Synth device of type %d (%s)\n",
406 n, sinfo[n].synth_type, sinfo[n].name);
407 }
408 exit(0);
409 }
410
411
412 // Search orders for pref device option.
413 // Now that this is changable from the DoomLegacy menu,
414 // no longer do search when an specific device is specified.
415 // Ext midi is only a port, even when nothing is there, so put it last.
416 static char * search_order[] =
417 {
418 "", // DVT_DEFAULT, never used
419 "ALTFE", // DVT_SEARCH1
420 "AFLTghjkE", // DVT_SEARCH2, to be customized
421 "kjhgTLFAE", // DVT_SEARCH3, to be customized
422 "TLE", // DVT_MIDI
423 "T", // DVT_TIMIDITY
424 "L", // DVT_FLUIDSYNTH
425 "E", // DVT_EXT_MIDI
426 "AFL", // DVT_SYNTH
427 "F", // DVT_FM_SYNTH
428 "A", // DVT_AWE32_SYNTH
429 "g", // DVT_DEV6
430 "h", // DVT_DEV7
431 "j", // DVT_DEV8
432 "k" // DVT_DEV9
433 };
434
435
436 static
seq_setup(int pref_dev,int dev_type,int port_num)437 void seq_setup(int pref_dev, int dev_type, int port_num)
438 {
439 int fnd_dev = -1;
440 char * pc; // pref sequence chars
441
442 // printf( "pref_dev = %i, dev_type = %i, port_num = %i\n", pref_dev, dev_type, port_num );
443 if ((seqfd = open("/dev/sequencer", O_WRONLY, 0)) < 0)
444 {
445 perror("open /dev/sequencer");
446 exit(1);
447 }
448
449 // Get the queue size;
450 ioctl(seqfd, SNDCTL_SEQ_GETOUTCOUNT, &queue_size );
451 if( verbose )
452 printf( " Sequencer queue size= %i\n", queue_size );
453
454 // Midi dev_type is usually always 0.
455 if((pref_dev == DVT_TIMIDITY) && (dev_type < 0))
456 dev_type = DVT_TYPE_TIMIDITY;
457 if((pref_dev == DVT_FLUIDSYNTH) && (dev_type < 0))
458 dev_type = DVT_TYPE_FLUIDSYNTH;
459
460 if( (pref_dev != DVT_DEFAULT)
461 && ((dev_type >= 0) || (port_num >= 0)) )
462 {
463 if( pref_dev >= DVT_SYNTH )
464 {
465 fnd_dev = find_synth( pref_dev, dev_type, port_num);
466 }
467 else
468 {
469 fnd_dev = find_midi( pref_dev, dev_type, port_num);
470 }
471 }
472
473 if( fnd_dev < 0 )
474 {
475 if (pref_dev == DVT_DEFAULT)
476 pref_dev = DEFAULT_DEV;
477
478 #ifdef DEFAULT_TYPE
479 if (dev_type == -1)
480 dev_type = DEFAULT_TYPE;
481 #endif
482 find_midi( DVT_MIDI, dev_type, -1);
483 find_synth( DVT_SYNTH, dev_type, -1);
484 }
485
486 if( verbose )
487 {
488 printf("Timidity port: %i\n", timidity_dev );
489 printf("Ext midi port: %i\n", ext_midi_dev );
490 printf("FM port: %i\n", fm_dev );
491 printf("AWE32 port: %i\n", awe_dev );
492 }
493
494 if ((timidity_dev < 0) && (ext_midi_dev < 0) && (fm_dev < 0) && (awe_dev < 0 ))
495 goto no_devices;
496
497 if( pref_dev < DVT_SEARCH1 || pref_dev > DVT_DEV9 ) // table limits
498 {
499 pref_dev = DVT_SEARCH1;
500 }
501 pc = search_order[pref_dev];
502 use_dvt = DVT_DEFAULT;
503 for( ; ; pc++ )
504 {
505 switch( *pc )
506 {
507 case 'T': // Timidity dev
508 if( timidity_dev >= 0 )
509 setup_midi( timidity_dev );
510 break;
511 case 'L': // Fluidsynth dev
512 if( fluidsynth_dev >= 0 )
513 setup_midi( fluidsynth_dev );
514 break;
515 case 'E': // Ext Midi dev
516 if( ext_midi_dev >= 0 )
517 setup_midi( ext_midi_dev );
518 break;
519 case 'F': // FM dev
520 if( fm_dev >= 0 )
521 setup_fm( fm_dev );
522 break;
523 case 'A': // Awe32 dev
524 #ifdef AWE32_SYNTH_SUPPORT
525 if (awe_dev >= 0)
526 setup_awe(awe_dev);
527 #endif
528 break;
529 case 'g': // new device
530 case 'h': // new device
531 case 'j': // new device
532 case 'k': // new device
533 break;
534 case 0: // end of list
535 goto no_devices;
536 }
537 if( use_dvt != DVT_DEFAULT ) break;
538 }
539
540 reset_midi();
541 return;
542
543 no_devices:
544 seq_dev = -1;
545 if( no_devices_exit )
546 cleanup_exit(1, "no music devices found" );
547 return;
548 }
549
550
551
552
553 // ---- MIDI
554
555 // [WDJ]
556 // SEQ_MIDIOUT: Puts the 4 byte midi command in the buffer.
557 // SEQ_START_NOTE: sends MIDI_NOTEON using 8 byte command
558 // SEQ_STOP_NOTE: sends MIDI_NOTEOFF using 8 byte command
559
560 // Midi Channel Mode Messages
561 enum {
562 CMM_RESET_ALL_CONTROLLERS = 0x79,
563 CMM_LOCAL_CONTROL = 0x7A,
564 CMM_ALL_NOTES_OFF = 0x7B,
565 CMM_OMNI_OFF = 0x7C,
566 CMM_OMNI_ON = 0x7D,
567 CMM_MONO_ON = 0x7E, // Poly off
568 CMM_POLY_ON = 0x7F // Mono off
569 };
570
571
cleanup_midi(void)572 void cleanup_midi(void)
573 {
574 reset_midi();
575 close(seqfd);
576 if (use_dvt == DVT_FM_SYNTH)
577 close(mixfd);
578 }
579
580
581 #ifdef ALL_OFF_FIX
582 // Some midi synth do not implement all-off, and will leave
583 // notes running (drones) when the stream stops.
584 // This tracks what notes and channels were used, and stops them.
585
586 // The number of notes and channels actually used in a song is limited.
587 byte channel_used[16];
588 byte note_used[0x7F];
589
590 static
clear_used(void)591 void clear_used(void)
592 {
593 memset( channel_used, 0, sizeof(channel_used) );
594 memset( note_used, 0, sizeof(note_used) );
595 }
596 #endif
597
all_off_midi(void)598 void all_off_midi(void)
599 {
600 if (use_dvt == DVT_MIDI)
601 {
602 #ifdef ALL_OFF_FIX
603 unsigned int note, channel;
604 for (channel = 0; channel < 16; channel++)
605 {
606 if( ! channel_used[channel] ) continue;
607 for( note=0; note <= 0x7F; note++ )
608 {
609 if( note_used[note] )
610 {
611 SEQ_MIDIOUT(seq_dev, MIDI_NOTEOFF | channel);
612 SEQ_MIDIOUT(seq_dev, note);
613 SEQ_MIDIOUT(seq_dev, 8);
614 SEQ_DUMPBUF();
615 }
616 }
617 }
618 clear_used();
619 #else
620 unsigned int channel;
621 for (channel = 0; channel < 16; channel++)
622 {
623 /* all notes off */
624 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE | channel);
625 SEQ_MIDIOUT(seq_dev, CMM_ALL_NOTES_OFF);
626 SEQ_MIDIOUT(seq_dev, 0);
627 }
628 SEQ_DUMPBUF();
629 #endif
630 }
631 }
632
633
634
pause_midi(void)635 void pause_midi(void)
636 {
637 // Pause as much as can be paused.
638 // Stop the notes.
639 unsigned int channel;
640
641 #ifdef AWE32_SYNTH_SUPPORT
642 if (use_dvt == DVT_AWE32_SYNTH)
643 {
644 AWE_SET_CHANNEL_MODE(seq_dev, 1);
645 AWE_NOTEOFF_ALL(seq_dev);
646 }
647 else
648 #endif
649 if (use_dvt == DVT_MIDI)
650 {
651 for (channel = 0; channel < 16; channel++)
652 {
653 /* all notes off */
654 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE | channel);
655 SEQ_MIDIOUT(seq_dev, CMM_ALL_NOTES_OFF);
656 SEQ_MIDIOUT(seq_dev, 0);
657 }
658 }
659 else
660 {
661 for (channel = 0; channel < sinfo[seq_dev].nr_voices; channel++)
662 {
663 SEQ_STOP_NOTE(seq_dev, channel, voices[channel].note, 64);
664 voices[channel].note = -1;
665 voices[channel].channel = -1;
666 }
667 }
668 SEQ_DUMPBUF();
669 }
670
reset_midi(void)671 void reset_midi(void)
672 {
673 unsigned int channel;
674
675 #ifdef AWE32_SYNTH_SUPPORT
676 if (use_dvt == DVT_AWE32_SYNTH)
677 {
678 AWE_SET_CHANNEL_MODE(seq_dev, 1);
679 AWE_NOTEOFF_ALL(seq_dev);
680 for (channel = 0; channel < 16; channel++)
681 {
682 SEQ_BENDER_RANGE(seq_dev, channel, 200);
683 SEQ_BENDER(seq_dev, channel, 0);
684 }
685 }
686 else
687 #endif
688 if (use_dvt == DVT_MIDI)
689 {
690 // SNDCTL_SEQ_SYNC hangs the musserver
691 // ioctl(seqfd, SNDCTL_SEQ_SYNC);
692 // All notes off on used channels.
693 // Being implemented at the driver, it has the most immediate effect.
694 ioctl(seqfd, SNDCTL_SEQ_RESET);
695 usleep( 500 ); // long enough for synth to react
696
697 #if 0
698 // Optional additional all notes off.
699 // It does not seem to affect anything much.
700 pause_midi();
701 // It takes a while for buffer to get to all notes off, and then
702 // there is an off decay.
703 // If other commands follow too closely, they retrigger the note.
704 usleep(20000);
705 #endif
706
707 #ifdef ALL_OFF_FIX
708 all_off_midi(); // for synth that drone on
709 // Touching the controls too soon seems to retrigger drone
710 usleep(20000);
711 #endif
712
713 for (channel = 0; channel < 16; channel++)
714 {
715 /* reset pitch bender */
716 pitch_bend( channel, 64 );
717 /* reset volume to 100 */
718 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE | channel);
719 SEQ_MIDIOUT(seq_dev, CTL_MAIN_VOLUME);
720 SEQ_MIDIOUT(seq_dev, volscale);
721 chanvol[channel] = 100;
722 /* reset pan */
723 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE | channel);
724 SEQ_MIDIOUT(seq_dev, CTL_PAN);
725 SEQ_MIDIOUT(seq_dev, 64);
726
727 SEQ_DUMPBUF();
728 }
729 }
730 else
731 {
732 for (channel = 0; channel < sinfo[seq_dev].nr_voices; channel++)
733 {
734 SEQ_STOP_NOTE(seq_dev, channel, voices[channel].note, 64);
735 SEQ_BENDER_RANGE(seq_dev, channel, 200);
736 voices[channel].note = -1;
737 voices[channel].channel = -1;
738 }
739 }
740 SEQ_DUMPBUF();
741 usleep( 300 ); // long enough for synth to react
742 }
743
744 // channel : 0..15
note_off(int note,int channel,int volume)745 void note_off(int note, int channel, int volume)
746 {
747 int x = 0;
748
749 #ifdef AWE32_SYNTH_SUPPORT
750 if (use_dvt == DVT_AWE32_SYNTH)
751 {
752 SEQ_STOP_NOTE(seq_dev, channel, note, volume);
753 }
754 else
755 #endif
756 if (use_dvt == DVT_MIDI)
757 {
758 SEQ_MIDIOUT(seq_dev, MIDI_NOTEOFF | channel);
759 SEQ_MIDIOUT(seq_dev, note);
760 SEQ_MIDIOUT(seq_dev, volume); // velocity
761 // some controllers use NOTEOFF velocity, some don't
762 }
763 else if( synth_ip )
764 {
765 for (x = 0; x < synth_ip->nr_voices; x++)
766 {
767 if ((voices[x].note == note) && (voices[x].channel == channel))
768 {
769 voices[x].note = -1;
770 voices[x].channel = -1;
771 SEQ_STOP_NOTE(seq_dev, x, note, volume);
772 break;
773 }
774 }
775 }
776 SEQ_DUMPBUF();
777 }
778
779
780 // channel : 0..15
note_on(int note,int channel,int volume)781 void note_on(int note, int channel, int volume)
782 {
783 int x = 0;
784
785 #ifdef AWE32_SYNTH_SUPPORT
786 if (use_dvt == DVT_AWE32_SYNTH)
787 {
788 SEQ_START_NOTE(seq_dev, channel, note, volume);
789 }
790 else
791 #endif
792 if (use_dvt == DVT_MIDI)
793 {
794 SEQ_MIDIOUT(seq_dev, MIDI_NOTEON | channel);
795 SEQ_MIDIOUT(seq_dev, note); // General Midi has assigned codes to notes, 0..127
796 SEQ_MIDIOUT(seq_dev, volume); // velocity 0..127
797 #ifdef ALL_OFF_FIX
798 channel_used[channel] = 1;
799 note_used[note] = 1;
800 #endif
801 }
802 else if( synth_ip )
803 {
804 // Find an empty voice
805 for (x = 0; x < synth_ip->nr_voices; x++)
806 {
807 if ((voices[x].note == -1) && (voices[x].channel == -1))
808 break;
809 }
810 if (x < synth_ip->nr_voices)
811 {
812 voices[x].note = note;
813 voices[x].channel = channel;
814 if (channel == 9) /* drum note */
815 {
816 if (use_dvt == DVT_FM_SYNTH)
817 {
818 SEQ_SET_PATCH(seq_dev, x, note + 93);
819 note = fm_instruments[note + 93].note;
820 }
821 else
822 SEQ_SET_PATCH(seq_dev, x, note + 128);
823 }
824 else
825 {
826 SEQ_SET_PATCH(seq_dev, x, synth_patches[channel]);
827 if ( fm_note12 ) // [WDJ] have no idea what this fixes
828 note = note + 12;
829 }
830 SEQ_START_NOTE(seq_dev, x, note, volume);
831 }
832 }
833 SEQ_DUMPBUF();
834 }
835
pitch_bend(int channel,signed int value)836 void pitch_bend(int channel, signed int value)
837 {
838 int x;
839
840 #ifdef AWE32_SYNTH_SUPPORT
841 if (use_dvt == DVT_AWE32_SYNTH)
842 {
843 SEQ_BENDER(seq_dev, channel, 128 * value);
844 }
845 else
846 #endif
847 if (use_dvt == DVT_MIDI)
848 {
849 SEQ_MIDIOUT(seq_dev, MIDI_PITCH_BEND | channel);
850 SEQ_MIDIOUT(seq_dev, value >> 7); // upper 7 bits
851 SEQ_MIDIOUT(seq_dev, value & 127); // lower 7 bits
852 }
853 else if( synth_ip )
854 {
855 for (x = 0; x < synth_ip->nr_voices; x++)
856 {
857 if (voices[x].channel == channel)
858 {
859 SEQ_BENDER_RANGE(seq_dev, x, 200);
860 SEQ_BENDER(seq_dev, x, 128*value);
861 }
862 }
863 }
864 SEQ_DUMPBUF();
865 }
866
control_change(int controller,int channel,int value)867 void control_change(int controller, int channel, int value)
868 {
869 int x;
870
871 if (controller == CTL_MAIN_VOLUME)
872 {
873 chanvol[channel] = value;
874 value = value * volscale / 100;
875 }
876
877 #ifdef AWE32_SYNTH_SUPPORT
878 if (use_dvt == DVT_AWE32_SYNTH)
879 {
880 SEQ_CONTROL(seq_dev, channel, controller, value);
881 }
882 else
883 #endif
884 if (use_dvt == DVT_MIDI)
885 {
886 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE | channel);
887 SEQ_MIDIOUT(seq_dev, controller);
888 SEQ_MIDIOUT(seq_dev, value);
889 }
890 else
891 {
892 for (x = 0; x < sinfo[seq_dev].nr_voices; x++)
893 {
894 if ((voices[x].channel == channel) && (controller == CTL_MAIN_VOLUME))
895 SEQ_MAIN_VOLUME(seq_dev, x, value);
896 }
897 }
898 SEQ_DUMPBUF();
899 }
900
patch_change(int patch,int channel)901 void patch_change(int patch, int channel)
902 {
903 int x;
904
905 #ifdef AWE32_SYNTH_SUPPORT
906 if (use_dvt == DVT_AWE32_SYNTH)
907 {
908 SEQ_SET_PATCH(seq_dev, channel, patch);
909 }
910 else
911 #endif
912 if (use_dvt == DVT_MIDI)
913 {
914 SEQ_MIDIOUT(seq_dev, MIDI_PGM_CHANGE | channel);
915 SEQ_MIDIOUT(seq_dev, patch);
916 }
917 else if( synth_ip )
918 {
919 for (x = 0; x < synth_ip->nr_voices; x++)
920 {
921 if (((voices[x].channel == -1) && (voices[x].note == -1)) || (voices[x].channel == channel))
922 {
923 synth_patches[channel] = patch;
924 break;
925 }
926 }
927 }
928 SEQ_DUMPBUF();
929 }
930
midi_wait(uint32_t wtime)931 void midi_wait( uint32_t wtime )
932 {
933 ioctl(seqfd, SNDCTL_SEQ_SYNC); // let queue go empty
934 SEQ_WAIT_TIME( wtime ); // wait, absolute time
935 SEQ_DUMPBUF();
936 }
937
938 // action : mmt_e
midi_timer(int action)939 void midi_timer(int action)
940 {
941 switch (action)
942 {
943 case MMT_START:
944 SEQ_START_TIMER();
945 break;
946 case MMT_STOP:
947 SEQ_STOP_TIMER();
948 break;
949 case MMT_CONT:
950 SEQ_CONTINUE_TIMER();
951 break;
952 }
953 }
954
955 static int logscale[32] = {
956 0,15, 25,33, 40,45, 50,55, 59,62, 65,68, 70,73, 75,77,
957 79,81, 83,85, 87,89, 90,92, 93,94, 95,97, 98,99, 100,100
958 };
959
vol_change(int volume)960 void vol_change(int volume)
961 {
962 int x;
963
964 volume = (volume < 0 ? 0 : (volume > 31 ? 31 : volume));
965 volscale = logscale[volume];
966 #ifdef AWE32_SYNTH_SUPPORT
967 if (use_dvt == DVT_AWE32_SYNTH)
968 {
969 for (x = 0; x < 16; x++)
970 SEQ_CONTROL(seq_dev, x, CTL_MAIN_VOLUME, chanvol[x] * volscale / 100);
971 }
972 else
973 #endif
974 if (use_dvt == DVT_MIDI)
975 {
976 for (x = 0; x < 16; x++)
977 {
978 SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + x);
979 SEQ_MIDIOUT(seq_dev, CTL_MAIN_VOLUME);
980 SEQ_MIDIOUT(seq_dev, chanvol[x] * volscale / 100);
981 }
982 }
983 else
984 {
985 volume = volscale;
986 volume |= (volume << 8);
987 //if (-1 == ioctl(mixfd, SOUND_MIXER_WRITE_SYNTH, &volume))
988 // perror("volume change");
989 ioctl(mixfd, SOUND_MIXER_WRITE_SYNTH, &volume);
990 ioctl(mixfd, SOUND_MIXER_WRITE_LINE2, &volume);
991 }
992 SEQ_DUMPBUF();
993 }
994
995
996 static
fmload(void)997 void fmload(void)
998 {
999 int x;
1000
1001 for (x = 0; x < 175; x++)
1002 {
1003 fm_sbi[x].key = FM_PATCH;
1004 fm_sbi[x].device = seq_dev;
1005 fm_sbi[x].channel = x;
1006 fm_sbi[x].operators[0] = fm_instruments[x].patchdata[0];
1007 fm_sbi[x].operators[1] = fm_instruments[x].patchdata[7];
1008 fm_sbi[x].operators[2] = fm_instruments[x].patchdata[4] + fm_instruments[x].patchdata[5];
1009 fm_sbi[x].operators[3] = fm_instruments[x].patchdata[11] + fm_instruments[x].patchdata[12];
1010 fm_sbi[x].operators[4] = fm_instruments[x].patchdata[1];
1011 fm_sbi[x].operators[5] = fm_instruments[x].patchdata[8];
1012 fm_sbi[x].operators[6] = fm_instruments[x].patchdata[2];
1013 fm_sbi[x].operators[7] = fm_instruments[x].patchdata[9];
1014 fm_sbi[x].operators[8] = fm_instruments[x].patchdata[3];
1015 fm_sbi[x].operators[9] = fm_instruments[x].patchdata[10];
1016 fm_sbi[x].operators[10] = fm_instruments[x].patchdata[6];
1017 fm_sbi[x].operators[11] = fm_instruments[x].patchdata[16];
1018 fm_sbi[x].operators[12] = fm_instruments[x].patchdata[23];
1019 fm_sbi[x].operators[13] = fm_instruments[x].patchdata[20] + fm_instruments[x].patchdata[21];
1020 fm_sbi[x].operators[14] = fm_instruments[x].patchdata[27] + fm_instruments[x].patchdata[28];
1021 fm_sbi[x].operators[15] = fm_instruments[x].patchdata[17];
1022 fm_sbi[x].operators[16] = fm_instruments[x].patchdata[24];
1023 fm_sbi[x].operators[17] = fm_instruments[x].patchdata[18];
1024 fm_sbi[x].operators[18] = fm_instruments[x].patchdata[25];
1025 fm_sbi[x].operators[19] = fm_instruments[x].patchdata[19];
1026 fm_sbi[x].operators[20] = fm_instruments[x].patchdata[26];
1027 fm_sbi[x].operators[21] = fm_instruments[x].patchdata[22];
1028 SEQ_WRPATCH(&fm_sbi[x], sizeof(fm_sbi[x]));
1029 }
1030 }
1031
1032
1033 // Init, load, setup the selected device
seq_midi_init_setup(int sel_dvt,int dev_type,int port_num)1034 void seq_midi_init_setup(int sel_dvt, int dev_type, int port_num)
1035 {
1036 seq_setup(sel_dvt, dev_type, port_num);
1037
1038 if (use_dvt == DVT_FM_SYNTH)
1039 {
1040 read_wad_genmidi( & genmidi_lump );
1041 fmload();
1042 }
1043
1044 // According to cph, this makes the device really load the instruments
1045 // Thanks, Colin!!
1046 cleanup_midi();
1047
1048 seq_setup(sel_dvt, dev_type, port_num);
1049
1050 if (use_dvt == DVT_FM_SYNTH)
1051 {
1052 read_wad_genmidi( & genmidi_lump );
1053 fmload();
1054 }
1055 }
1056