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