⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequencer.c

📁 The source code of Doom legacy for windows
💻 C
字号:
/************************************************************************* *  sequencer.c * *  Copyright (C) 1995-1997 Michael Heasley (mheasley@hmc.edu) * *  Portions Copyright (c) 1997 Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp) * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  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. *************************************************************************/#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/soundcard.h>#include "musserver.h"struct synth_info sinfo[5];struct midi_info minfo[5];int seqfd;int mixfd;int use_dev = -1;int seq_dev = -1;int synth_patches[16];int chanvol[16];int volscale = 100;unsigned int voxdate;struct synth_voice *voices;struct opl_instr fm_instruments[175];struct sbi_instrument fm_sbi[175];extern int verbose;extern void cleanup(int status);extern void reset_midi();extern void read_genmidi(FILE *wadfile);struct opl_instr fm_instruments[175];struct sbi_instrument fm_sbi[175];SEQ_USE_EXTBUF();SEQ_DEFINEBUF(2048);void seqbuf_dump(void){  if (_seqbufptr)  if (write(seqfd, _seqbuf, _seqbufptr) == -1)    {     perror("write /dev/sequencer");     cleanup(-1);     }  _seqbufptr = 0;}int find_midi(int m_type, int dev_num){int num_midi;int use_midi = -1;int m = 0;  if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &num_midi) == -1)    return 0;  for (m = 0; m < num_midi; m++)    {    minfo[m].device = m;    ioctl(seqfd, SNDCTL_MIDI_INFO, &minfo[m]);    use_midi = m;    if (minfo[m].dev_type == dev_num)      break;    }  if (m_type == NO_SYNTH)    return num_midi;  else    return use_midi;}int find_synth(int s_type, int dev_num){int num = 0;int fm = -1;#ifdef AWE32_SYNTH_SUPPORTint awe = -1;#endifint s = 0;  if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &num) == -1)    return 0;  else    for (s = 0; s < num; s++)      {      sinfo[s].device = s;      ioctl(seqfd, SNDCTL_SYNTH_INFO, &sinfo[s]);      if (sinfo[s].synth_type == SYNTH_TYPE_SAMPLE)        {#ifdef AWE32_SYNTH_SUPPORT        if (sinfo[s].synth_subtype == SAMPLE_TYPE_AWE32)          {          awe = s;	  if ((dev_num == SYNTH_TYPE_SAMPLE) && (s_type == AWE32_SYNTH))	    break;	  }#endif	}      else	{        fm = s;        if ((sinfo[s].synth_type == dev_num) && (s_type == FM_SYNTH))          break;        }      }  switch(s_type)    {    case FM_SYNTH:      return fm;      break;#ifdef AWE32_SYNTH_SUPPORT    case AWE32_SYNTH:      return awe;      break;#endif    case NO_SYNTH:      return num;      break;    default:      return -1;      break;    }}#ifdef AWE32_SYNTH_SUPPORTvoid setup_awe(int num_awe){  use_dev = AWE32_SYNTH;  seq_dev = num_awe;  if (verbose)    printf("Using synth device number %d (%s)\n", seq_dev+1, sinfo[seq_dev].name);}#endifvoid setup_midi(int num_midi){  use_dev = EXT_MIDI;  seq_dev = num_midi;  if (verbose)    printf("Using midi device number %d (%s)\n", seq_dev+1, minfo[seq_dev].name);}void setup_fm(int num_fm){int x;int y;FILE *sndstat;char sndver[100];char snddate[100];  use_dev = FM_SYNTH;  seq_dev = num_fm;  sndstat = fopen("/dev/sndstat", "r");  if (sndstat == NULL)    {    printf("musserver: could not open /dev/sndstat, exiting.\n");    exit(1);    }  fgets(sndver, 100, sndstat);  for (x = 0; x < strlen(sndver); x++)    if (sndver[x] == '-')      {      x++;      for (y = x; y < strlen(sndver); y++)        if (sndver[y] != ' ')          snddate[y-x] = sndver[y];        else          {          snddate[y-x] = 0;          break;          }      break;      }  voxdate = atoi(snddate);  fclose(sndstat);  voices = malloc(sinfo[seq_dev].nr_voices * sizeof(struct synth_voice));  for (x = 0; x < sinfo[seq_dev].nr_voices; x++)    {    voices[x].note = -1;    voices[x].channel = -1;    }  for (x = 0; x < 16; x++)    synth_patches[x] = -1;  mixfd = open("/dev/mixer", O_WRONLY, 0);  if (verbose)    printf("Using synth device number %d (%s)\n", seq_dev+1, sinfo[seq_dev].name);}void list_devs(){int dummy;int x;  if ((seqfd = open("/dev/sequencer", O_WRONLY, 0)) < 0)    {    perror("open /dev/sequencer");    exit(1);    }  dummy = find_midi(NO_SYNTH, NO_SYNTH);  for (x = 0; x < dummy; x++)    printf("Found a midi device of type %d (%s)\n", minfo[x].dev_type,            minfo[x].name);  dummy = find_synth(NO_SYNTH, NO_SYNTH);  for (x = 0; x < dummy; x++)    printf("Found a synth device of type %d (%s)\n", sinfo[x].synth_type,            sinfo[x].name);  exit(0);}void seq_setup(int pref_dev, int dev_type){int num_midi;int num_awe;int num_fm;  if ((seqfd = open("/dev/sequencer", O_WRONLY, 0)) < 0)    {    perror("open /dev/sequencer");    exit(1);    }  num_midi = find_midi(EXT_MIDI, dev_type);  num_fm = find_synth(FM_SYNTH, dev_type);  num_awe = find_synth(AWE32_SYNTH, dev_type);  if ((num_midi == -1) && (num_fm == -1) && (num_awe == -1))    {    printf("musserver: no music devices found, exiting.\n");    exit(1);    }  switch(pref_dev) {    case EXT_MIDI:      if (num_midi != -1)	setup_midi(num_midi);#ifdef AWE32_SYNTH_SUPPORT      else if (num_awe != -1)	setup_awe(num_awe);#endif      else if (num_fm != -1)	setup_fm(num_fm);      break;    case FM_SYNTH:      if (num_fm != -1)	setup_fm(num_fm);      else if (num_midi != -1)	setup_midi(num_midi);#ifdef AWE32_SYNTH_SUPPORT      else if (num_awe != -1)	setup_awe(num_awe);#endif      break;#ifdef AWE32_SYNTH_SUPPORT    case AWE32_SYNTH:      if (num_awe != -1)	setup_awe(num_awe);      else if (num_midi != -1)	setup_midi(num_midi);      else if (num_fm != -1)	setup_fm(num_fm);      break;#endif    default:      break;  }  reset_midi();}void cleanup_midi(void){  reset_midi();  close(seqfd);  if (use_dev == FM_SYNTH)    close(mixfd);}void reset_midi(void){unsigned int channel;#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)    {    AWE_SET_CHANNEL_MODE(seq_dev, 1);    AWE_NOTEOFF_ALL(seq_dev);    for (channel = 0; channel < 16; channel++)      {      SEQ_BENDER_RANGE(seq_dev, channel, 200);      SEQ_BENDER(seq_dev, channel, 0);      }    }  else#endif  if (use_dev == EXT_MIDI)    for (channel = 0; channel < 16; channel++)      {      /* all notes off */      SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + channel);      SEQ_MIDIOUT(seq_dev, 0x7b);      SEQ_MIDIOUT(seq_dev, 0);      /* reset pitch bender */      SEQ_MIDIOUT(seq_dev, MIDI_PITCH_BEND + channel);      SEQ_MIDIOUT(seq_dev, 64 >> 7);      SEQ_MIDIOUT(seq_dev, 64 & 127);      /* reset volume to 100 */      SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + channel);      SEQ_MIDIOUT(seq_dev, CTL_MAIN_VOLUME);      SEQ_MIDIOUT(seq_dev, volscale);      chanvol[channel] = 100;      /* reset pan */      SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + channel);      SEQ_MIDIOUT(seq_dev, CTL_PAN);      SEQ_MIDIOUT(seq_dev, 64);      }  else    for (channel = 0; channel < sinfo[seq_dev].nr_voices; channel++)      {        SEQ_STOP_NOTE(seq_dev, channel, voices[channel].note, 64);        SEQ_BENDER_RANGE(seq_dev, channel, 200);        voices[channel].note = -1;        voices[channel].channel = -1;      }  SEQ_DUMPBUF();}void note_off(int note, int channel, int volume){int x = 0;#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    SEQ_STOP_NOTE(seq_dev, channel, note, volume);  }  else#endif  if (use_dev == EXT_MIDI)    {    SEQ_MIDIOUT(seq_dev, MIDI_NOTEOFF + channel);    SEQ_MIDIOUT(seq_dev, note);    SEQ_MIDIOUT(seq_dev, volume);    }  else    {    for (x = 0; x < sinfo[seq_dev].nr_voices; x++)      if ((voices[x].note == note) && (voices[x].channel == channel))        break;    if (x != sinfo[seq_dev].nr_voices)      {      voices[x].note = -1;      voices[x].channel = -1;      SEQ_STOP_NOTE(seq_dev, x, note, volume);      }    }  SEQ_DUMPBUF();}void note_on(int note, int channel, int volume){int x = 0;#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    SEQ_START_NOTE(seq_dev, channel, note, volume);  }  else#endif  if (use_dev == EXT_MIDI)    {    SEQ_MIDIOUT(seq_dev, MIDI_NOTEON + channel);    SEQ_MIDIOUT(seq_dev, note);    SEQ_MIDIOUT(seq_dev, volume);    }  else    {    for (x = 0; x < sinfo[seq_dev].nr_voices; x++)      if ((voices[x].note == -1) && (voices[x].channel == -1))        break;    if (x != sinfo[seq_dev].nr_voices)      {      voices[x].note = note;      voices[x].channel = channel;      if (channel == 9)         /* drum note */        {        if (use_dev == FM_SYNTH)          {          SEQ_SET_PATCH(seq_dev, x, note + 93);          note = fm_instruments[note + 93].note;          }        else          SEQ_SET_PATCH(seq_dev, x, note + 128);        }      else        {        SEQ_SET_PATCH(seq_dev, x, synth_patches[channel]);        if ((voxdate != 950728) && (use_dev == FM_SYNTH))          note = note + 12;        }      SEQ_START_NOTE(seq_dev, x, note, volume);      }    }  SEQ_DUMPBUF();}void pitch_bend(int channel, signed int value){int x;#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    SEQ_BENDER(seq_dev, channel, 128 * value);  }  else#endif  if (use_dev == EXT_MIDI)    {    SEQ_MIDIOUT(seq_dev, MIDI_PITCH_BEND + channel);    SEQ_MIDIOUT(seq_dev, value >> 7);    SEQ_MIDIOUT(seq_dev, value & 127);    }  else    {    for (x = 0; x < sinfo[seq_dev].nr_voices; x++)      if (voices[x].channel == channel)        {        SEQ_BENDER_RANGE(seq_dev, x, 200);        SEQ_BENDER(seq_dev, x, 128*value);        }    }  SEQ_DUMPBUF();}void control_change(int controller, int channel, int value){int x;  if (controller == CTL_MAIN_VOLUME)    {    chanvol[channel] = value;    value = value * volscale / 100;    }#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    SEQ_CONTROL(seq_dev, channel, controller, value);  }  else#endif  if (use_dev == EXT_MIDI)    {    SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + channel);    SEQ_MIDIOUT(seq_dev, controller);    SEQ_MIDIOUT(seq_dev, value);    }  else    {    for (x = 0; x < sinfo[seq_dev].nr_voices; x++)      if ((voices[x].channel == channel) && (controller == CTL_MAIN_VOLUME))          SEQ_MAIN_VOLUME(seq_dev, x, value);    }  SEQ_DUMPBUF();}void patch_change(int patch, int channel){int x;#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    SEQ_SET_PATCH(seq_dev, channel, patch);  }  else#endif  if (use_dev == EXT_MIDI)    {    SEQ_MIDIOUT(seq_dev, MIDI_PGM_CHANGE + channel);    SEQ_MIDIOUT(seq_dev, patch);    }  else    {    for (x = 0; x < sinfo[seq_dev].nr_voices; x++)      if (((voices[x].channel == -1) && (voices[x].note == -1)) || (voices[x].channel == channel))	{        synth_patches[channel] = patch;	break;	}    }  SEQ_DUMPBUF();}void midi_wait(float time){  ioctl(seqfd, SNDCTL_SEQ_SYNC);  SEQ_WAIT_TIME((int) time);  SEQ_DUMPBUF();}void midi_timer(int action){  switch (action)    {    case 0:      SEQ_START_TIMER();      break;    case 1:      SEQ_STOP_TIMER();      break;    case 2:      SEQ_CONTINUE_TIMER();      break;    }}void vol_change(int volume){int x; int logscale[32] = {0,15, 25,33, 40,45, 50,55, 59,62, 65,68, 70,73, 75,77, 79,81, 83,85, 87,89, 90,92, 93,94, 95,97, 98,99, 100,100};  volume = (volume < 0 ? 0 : (volume > 31 ? 31 : volume));  volscale = logscale[volume];#ifdef AWE32_SYNTH_SUPPORT  if (use_dev == AWE32_SYNTH)  {    for (x = 0; x < 16; x++)      SEQ_CONTROL(seq_dev, x, CTL_MAIN_VOLUME, chanvol[x] * volscale / 100);  }  else#endif  if (use_dev == EXT_MIDI)    {    for (x = 0; x < 16; x++)      {      SEQ_MIDIOUT(seq_dev, MIDI_CTL_CHANGE + x);      SEQ_MIDIOUT(seq_dev, CTL_MAIN_VOLUME);      SEQ_MIDIOUT(seq_dev, chanvol[x] * volscale / 100);      }    }  else    {    volume = volscale;    volume |= (volume << 8);    //if (-1 == ioctl(mixfd, SOUND_MIXER_WRITE_SYNTH, &volume))    //  perror("volume change");    ioctl(mixfd, SOUND_MIXER_WRITE_SYNTH, &volume);    ioctl(mixfd, SOUND_MIXER_WRITE_LINE2, &volume);    }  SEQ_DUMPBUF();}void fmload(void){int x;  for (x = 0; x < 175; x++)    {    fm_sbi[x].key = FM_PATCH;    fm_sbi[x].device = seq_dev;    fm_sbi[x].channel = x;    fm_sbi[x].operators[0] = fm_instruments[x].patchdata[0];    fm_sbi[x].operators[1] = fm_instruments[x].patchdata[7];    fm_sbi[x].operators[2] = fm_instruments[x].patchdata[4] + fm_instruments[x].patchdata[5];    fm_sbi[x].operators[3] = fm_instruments[x].patchdata[11] + fm_instruments[x].patchdata[12];    fm_sbi[x].operators[4] = fm_instruments[x].patchdata[1];    fm_sbi[x].operators[5] = fm_instruments[x].patchdata[8];    fm_sbi[x].operators[6] = fm_instruments[x].patchdata[2];    fm_sbi[x].operators[7] = fm_instruments[x].patchdata[9];    fm_sbi[x].operators[8] = fm_instruments[x].patchdata[3];    fm_sbi[x].operators[9] = fm_instruments[x].patchdata[10];    fm_sbi[x].operators[10] = fm_instruments[x].patchdata[6];    fm_sbi[x].operators[11] = fm_instruments[x].patchdata[16];    fm_sbi[x].operators[12] = fm_instruments[x].patchdata[23];    fm_sbi[x].operators[13] = fm_instruments[x].patchdata[20] + fm_instruments[x].patchdata[21];    fm_sbi[x].operators[14] = fm_instruments[x].patchdata[27] + fm_instruments[x].patchdata[28];    fm_sbi[x].operators[15] = fm_instruments[x].patchdata[17];    fm_sbi[x].operators[16] = fm_instruments[x].patchdata[24];    fm_sbi[x].operators[17] = fm_instruments[x].patchdata[18];    fm_sbi[x].operators[18] = fm_instruments[x].patchdata[25];    fm_sbi[x].operators[19] = fm_instruments[x].patchdata[19];    fm_sbi[x].operators[20] = fm_instruments[x].patchdata[26];    fm_sbi[x].operators[21] = fm_instruments[x].patchdata[22];    SEQ_WRPATCH(&fm_sbi[x], sizeof(fm_sbi[x]));    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -