home *** CD-ROM | disk | FTP | other *** search
- From: brians@eecs.cs.pdx.edu (Brian Smith)
- Newsgroups: alt.sources
- Subject: Sound Blaster Unix Driver 2/2
- Message-ID: <2822@pdxgate.UUCP>
- Date: 6 Jun 91 17:22:05 GMT
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # apps/Makefile
- # apps/get_instr.1
- # apps/get_instr.c
- # apps/play_cleanup.1
- # apps/play_cleanup.c
- # apps/play_cmf.1
- # apps/play_cmf.c
- # apps/play_snd.1
- # apps/play_snd.c
- # apps/record_snd.1
- # apps/record_snd.c
- # apps/set_speed.1
- # apps/set_speed.c
- # apps/snd_norm.1
- # apps/snd_norm.c
- # apps/tst_fm_note.c
- # apps/tst_fm_open.c
- # apps/tst_instr.c
- # This archive created: Thu Jun 6 08:33:44 1991
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'apps/Makefile'
- then
- echo shar: "will not over-write existing file 'apps/Makefile'"
- else
- cat << \SHAR_EOF > 'apps/Makefile'
- #
- # Programs using Sound Blaster(tm) Driver
- # (Copyright 1991, Brian Smith)
- #
-
- SHELL=/bin/sh
- CC= gcc -fpcc-struct-return
- CFLAGS = # -O
- LIBS= -lc_s
-
- PROGRAMS= play_snd set_speed play_cmf record_snd snd_norm
- TESTS= play_cleanup tst_fm_open tst_fm_note get_instr tst_instr
-
- all: $(PROGRAMS) $(TESTS)
-
- record_snd: record_snd.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o record_snd record_snd.c $(LIBS)
-
- play_snd: play_snd.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o play_snd play_snd.c $(LIBS)
-
- play_cleanup: play_cleanup.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o play_cleanup play_cleanup.c $(LIBS)
-
- get_instr: get_instr.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o get_instr get_instr.c $(LIBS)
-
- set_speed: set_speed.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o set_speed set_speed.c $(LIBS)
-
- tst_fm_open: tst_fm_open.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o tst_fm_open tst_fm_open.c $(LIBS)
-
- tst_fm_note: tst_fm_note.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o tst_fm_note tst_fm_note.c $(LIBS)
-
- play_cmf: play_cmf.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o play_cmf play_cmf.c -linet $(LIBS)
-
- tst_instr: tst_instr.c /usr/include/sys/sb.h
- $(CC) $(CFLAGS) -o tst_instr tst_instr.c $(LIBS)
-
- snd_norm: snd_norm.c
- $(CC) $(CFLAGS) -o snd_norm snd_norm.c $(LIBS)
-
- install: $(PROGRAMS)
- for i in $(PROGRAMS); do \
- mcs -d $$i ; \
- strip $$i ; \
- (echo $$i | cpio -pdlmv /usr/local/bin) ; \
- done
-
- clean:
- /bin/rm -f $(PROGRAMS) $(TESTS)
- SHAR_EOF
- fi
- if test -f 'apps/get_instr.1'
- then
- echo shar: "will not over-write existing file 'apps/get_instr.1'"
- else
- cat << \SHAR_EOF > 'apps/get_instr.1'
- .TH GET_INSTR 1 "3 June 1991"
- .UC 4
- .SH NAME
- get_instr \- decodes and prints instrument info from CMF files
- .SH SYNOPSIS
- .B get_instr
- [
- .I file
- ]
- .PP
- The argument must be the CMF file to be examined.
- .SH DESCRIPTION
- .B get_instr
- reads the portion of the CMF file detailing the instruments used, and
- then prints out the breakdown of that information.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/get_instr.c'
- then
- echo shar: "will not over-write existing file 'apps/get_instr.c'"
- else
- cat << \SHAR_EOF > 'apps/get_instr.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/unistd.h>
- #include <sys/sb.h>
- #include <stdio.h>
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int cmf_fd;
-
- if (argc != 2)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* open cmf file */
- cmf_fd = open(argv[1], O_RDONLY);
- if (cmf_fd == -1)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* verify that file is a cmf file */
- if (!verify_cmf(cmf_fd))
- {
- printf("file was not a cmf file\n");
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* print out info on instruments in cmf file */
- print_instruments(cmf_fd);
-
- return(0);
- }
-
-
- /* check for "CTMF" in first four bytes of file */
- int verify_cmf(fd)
- int fd;
- {
- char idbuf[5];
-
- /* get id */
- lseek(fd, 0, SEEK_SET);
- if (read(fd, idbuf, 4) != 4)
- return(FALSE);
-
- /* compare to standard id */
- idbuf[4] = (char)0;
- if (strcmp(idbuf, "CTMF") != 0)
- return(FALSE);
-
- return(TRUE);
- }
-
- int print_instruments(fd)
- int fd;
- {
- int offset;
- int num_instruments;
- int i;
- int j;
- unsigned char tmp_byte;
- unsigned char instrument_buf[16];
-
- #define lobyte(X) (((unsigned char *)&X)[0])
- #define hibyte(X) (((unsigned char *)&X)[1])
-
- /* get offset of instrument block */
- offset = 0;
- lseek(fd, 0x06, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(offset) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(offset) = tmp_byte;
-
- /* get number of instruments */
- num_instruments = 0;
- lseek(fd, 0x24, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(num_instruments) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(num_instruments) = tmp_byte;
-
- /* read each instrument */
- lseek(fd, offset, SEEK_SET);
- for (i=0; i< num_instruments; i++)
- {
- read(fd, instrument_buf, 16);
- printf("instrument: 0x%02x\n", i);
-
- for (j=0; j<16; j++)
- printf("0x%02x ", (unsigned int)instrument_buf[j]);
- printf("\n");
-
- /* byte 0 */
- printf("\tModulator: 0x%02x\n", (unsigned int)instrument_buf[0]);
-
- /* byte 1 */
- printf("\tCarrier Sound Characteristic\n");
- if (instrument_buf[1] & (1<<7))
- printf("\tPitch Vibrato: On\n");
- else
- printf("\tPitch Vibrato: Off\n");
- if (instrument_buf[1] & (1<<6))
- printf("\tAmplitude Vibrato: On\n");
- else
- printf("\tAmplitude Vibrato: Off\n");
- if (instrument_buf[1] & (1<<5))
- printf("\tSustaining Sound: On\n");
- else
- printf("\tSustaining Sound: Off\n");
- if (instrument_buf[1] & (1<<4))
- printf("\tEnvelope Scaling: On\n");
- else
- printf("\tEnvelope Scaling: Off\n");
- printf("\tFrequency Multiplier: 0x%02x\n", instrument_buf[1] & 0x0F);
-
- /* byte 2 */
- printf("\tModulator Level Scaling: 0x%02x\n", instrument_buf[2] >> 4);
- printf("\tModulator Output Level: 0x%02x\n", instrument_buf[2] & 0x3f);
-
- /* byte 3 */
- printf("\tCarrier Level Scaling: 0x%02x\n", instrument_buf[3] >> 4);
- printf("\tCarrier Output Level: 0x%02x\n", instrument_buf[3] & 0x3f);
-
- /* byte 4 */
- printf("\tModulator Attack Rate 0x%02x\n", instrument_buf[5] >> 4);
- printf("\tModulator Decay Rate 0x%02x\n", instrument_buf[5] & 0xF);
-
- /* byte 5 */
- printf("\tCarrier Attack Rate 0x%02x\n", instrument_buf[5] >> 4);
- printf("\tCarrier Decay Rate 0x%02x\n", instrument_buf[5] & 0xF);
-
- /* byte 6 */
- printf("\tModulator Sustain Level 0x%02x\n", instrument_buf[6] >> 4);
- printf("\tModulator Release Level 0x%02x\n", instrument_buf[6] >> 4);
-
- /* byte 7 */
- printf("\tCarrier Sustain Level 0x%02x\n", instrument_buf[7] >> 4);
- printf("\tCarrier Release Level 0x%02x\n", instrument_buf[7] >> 4);
-
- /* byte 8 */
- printf("\tModulator Wave Select 0x%02x\n", instrument_buf[8] & 0x03);
-
- /* byte 9 */
- printf("\tCarrier Wave Select 0x%02x\n", instrument_buf[9] & 0x03);
-
- /* byte A */
- printf("\tModulator FeedBack 0x%02x\n",
- (instrument_buf[0xA] >> 1) & 0x07);
- }
-
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/play_cleanup.1'
- then
- echo shar: "will not over-write existing file 'apps/play_cleanup.1'"
- else
- cat << \SHAR_EOF > 'apps/play_cleanup.1'
- .TH PLAY_CLEANUP 1 "3 June 1991"
- .UC 4
- .SH NAME
- play_cleanup \- Cleans up after a very abnormal exit from play_snd
- .SH SYNOPSIS
- .B play_cleanup
- .PP
- No arguments are necessary.
- .SH DESCRIPTION
- If play_snd exits without destroying the shared memory segment,
- further invocations will fail until the segment is destroyed. This
- program destroys that memory segment. This should not be needed,
- because play_snd cleans up after getting eof and SIGINT. It cannot,
- however, catch SIGKILL.
- .B play_cleanup
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/play_cleanup.c'
- then
- echo shar: "will not over-write existing file 'apps/play_cleanup.c'"
- else
- cat << \SHAR_EOF > 'apps/play_cleanup.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
-
- #define NUMBUFS 2
- #define SHM_BUFSIZ (8*4096)
- #define SHM_KEY 1796
-
- typedef struct {
- int not_last_segment[NUMBUFS];
- int unlocked[NUMBUFS];
- char buf[NUMBUFS*SHM_BUFSIZ];
- } buf_struct;
-
-
- main()
- {
- int rc;
- int shmid;
-
- shmid = shmget(SHM_KEY, sizeof(buf_struct), IPC_CREAT | 0644);
- if (shmid == -1)
- {
- perror("creating shared-mem buffer");
- exit(-1);
- }
-
- rc = shmctl(shmid, IPC_RMID, 0);
- if (rc == -1)
- perror("removing segment");
-
- exit(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/play_cmf.1'
- then
- echo shar: "will not over-write existing file 'apps/play_cmf.1'"
- else
- cat << \SHAR_EOF > 'apps/play_cmf.1'
- .TH PLAY_CMF 1 "3 June 1991"
- .UC 4
- .SH NAME
- play_cmf \- decodes and plays a CMF music file.
- .SH SYNOPSIS
- .B play_cmf
- [
- .I file
- ]
- .PP
- The argument must be the CMF file to be played.
- .SH DESCRIPTION
- .B play_cmf
- Attempts to play a CMF file.
- .SH BUGS
- Many CMF files attempt to use Control Change events not understood by the
- author. Therefore, the program does not implement whatever these
- control changes are supposed to do.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/play_cmf.c'
- then
- echo shar: "will not over-write existing file 'apps/play_cmf.c'"
- else
- cat << \SHAR_EOF > 'apps/play_cmf.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/unistd.h>
- #include <sys/sb.h>
- #include <sys/time.h>
- #include <stdio.h>
-
- #define lobyte(X) (((unsigned char *)&X)[0])
- #define hibyte(X) (((unsigned char *)&X)[1])
-
- /* Globals */
- int fm_herz; /* clock ticks per second */
- int tempo; /* clock ticks per quarter note */
- int fm_fd;
- int note_on[16];
- char **instrument_table;
- int note_table[12] = {
- 343,
- 363,
- 385,
- 408,
- 432,
- 458,
- 485,
- 514,
- 544,
- 577,
- 611,
- 647
- };
-
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int cmf_fd;
-
- if (argc != 2)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* open cmf file */
- cmf_fd = open(argv[1], O_RDONLY);
- if (cmf_fd == -1)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* verify that file is a cmf file */
- if (!verify_cmf(cmf_fd))
- {
- printf("file was not a cmf file\n");
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* read and set instruments from cmf file */
- get_instruments(cmf_fd);
-
- /* get timing */
- set_timing(cmf_fd);
-
- /* open soundblaster fm chips */
- fm_fd = open("/dev/sbfm", O_WRONLY);
- if (fm_fd == -1)
- {
- perror("opening fm chips");
- exit(-1);
- }
-
- /* play song */
- play_song(cmf_fd);
-
- return(0);
- }
-
-
- /* check for "CTMF" in first four bytes of file */
- int verify_cmf(fd)
- int fd;
- {
- char idbuf[5];
-
- /* get id */
- lseek(fd, 0, SEEK_SET);
- if (read(fd, idbuf, 4) != 4)
- return(FALSE);
-
- /* compare to standard id */
- idbuf[4] = (char)0;
- if (strcmp(idbuf, "CTMF") != 0)
- return(FALSE);
-
- return(TRUE);
- }
-
- int get_instruments(fd)
- int fd;
- {
- int offset;
- int num_instruments;
- int i;
- int rc;
- int fnum, block, note;
- unsigned char tmp_byte;
- sb_fm_character note_character;
-
- /* get offset of instrument block */
- offset = 0;
- lseek(fd, 0x06, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(offset) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(offset) = tmp_byte;
-
- /* get number of instruments */
- num_instruments = 0;
- lseek(fd, 0x24, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(num_instruments) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(num_instruments) = tmp_byte;
-
- /* allocate space */
- instrument_table = (char **)malloc(sizeof(int *) * num_instruments);
-
- /* read each instrument */
- lseek(fd, offset, SEEK_SET);
- for (i=0; i< num_instruments; i++)
- {
- /* allocate space */
- instrument_table[i] = (char *)malloc(16);
-
- /* set instrument characteristics */
- read(fd, instrument_table[i], 16);
- }
-
- return(0);
- }
-
-
- /*
- * get and set timing parameters
- */
- int set_timing(fd)
- int fd;
- {
- unsigned char tmp_byte;
-
- /* get tempo */
- tempo = 0;
- lseek(fd, 0x0C, SEEK_SET);
- read(fd, &tmp_byte, 1);
- tempo = (unsigned int)tmp_byte;
- read(fd, &tmp_byte, 1);
- tempo += (unsigned int)tmp_byte << 8;
-
- /* get herz of timing clock */
- fm_herz = 0;
- lseek(fd, 0x0C, SEEK_SET);
- read(fd, &tmp_byte, 1);
- fm_herz = (unsigned int)tmp_byte;
- read(fd, &tmp_byte, 1);
- fm_herz += (unsigned int)tmp_byte << 8;
-
- return(0);
- }
-
-
- /*
- * seek to the midi stream and handle midi events for the song
- */
- int play_song(fd)
- int fd;
- {
- int offset;
- unsigned char tmp_byte;
- int delta;
-
- /* get offset of music stream */
- lseek(fd, 8, SEEK_SET);
- read(fd, &tmp_byte, 1);
- offset = (unsigned int)tmp_byte;
- read(fd, &tmp_byte, 1);
- offset += (unsigned int)tmp_byte << 8;
- lseek(fd, offset, SEEK_SET);
-
- /* process till EOF */
- while(1)
- {
- /* get delta time */
- delta = ReadVarLen(fd);
- if (delta == -1)
- break;
-
- /* wait delta */
- if (delta > 0)
- high_res_sleep((double)delta/(double)fm_herz);
-
- /* process midi event */
- process_event(fd, delta);
- }
-
-
- return(0);
- }
-
-
- /*
- * read a variable length scalar in MIDI format
- */
- int ReadVarLen(fd)
- int fd;
- {
- int value;
- unsigned char tmp_byte;
-
- if (read(fd, &tmp_byte, 1) == 0)
- return(-1);
- value = (int)tmp_byte;
- if (tmp_byte & 0x80)
- {
- value &= 0x7F;
- do
- {
- if (read(fd, &tmp_byte, 1) == 0)
- return(-1);
- value = (value << 7) + (tmp_byte & 0x7F);
- } while (tmp_byte & 0x80);
- }
-
- return(value);
- }
-
-
- /*
- * process a midi event
- */
- int process_event(fd, delta)
- int fd;
- {
- int rc;
- unsigned char tmp_byte;
- static int status = -1;
- sb_fm_note note;
-
- /* get status byte */
- read(fd, &tmp_byte, 1);
- if (tmp_byte & 0x80)
- {
- status = (unsigned int)tmp_byte;
- }
- else
- {
- /* running status, so back up one */
- if (status == -1)
- {
- printf("ERROR in cmf file. Running status at beginning of file\n");
- exit(-1);
- }
- lseek(fd, -1, SEEK_CUR);
- }
-
- /* switch different events */
- switch (status & 0xF0)
- {
- case 0x80:
- /* turn note off */
- ioctl(fm_fd, FM_IOCTL_NOTE_OFF, status & 0x0F);
- note_on[status&0x0F] = 0;
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- case 0x90:
- /* get note */
- read(fd, &tmp_byte, 1);
- /* determine note */
- note_num(note) = status & 0x0F;
- fnum_low(note) = note_table[tmp_byte%12] & 0xFF;
- fnum_low(note) = note_table[tmp_byte%12] & 0xFF;
- keyon_blk_fnum(note) = 0;
- keyon_blk_fnum(note) |= 1<<5;
- keyon_blk_fnum(note) |= ((tmp_byte/12) & 7) << 2;
- keyon_blk_fnum(note) |= (note_table[tmp_byte%12] & 0x3FF) >> 8;
-
- /* turn note on */
- if (note_on[status&0x0F])
- ioctl(fm_fd, FM_IOCTL_NOTE_OFF, status&0x0F);
- ioctl(fm_fd, FM_IOCTL_NOTE_ON, note);
- note_on[status&0x0F] = 1;
-
- /* waste a bytes */
- read(fd, &tmp_byte, 1);
- break;
- case 0xA0:
- printf("polyphonic key pressure: not handled\n");
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- case 0xB0:
- printf("control change: not handled\n");
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- case 0xC0:
- /* change the instrument on a channel */
- read(fd, &tmp_byte, 1);
- load_instrument(status&0x0F, tmp_byte & 0x0F);
- break;
- case 0xD0:
- printf("Channel Pressure: not handled\n");
- /* waste a byte */
- read(fd, &tmp_byte, 1);
- break;
- case 0xE0:
- printf("Pitch Wheel Change: not handled\n");
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- case 0xF0:
- printf("System Exclusive: not handled\n");
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- default:
- printf("internal program error\n");
- /* waste two bytes */
- read(fd, &tmp_byte, 1);
- read(fd, &tmp_byte, 1);
- break;
- }
-
-
- return(0);
- }
-
-
- /*
- * load an instrument from the instrument table into the SoundBlaster
- */
- int load_instrument(channel, instrument)
- {
- int rc;
- sb_fm_character note_character;
-
- /* error check! */
- if ((channel <0) || (channel >= 9))
- return;
-
- /* abort instrument if being loaded */
- if (note_on[channel])
- ioctl(fm_fd, FM_IOCTL_NOTE_OFF, channel);
-
- /* set instrument characteristics */
- note_character.voice_num = channel;
- memcpy(note_character.data, instrument_table[instrument], 16);
- rc = ioctl(fm_fd, FM_IOCTL_SET_VOICE, (int)¬e_character);
- if (rc == -1)
- {
- perror("fm chips voice set");
- exit(-1);
- }
-
- return(0);
- }
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- Higher-resolution sleep
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- int high_res_sleep(seconds)
- double seconds;
- {
- int fds = 0;
- struct timeval timeout;
-
- timeout.tv_sec = seconds;
- timeout.tv_usec = (seconds - timeout.tv_sec) * 1000000.0;
- select(0, &fds, &fds, &fds, &timeout);
- }
-
- SHAR_EOF
- fi
- if test -f 'apps/play_snd.1'
- then
- echo shar: "will not over-write existing file 'apps/play_snd.1'"
- else
- cat << \SHAR_EOF > 'apps/play_snd.1'
- .TH PLAY_SND 1 "3 June 1991"
- .UC 4
- .SH NAME
- play_snd \- plays a raw 8-bit sound file
- .SH SYNOPSIS
- .B play_snd
- [
- .I file
- ]
- .PP
- The argument must be the sound file to be played.
- .SH DESCRIPTION
- .B play_snd
- Plays raw 8-bit sound files, using shared memory and two processes
- to double buffer reads and writes. Feel free to use SIGINT (usually
- control-C) to interrupt the play. Do NOT, however, use SIGKILL or any
- other signal to terminate the program. This leaves unwanted
- left-overs, in the form of a shared memory segment. Use play_cleanup
- if this happens accidentally.
-
- Use set_speed to change the playing rate of the samples.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/play_snd.c'
- then
- echo shar: "will not over-write existing file 'apps/play_snd.c'"
- else
- cat << \SHAR_EOF > 'apps/play_snd.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/sb.h>
- #include <signal.h>
- #include <errno.h>
- #include <stdio.h>
-
- #define NUMBUFS 4
- #define SHM_BUFSIZ (8*4096)
- #define SHM_KEY 1796
-
- typedef struct {
- char buf[NUMBUFS*SHM_BUFSIZ];
- int write_waiting;
- int read_waiting;
- int locked[NUMBUFS];
- int length[NUMBUFS];
- } buf_struct;
-
-
- /* GLOBALS */
- int shmid;
- buf_struct *buffers;
- int sound_fd;
-
- void sigusr_handler()
- {
- return;
- }
-
-
- void cleanup()
- {
- shmctl(shmid, IPC_RMID, 0);
- exit(0);
- }
-
- void detach()
- {
- shmdt(buffers);
- exit(0);
- }
-
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int infile;
- int child_pid;
- int buf_num;
- int rc;
-
- if (argc != 2)
- {
- printf("usage: %s <sound file>\n", argv[0]);
- printf("\tif <sound file> is \"-\", then %s will play from stdin\n",
- argv[0]);
- exit(-1);
- }
-
- if (strcmp(argv[1], "-") == 0)
- infile = 0;
- else
- {
- infile = open(argv[1], O_RDONLY);
- if (infile == -1)
- {
- perror("opening data file");
- printf("usage: %s <sound file>\n", argv[0]);
- printf("\tif <sound file> is \"-\", then %s will play from stdin\n",
- argv[0]);
- exit(-1);
- }
- }
-
- /* open device */
- sound_fd = open("/dev/sbdsp", O_WRONLY);
- if (sound_fd == -1)
- {
- perror("opening SoundBlaster device");
- exit(-1);
- }
-
- /* create shared memory segment */
- shmid = shmget(SHM_KEY, sizeof(buf_struct), IPC_CREAT | IPC_EXCL | 0644);
- if (shmid == -1)
- {
- perror("creating shared-mem buffer");
- exit(-1);
- }
-
- /* attach handler for signal */
- sigset(SIGUSR1, sigusr_handler);
- sigset(SIGINT, cleanup);
- sigset(SIGHUP, cleanup);
-
- /* start read process */
- child_pid = fork();
- switch (child_pid)
- {
- case 0:
- start_read(infile);
- exit(0);
- case -1:
- perror("forking reader process");
- cleanup();
- }
-
- /* attach shared memory segment */
- buffers = (buf_struct *)shmat(shmid, 0, 0);
- if (buffers == (buf_struct *)-1)
- {
- perror("attaching shared memory");
- if (buffers->read_waiting)
- kill(child_pid, SIGKILL);
- cleanup();
- }
-
- /* start writing stuff in buffers */
- while(1)
- {
- /* wait until buffer is locked for us, or flush and break on eof */
- if (!buffers->locked[buf_num])
- {
- buffers->write_waiting = 1;
- sigpause(SIGUSR1);
- continue;
- }
-
- /* not waiting now */
- buffers->write_waiting = 0;
-
- /* eof check */
- if (buffers->length[buf_num] <= 0)
- break;
-
- /* write out data in buffer */
- rc = write(sound_fd, buffers->buf + (buf_num*SHM_BUFSIZ),
- buffers->length[buf_num]);
- if (rc != buffers->length[buf_num])
- {
- if ((errno == EINTR) || (errno == 0))
- continue;
-
- perror("writing to sound blaster");
- kill(child_pid, SIGKILL);
- cleanup();
- }
-
- /* unlock buffer for child's use */
- buffers->locked[buf_num] = 0;
- if (buffers->read_waiting)
- kill(child_pid, SIGUSR1);
-
- /* go to next buffer */
- buf_num++;
- buf_num %= NUMBUFS;
- }
-
-
- cleanup();
- return(0);
- }
-
- int start_read(infile)
- int infile;
- {
- buf_struct *buffers;
- int buf_num = 0;
-
- /* attach handler for signal */
- sigset(SIGUSR1, sigusr_handler);
- sigset(SIGINT, detach);
- sigset(SIGHUP, detach);
-
- /* attach shared memory */
- buffers = (buf_struct *)shmat(shmid, 0, 0);
- if (buffers == (buf_struct *)-1)
- {
- perror("attaching shared memory");
- exit(0);
- }
-
- /* init shared mem stuff */
- buffers->read_waiting = 0;
- for (buf_num=0; buf_num < NUMBUFS; buf_num++)
- buffers->locked[buf_num] = 0;
-
- /* start reading into buffers */
- buf_num = 0;
- sleep(1);
- while(1)
- {
- /* wait for current buffer to become unlocked */
- if (buffers->locked[buf_num])
- {
- buffers->read_waiting = 1;
- sigpause(SIGUSR1);
- continue;
- }
-
- /* not waiting any more */
- buffers->read_waiting = 0;
-
- /* actually read data */
- buffers->length[buf_num] =
- read(infile, buffers->buf + (buf_num*SHM_BUFSIZ), SHM_BUFSIZ);
- if (buffers->length[buf_num] == -1)
- {
- if (errno == EINTR)
- continue;
- else
- {
- perror("reading from input file\n");
- detach();
- }
- }
- else if (buffers->length[buf_num] == 0)
- {
- buffers->locked[buf_num] = 1;
-
- /* wake up parent */
- if (buffers->write_waiting)
- kill(getppid(), SIGUSR1);
-
- break;
- }
-
- /* lock buffer for parent's use */
- buffers->locked[buf_num] = 1;
-
- /* wake up parent */
- if (buffers->write_waiting)
- kill(getppid(), SIGUSR1);
-
- /* go to next buffer */
- buf_num++;
- buf_num %= NUMBUFS;
- }
-
-
- /* wake up parent */
- if (buffers->write_waiting)
- kill(getppid(), SIGUSR1);
-
- /* detach shared memory */
- shmdt(buffers);
-
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/record_snd.1'
- then
- echo shar: "will not over-write existing file 'apps/record_snd.1'"
- else
- cat << \SHAR_EOF > 'apps/record_snd.1'
- .TH RECORD_SND 1 "3 June 1991"
- .UC 4
- .SH NAME
- record_snd \- records a raw 8-bit sound file
- .SH SYNOPSIS
- .B record_snd
- [
- .I file
- ]
- .PP
- The argument must be the sound file to contain the recording.
- .SH DESCRIPTION
- .B record_snd
- Records raw 8-bit sound files, using shared memory and two processes
- to double buffer reads and writes. Use SIGINT (usually control-C) to
- stop the recording. Do NOT, however, use SIGKILL or any other signal
- to terminate the program. This leaves unwanted left-overs, in the
- form of a shared memory segment. Use play_cleanup if this happens
- accidentally.
-
- Use set_speed to change the recording rate of the samples.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/record_snd.c'
- then
- echo shar: "will not over-write existing file 'apps/record_snd.c'"
- else
- cat << \SHAR_EOF > 'apps/record_snd.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/sb.h>
- #include <signal.h>
- #include <errno.h>
- #include <stdio.h>
-
- #define NUMBUFS 4
- #define SHM_BUFSIZ (8*4096)
- #define SHM_KEY 1796
-
- typedef struct {
- char buf[NUMBUFS*SHM_BUFSIZ];
- int write_waiting;
- int read_waiting;
- int locked[NUMBUFS];
- int length[NUMBUFS];
- } buf_struct;
-
-
- /* GLOBALS */
- int shmid;
- buf_struct *buffers;
-
- void sigusr_handler()
- {
- return;
- }
-
-
- void cleanup()
- {
- printf("cleanup\n");
- shmctl(shmid, IPC_RMID, 0);
- exit(0);
- }
-
- void detach()
- {
- printf("detaching\n");
- shmdt(buffers);
- exit(0);
- }
-
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int outfile;
- int sound_fd;
- int child_pid;
- int buf_num;
- int rc;
-
- if (argc != 2)
- {
- printf("usage: %s <new sound file>\n", argv[0]);
- printf("\tif <sound file> is \"-\", then %s will record to stdout\n",
- argv[0]);
- exit(-1);
- }
-
- if (strcmp(argv[1], "-") == 0)
- outfile = 1;
- else
- {
- outfile = open(argv[1], O_WRONLY | O_CREAT, 0666);
- if (outfile == -1)
- {
- perror("opening output file");
- printf("usage: %s <output sound file>\n", argv[0]);
- printf("\tif <sound file> is \"-\", %s will record to stdout\n",
- argv[0]);
- exit(-1);
- }
- }
-
- /* open device */
- sound_fd = open("/dev/sbdsp", O_RDONLY);
- if (sound_fd == -1)
- {
- perror("opening SoundBlaster device");
- exit(-1);
- }
- if (ioctl(sound_fd, DSP_IOCTL_RESET) == -1)
- {
- perror("trying to reset DSP");
- exit(-1);
- }
- if (ioctl(sound_fd, DSP_IOCTL_VOICE, 0) == -1)
- {
- perror("trying to set voice on");
- exit(-1);
- }
-
- /* create shared memory segment */
- shmid = shmget(SHM_KEY, sizeof(buf_struct), IPC_CREAT | IPC_EXCL | 0644);
- if (shmid == -1)
- {
- perror("creating shared-mem buffer");
- exit(-1);
- }
-
- /* attach handler for signal */
- sigset(SIGUSR1, sigusr_handler);
- sigset(SIGINT, cleanup);
- sigset(SIGHUP, cleanup);
-
- /* start read process */
- child_pid = fork();
- switch (child_pid)
- {
- case 0:
- start_read(sound_fd);
- exit(0);
- case -1:
- perror("forking read process");
- cleanup();
- }
-
- /* attach shared memory segment */
- buffers = (buf_struct *)shmat(shmid, 0, 0);
- if (buffers == (buf_struct *)-1)
- {
- perror("attaching shared memory");
- if (buffers->read_waiting)
- kill(child_pid, SIGKILL);
- cleanup();
- }
-
- /* start writing stuff from buffers */
- while(1)
- {
- /* wait until buffer is locked for us, or flush and break on eof */
- if (!buffers->locked[buf_num])
- {
- buffers->write_waiting = 1;
- sigpause(SIGUSR1);
- continue;
- }
-
- /* not waiting now */
- buffers->write_waiting = 0;
-
- /* eof check */
- if (buffers->length[buf_num] <= 0)
- break;
-
- /* write out data in buffer */
- rc = write(outfile, buffers->buf + (buf_num*SHM_BUFSIZ),
- buffers->length[buf_num]);
- if (rc != buffers->length[buf_num])
- {
- if ((errno == EINTR) || (errno == 0))
- continue;
-
- perror("writing to output file");
- kill(child_pid, SIGKILL);
- cleanup();
- }
-
- /* unlock buffer for child's use */
- buffers->locked[buf_num] = 0;
- if (buffers->read_waiting)
- kill(child_pid, SIGUSR1);
-
- /* go to next buffer */
- buf_num++;
- buf_num %= NUMBUFS;
- }
-
-
- printf("done\n");
- cleanup();
- return(0);
- }
-
- int start_read(sound_fd)
- int sound_fd;
- {
- buf_struct *buffers;
- int buf_num = 0;
-
- /* attach handler for signal */
- sigset(SIGUSR1, sigusr_handler);
- sigset(SIGINT, detach);
- sigset(SIGHUP, detach);
-
- /* attach shared memory */
- buffers = (buf_struct *)shmat(shmid, 0, 0);
- if (buffers == (buf_struct *)-1)
- {
- perror("attaching shared memory");
- exit(0);
- }
-
- for (buf_num=0; buf_num < NUMBUFS; buf_num++)
- buffers->locked[buf_num] = 0;
-
- /* start reading into buffers */
- buf_num = 0;
- sleep(1);
- while(1)
- {
- /* wait for current buffer to become unlocked */
- if (buffers->locked[buf_num])
- {
- buffers->read_waiting = 1;
- sigpause(SIGUSR1);
- continue;
- }
-
- /* not waiting any more */
- buffers->read_waiting = 1;
-
- /* actually read data */
- buffers->length[buf_num] =
- read(sound_fd, buffers->buf + (buf_num*SHM_BUFSIZ), SHM_BUFSIZ);
- if (buffers->length[buf_num] == -1)
- {
- if (errno == EINTR)
- continue;
- else
- {
- perror("reading from SoundBlaster\n");
- detach();
- }
- }
- else if (buffers->length[buf_num] == 0)
- {
- buffers->locked[buf_num] = 1;
-
- /* wake up parent */
- if (buffers->write_waiting)
- kill(getppid(), SIGUSR1);
-
- break;
- }
-
- /* lock buffer for parent's use */
- buffers->locked[buf_num] = 1;
-
- /* wake up parent */
- if (buffers->write_waiting)
- kill(getppid(), SIGUSR1);
-
- /* go to next buffer */
- buf_num++;
- buf_num %= NUMBUFS;
- }
-
-
- /* wake up parent */
- kill(getppid(), SIGUSR1);
-
- /* detach shared memory */
- shmdt(buffers);
-
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/set_speed.1'
- then
- echo shar: "will not over-write existing file 'apps/set_speed.1'"
- else
- cat << \SHAR_EOF > 'apps/set_speed.1'
- .TH SET_SPEED 1 "3 June 1991"
- .UC 4
- .SH NAME
- set_speed \- changes the speed of recording and playing on Sound
- Blaster
- .SH SYNOPSIS
- .B set_speed
- ]
- .I speed
- ]
- .PP
- The argument must be the speed (in HZ) for sampling or playing.
- .SH DESCRIPTION
- .B set_speed
- Sets the speed of the sampling and playing of the Sound Blaster
- driver. The speed must be greater than (or equal) to 4000Hz, and less
- than 24000Hz. Speeds in excess of 13000Hz will be truncated to
- approximately 13000Hz by any recording.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/set_speed.c'
- then
- echo shar: "will not over-write existing file 'apps/set_speed.c'"
- else
- cat << \SHAR_EOF > 'apps/set_speed.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/sb.h>
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int fd;
- int speed;
-
- if (argc != 2)
- {
- printf("usage: %s <speed>\n", argv[0]);
- exit(-1);
- }
- speed = atoi(argv[1]);
- if ((speed < 4000) || (speed > 24000))
- {
- printf("usage: %s <speed>\n", argv[0]);
- printf("\tspeed must be between 4000 and 24000");
- exit(-1);
- }
-
- fd = open("/dev/sbdsp", O_RDONLY);
- if (fd == -1)
- {
- perror("opening SoundBlaster");
- exit(-1);
- }
-
- ioctl(fd, DSP_IOCTL_SPEED, speed);
-
- exit(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/snd_norm.1'
- then
- echo shar: "will not over-write existing file 'apps/snd_norm.1'"
- else
- cat << \SHAR_EOF > 'apps/snd_norm.1'
- .TH SND_NORM 1 "3 June 1991"
- .UC 4
- .SH NAME
- snd_norm \- normalizes a sound file
- .SH SYNOPSIS
- .B snd_norm
- [
- .I old file
- ]
- [
- .I new file
- ]
- .PP
- The arguments are the input and output of the normalization.
- .SH DESCRIPTION
- .B snd_norm
- The input file is normalized, such that the larget amplitude 127, thus
- obtaining the larget volume from a file (for a given volume setting on
- the actual Sound Blaster). Usefull for post-processing recordings
- which are barely audible.
- .SH AUTHOR
- .PP
- Brian Smith
- SHAR_EOF
- fi
- if test -f 'apps/snd_norm.c'
- then
- echo shar: "will not over-write existing file 'apps/snd_norm.c'"
- else
- cat << \SHAR_EOF > 'apps/snd_norm.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <stdio.h>
- #include <sys/fcntl.h>
- #include <sys/unistd.h>
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int fd, new_fd, rc, max_wave;
- unsigned char tmp_byte;
- int tmp_int;
- int i;
- double augmentation;
-
- if (argc != 3)
- {
- printf("usage: %s <oldfile> <newfile>\n", argv[0]);
- exit(-1);
- }
-
- fd = open(argv[1], O_RDONLY);
- if (fd == -1)
- {
- perror("opening oldfile");
- exit(-1);
- }
-
- new_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
- if (new_fd == -1)
- {
- perror("opening newfile");
- exit(-1);
- }
-
- printf("normalizing from input file..");
- fflush(stdout);
- i = 0;
- max_wave = 0;
- while(1)
- {
- i++ ; i &= 0x7FFF;
- if (!i)
- write(1, ".", 1);
-
- rc = read(fd, &tmp_byte, 1);
- if (rc == 0)
- break;
- tmp_int = tmp_byte - 128;
- if (abs(tmp_int) > max_wave)
- max_wave = abs(tmp_int);
- }
- write(1, "\n", 1);
-
- augmentation = (double)0x80 / (double)max_wave;
- printf("max_wave\t%d\n", max_wave);
- printf("augmentation\t%f\n", augmentation);
-
-
- /* write out new file */
- lseek(fd, 0, SEEK_SET);
- while (1)
- {
- rc = read(fd, &tmp_byte, 1);
- if (rc == 0)
- break;
-
- tmp_int = tmp_byte - 128;
- tmp_int *= augmentation;
- tmp_int += 128;
-
- tmp_byte = tmp_int;
-
- rc = write(new_fd, &tmp_byte, 1);
- if (rc != 1)
- {
- perror("writing to new_fd");
- exit(-1);
- }
- }
-
-
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/tst_fm_note.c'
- then
- echo shar: "will not over-write existing file 'apps/tst_fm_note.c'"
- else
- cat << \SHAR_EOF > 'apps/tst_fm_note.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/signal.h>
- #include <sys/sb.h>
- #include <stdio.h>
- #include <memory.h>
-
- void handler()
- {
- return;
- }
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int fd;
- int rc;
- int i;
- int note;
- int fnum;
- int block;
- static unsigned char instrument_buf[16] = {
- 0x11, 0x01, 0x8a, 0x40,
- 0xf1, 0xf1, 0x11, 0xb3,
- 0x00, 0x00, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- sb_fm_character note_character;
-
- sigset(SIGINT, handler);
-
- fd = open("/dev/sbfm", O_WRONLY);
- if (fd == -1)
- {
- perror("opening fm device");
- return(-1);
- }
-
- /* test reset */
- rc = ioctl(fd, FM_IOCTL_RESET);
- if (rc == -1)
- {
- perror("fm chips reset");
- exit(-1);
- }
-
- /* test setting an instrument */
- for (i=0 ; i<9; i++)
- {
- /* set instrument characteristics */
- note_character.voice_num = i;
- memset(note_character.data, (char)0, 16);
- memcpy(note_character.data, instrument_buf, 16);
- rc = ioctl(fd, FM_IOCTL_SET_VOICE, (int)¬e_character);
- if (rc == -1)
- {
- perror("fm chips voice set");
- exit(-1);
- }
-
- /* set note to play */
- fnum = 686;
- block = i;
- note_num(note) = i;
- fnum_low(note) = fnum & 0xFF;
- keyon_blk_fnum(note) = 0;
- keyon_blk_fnum(note) |= 1<<5; /* KEYON bit */
- keyon_blk_fnum(note) |= (block & 7) << 2; /* block/octave */
- keyon_blk_fnum(note) |= (fnum & 0x3FF) >> 8; /* top 2 bits of fnum */
-
- /* test note on/off */
- rc = ioctl(fd, FM_IOCTL_NOTE_ON, note);
- if (rc == -1)
- {
- perror("fm chips voice on");
- exit(-1);
- }
- }
-
- /* wait for ^C */
- sigpause(SIGINT);
- close(fd);
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/tst_fm_open.c'
- then
- echo shar: "will not over-write existing file 'apps/tst_fm_open.c'"
- else
- cat << \SHAR_EOF > 'apps/tst_fm_open.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/sb.h>
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int fd;
-
- fd = open("/dev/sbfm", O_WRONLY);
- if (fd == -1)
- perror("opening fm device");
- else
- close(fd);
-
- return(0);
- }
- SHAR_EOF
- fi
- if test -f 'apps/tst_instr.c'
- then
- echo shar: "will not over-write existing file 'apps/tst_instr.c'"
- else
- cat << \SHAR_EOF > 'apps/tst_instr.c'
- /*
- * Copyrighted as an unpublished work.
- * (c) Copyright 1991 Brian Smith
- * All rights reserved.
- *
- * Read the LICENSE file for details on distribution and use.
- *
- */
-
- #include <sys/fcntl.h>
- #include <sys/unistd.h>
- #include <sys/sb.h>
- #include <stdio.h>
-
- #define lobyte(X) (((unsigned char *)&X)[0])
- #define hibyte(X) (((unsigned char *)&X)[1])
-
- /* Globals */
- int fm_herz; /* clock ticks per second */
- int tempo; /* clock ticks per quarter note */
- int fm_fd;
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int cmf_fd;
-
- if (argc != 2)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* open cmf file */
- cmf_fd = open(argv[1], O_RDONLY);
- if (cmf_fd == -1)
- {
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* verify that file is a cmf file */
- if (!verify_cmf(cmf_fd))
- {
- printf("file was not a cmf file\n");
- printf("usage: %s <cmf file>\n", argv[0]);
- exit(-1);
- }
-
- /* read and set instruments from cmf file */
- set_instruments(cmf_fd);
-
- /* play song */
- play_song(cmf_fd);
-
- return(0);
- }
-
-
- /* check for "CTMF" in first four bytes of file */
- int verify_cmf(fd)
- int fd;
- {
- char idbuf[5];
-
- /* get id */
- lseek(fd, 0, SEEK_SET);
- if (read(fd, idbuf, 4) != 4)
- return(FALSE);
-
- /* compare to standard id */
- idbuf[4] = (char)0;
- if (strcmp(idbuf, "CTMF") != 0)
- return(FALSE);
-
- return(TRUE);
- }
-
- int set_instruments(fd)
- int fd;
- {
- int offset;
- int num_instruments;
- int i;
- int rc;
- int fnum, block, note;
- unsigned char tmp_byte;
- sb_fm_character note_character;
-
- /* open soundblaster fm chips */
- fm_fd = open("/dev/sbfm", O_WRONLY);
- if (fm_fd == -1)
- {
- perror("opening fm chips");
- exit(-1);
- }
-
- /* get offset of instrument block */
- offset = 0;
- lseek(fd, 0x06, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(offset) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(offset) = tmp_byte;
-
- /* get number of instruments */
- num_instruments = 0;
- lseek(fd, 0x24, SEEK_SET);
- read(fd, &tmp_byte, 1);
- lobyte(num_instruments) = tmp_byte;
- read(fd, &tmp_byte, 1);
- hibyte(num_instruments) = tmp_byte;
-
- if (num_instruments > 9)
- num_instruments = 9;
- printf("loading %d instruments\n", num_instruments);
-
- /* read each instrument */
- lseek(fd, offset, SEEK_SET);
- for (i=0; i< num_instruments; i++)
- {
- /* set instrument characteristics */
- note_character.voice_num = i;
- read(fd, note_character.data, 16);
- printf("loading instrument: 0x%02x\n", i);
- rc = ioctl(fm_fd, FM_IOCTL_SET_VOICE, (int)¬e_character);
- if (rc == -1)
- {
- perror("fm chips voice set");
- exit(-1);
- }
-
- /* set note to regular C note */
- fnum = 686;
- block = 4;
- note_num(note) = i;
- fnum_low(note) = fnum & 0xFF;
- keyon_blk_fnum(note) = 0;
- keyon_blk_fnum(note) |= 1<<5; /* KEYON bit */
- keyon_blk_fnum(note) |= (block & 7) << 2; /* block/octave */
- keyon_blk_fnum(note) |= (fnum & 0x3FF) >> 8; /* top 2 bits of fnum */
- ioctl(fm_fd, FM_IOCTL_NOTE_ON, note);
- sleep(1);
- ioctl(fm_fd, FM_IOCTL_NOTE_ON, i);
- }
-
- return(0);
- }
-
-
- /*
- * get and set timing parameters
- */
- void set_timing(fd)
- int fd;
- {
- unsigned char tmp_byte;
-
- /* get tempo */
- tempo = 0;
- lseek(fd, 0x0C, SEEK_SET);
- read(fd, &tmp_byte, 1);
- tempo = (unsigned int)tmp_byte;
- read(fd, &tmp_byte, 1);
- tempo += (unsigned int)tmp_byte << 8;
-
- /* get herz of timing clock */
- fm_herz = 0;
- lseek(fd, 0x0C, SEEK_SET);
- read(fd, &tmp_byte, 1);
- tempo = (unsigned int)fm_herz;
- read(fd, &tmp_byte, 1);
- tempo += (unsigned int)fm_herz << 8;
-
- return;
- }
-
-
- /*
- * seek to the midi stream and handle midi events for the song
- */
- int play_song(fd)
- int fd;
- {
- return(0);
- }
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-