/*************************************************************************** oss-adlib.c Copyright (C) 2001 Solomon Peachy, 03,04 Christoph Reichenbach This program may be modified and copied freely according to the terms of the GNU general public license (GPL), as long as the above copyright notice and the licensing information contained herein are preserved. Please refer to www.gnu.org for licensing details. This work is provided AS IS, without warranty of any kind, expressed or implied, including but not limited to the warranties of merchantibility, noninfringement, and fitness for a specific purpose. The author will not be held liable for any damage caused by this work or derivatives of it. By using this source code, you agree to the licensing terms as stated above. ***************************************************************************/ #include #ifdef HAVE_UNISTD_H # include #endif #include "../sequencer.h" #ifdef HAVE_SYS_SOUNDCARD_H #include "../adlib.h" #include #include #include #include /* for some MIDI information */ #if 1 SEQ_DEFINEBUF(2048); static int seqfd; #else extern unsigned char _seqbuf[2048]; extern int _seqbuflen; extern int _seqbufptr; extern int seqfd; #endif static guint8 instr[MIDI_CHANNELS]; static int dev; static int free_voices = ADLIB_VOICES; static long note_time[ADLIB_VOICES]; static unsigned char oper_note[ADLIB_VOICES]; static unsigned char oper_chn[ADLIB_VOICES]; #if 1 void seqbuf_dump(void) /* OSS upcall */ { if (_seqbufptr) if (write(seqfd, _seqbuf, _seqbufptr) == -1) { perror("ADLIB write "); exit(-1); } _seqbufptr = 0; } #endif /* initialise note/operator lists, etc. */ void adlib_init_lists(void) { int i; for(i = 0 ; i < ADLIB_VOICES ; i++) { oper_note[i] = 255; oper_chn[i] = 255; note_time[i] = 0; } free_voices = ADLIB_VOICES; } int adlib_stop_note(int chn, int note, int velocity) { int i, op=255; for (i=0;i= ADLIB_VOICES) { printf("Free list empty but no notes playing\n"); return 255; } /* No notes playing */ for (i = 0; i < ADLIB_VOICES ; i++) { if (oper_chn[i] != chn) continue; if (note_time[i] == 0) continue; if (time == 0) { time = note_time[i]; oldest = i; continue; } if (note_time[i] < time) { time = note_time[i]; oldest = i; } } /* printf("Killing chn %d, oper %d\n", chn, oldest); */ if (oldest == 255) return 255; /* Was already stopped. Why? */ SEQ_STOP_NOTE(dev, oldest, oper_note[oldest], 0); SEQ_DUMPBUF(); oper_chn[oldest] = 255; oper_note[oldest] = 255; note_time[oldest] = 0; free_voices++; return oldest; } static void adlib_start_note(int chn, int note, int velocity) { int free; struct timeval now; if (velocity == 0) { adlib_stop_note(chn, note, velocity); return; } gettimeofday(&now, NULL); if (free_voices <= 0) free = adlib_kill_one_note(chn); else for (free = 0; free < ADLIB_VOICES ; free++) if (oper_chn[free] == 255) break; /* printf("play operator %d/%d: %d %d %d\n", free, free_voices, chn, note, velocity); */ oper_chn[free] = chn; oper_note[free] = note; note_time[free] = now.tv_sec * 1000000 + now.tv_usec; free_voices--; SEQ_SET_PATCH(dev, free, instr[chn]); SEQ_START_NOTE(dev, free, note, velocity); SEQ_DUMPBUF(); } static int midi_adlib_open(int data_length, byte *data_ptr, int data2_length, byte *data2_ptr, void *seq) { int nrdevs, i, n; struct synth_info info; struct sbi_instrument sbi; if (data_length < 1344) { printf ("invalid patch.003"); return -1; } for (i = 0; i < 48; i++) make_sbi((adlib_def *)(data_ptr+(28 * i)), adlib_sbi[i]); if (data_length > 1344) for (i = 48; i < 96; i++) make_sbi((adlib_def *)(data_ptr+2+(28 * i)), adlib_sbi[i]); memset(instr, 0, sizeof(instr)); if (!IS_VALID_FD(seqfd=open("/dev/sequencer", O_WRONLY, 0))) { perror("/dev/sequencer"); return(-1); } if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrdevs) == -1) { perror("/dev/sequencer"); return(-1); } for (i=0;i 1) return midi_adlib_event1(command, argv[0], argv[1]); else return midi_adlib_event2(command, argv[0]); } static int midi_adlib_delay(int ticks) { SEQ_DELTA_TIME(ticks); return SFX_OK; } static int midi_adlib_set_option(char *name, char *value) { return SFX_ERROR; /* No options are supported at this time */ } /* the driver struct */ sfx_sequencer_t sfx_sequencer_oss_adlib = { "adlib", "0.1", SFX_DEVICE_NONE, /* No device dependancy-- fixme, this might become ossseq */ &midi_adlib_set_option, &midi_adlib_open, &midi_adlib_close, &midi_adlib_event, &midi_adlib_delay, NULL, &midi_adlib_allstop, NULL, &midi_adlib_reverb, 003, /* patch.003 */ SFX_SEQ_PATCHFILE_NONE, 0x04, /* playflag */ 0, /* do not play channel 9 */ ADLIB_VOICES, /* Max polyphony */ 0 /* Does not require any write-ahead by its own */ }; #endif /* HAVE_SYS_SOUNDCARD_H */