From pa.dec.com!decwrl!elroy.jpl.nasa.gov!lll-winken!uunet!sparky!kent Sun Jun 9 13:39:51 PDT 1991 Article: 2439 of comp.sources.misc Path: pa.dec.com!decwrl!elroy.jpl.nasa.gov!lll-winken!uunet!sparky!kent From: brians@eecs.cs.pdx.edu (Brian Smith) Newsgroups: comp.sources.misc Subject: v20i048: sndblast - Sound Blaster Unix Driver, Part02/02 Message-ID: <1991Jun8.034158.24831@sparky.IMD.Sterling.COM> Date: 8 Jun 91 03:41:58 GMT References: Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: Sterling Software, IMD Lines: 1358 Approved: kent@sparky.imd.sterling.com X-Md4-Signature: 80518592f1aeee09cc9ee042d46ef411 Submitted-by: Brian Smith Posting-number: Volume 20, Issue 48 Archive-name: sndblast/part02 Environment: ISC-Unix #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: ./INSTALL ./LICENSE ./Makefile ./Master ./Name ./Node # ./README ./Space.c ./System ./apps/Makefile ./apps/get_instr.1 # ./apps/get_instr.c ./apps/play_cleanup.c ./apps/play_cmf.1 # ./apps/play_snd.1 ./apps/record_snd.1 ./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 # Wrapped by kent@sparky on Fri Jun 7 22:16:57 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 2 (of 2)."' if test -f './INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./INSTALL'\" else echo shar: Extracting \"'./INSTALL'\" \(1068 characters\) sed "s/^X//" >'./INSTALL' <<'END_OF_FILE' X X Sound Blaster(tm) Driver X (Copyright 1991, Brian Smith) X X XINSTALLING THE DRIVER X X1. Run make in the directory with the driver code (sb.c, sb.h, etc...). X2. su to root, if not already so, and run /etc/insdriver. X a. Answer . for query asking for the directory of the driver X files. X b. Answer sb for the query asking for the driver name. X c. Accept the default of /etc/conf for the configuration directory X by hitting return. X d. Enter any description you like. Maybe: "Sound Blaster Driver". X e. Answer n to the configuration question. X3. As root still, run /etc/kconfig. X4. Make sure the driver is configured into the kernel in the X configuration menu. X5. Build a new kernel. X6. Install the new kernel. This reboots the machine. X X XINSTALLING THE USER PROGRAMS X X1. Edit the Makefile in the apps directory. X2. Run make. X3. Run make install. X4. Manually install the man files however you like. The *.1 files are Xnroff source, while the *.doc files are nroff'ed for those of use Xwithout. END_OF_FILE if test 1068 -ne `wc -c <'./INSTALL'`; then echo shar: \"'./INSTALL'\" unpacked with wrong size! fi # end of './INSTALL' fi if test -f './LICENSE' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./LICENSE'\" else echo shar: Extracting \"'./LICENSE'\" \(2117 characters\) sed "s/^X//" >'./LICENSE' <<'END_OF_FILE' X X SoundBlaster(tm) Driver General Public License X (Copyright 1991, Brian Smith) X X Most licenses are restrictive in one way or another, the GNU license Xas well. The whole purpose of this excercise was to benefit the computer Xcommunity as a whole, including those of us unprincipled enough to want Xto make money on software. :-) X X For my protection, it must be stated at the outset that there is NO Xstated or implied warranty for the driver nor is there any stated or Ximplied warranty for any of the associated user programs nor for the Xdocumentation. The mistakes are mine, the responsibility is yours (for Xusing the package). X XCOPYING ANDUSE POLICIES X X1. You may use this unmodified package on any and all computers which Xyou wish to install this package. X X2. You may copy and distribute verbatim copies of this SoundBlaster driver Xand associated user software as you recieved them. Distribute them however Xyou like, as long as they are distributed with the original copyright Xand (lack of) warranty messages intact. X X3. You may distribute modified copies of this driver in source forms if Xand only if my copyright and (lack of) is intact in addition to an Xappended statement of your modification. I must not be held responsible Xfor any modifications made by other persons. X X4. Any persons or companies or persons who wish to make a commercial Xdistribution (binaries only) using this package or any portion of this Xpackage must contact me first. I will most likely license the person or Xcompany for little or no charge. Mostly, I'm a snoop: if you are using Xmy software let me know. :-) X XAs I am not a lawyer, so, there are likely legal holes the size of Xsmall continents, but please try to keep the spirit of this license. The Xintent of this was for betterment of the community. Any changes should Xbe sent to me for integration (either e-mail or snail-mail). X XCURRENT ADDRESSES X e-mail: brians@cs.pdx.edu X ...!uunet!tektronix!pdxgate!eecs!brians X US Mail: Brian Smith X 18700 SW Cascadia Court X Aloha, OR 97007 END_OF_FILE if test 2117 -ne `wc -c <'./LICENSE'`; then echo shar: \"'./LICENSE'\" unpacked with wrong size! fi # end of './LICENSE' fi if test -f './Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Makefile'\" else echo shar: Extracting \"'./Makefile'\" \(1110 characters\) sed "s/^X//" >'./Makefile' <<'END_OF_FILE' X# X# Sound Blaster(tm) Driver X# (Copyright 1991, Brian Smith) X# X XSHELL=/bin/sh XINCLSYS = /usr/include/sys XLKDRVRDIR = /etc/conf/pack.d/sb XLKSCONFDIR = /etc/conf/sdevice.d XLKNCONFDIR = /etc/conf/node.d XLKICONFDIR = /etc/conf/init.d XLKKCONFDIR = /etc/conf/kconfig.d XDRVRNAME = Driver.o XCONFNAME = sb X XCC=cc XCFLAGS = -O -DINKERNEL X XOBJS = Driver.o X Xall: Driver.o $(INCLSYS)/sb.h X XDriver.o: sb.c $(INCLSYS)/sb.h Makefile X $(CC) $(CFLAGS) -c sb.c X mv sb.o Driver.o X Xinstall: $(LKDRVRDIR) $(LKDRVRDIR)/$(DRVRNAME) $(LKDRVRDIR)/space.c \ X $(INCLSYS)/sb.h X X# OLD install, now done manually X# install: Driver.o $(INCLSYS)/sb.h Master System Space.c Node X# /etc/insdriver X# /etc/kconfig X X$(LKDRVRDIR): X -mkdir $(LKDRVRDIR) 2> /dev/null X chmod 755 $(LKDRVRDIR) X X$(INCLSYS)/sb.h: sb.h X @echo /bin/cp sb.h $(INCLSYS)/sb.h X /bin/cp sb.h $(INCLSYS)/sb.h X X$(LKDRVRDIR)/Driver.o: Driver.o X cp Driver.o $(LKDRVRDIR)/$(DRVRNAME) X chmod 644 $(LKDRVRDIR)/$(DRVRNAME) X X$(LKDRVRDIR)/space.c: Space.c X cp Space.c $(LKDRVRDIR)/space.c X chmod 644 $(LKDRVRDIR)/space.c X Xclean: X rm -f Driver.o END_OF_FILE if test 1110 -ne `wc -c <'./Makefile'`; then echo shar: \"'./Makefile'\" unpacked with wrong size! fi # end of './Makefile' fi if test -f './Master' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Master'\" else echo shar: Extracting \"'./Master'\" \(27 characters\) sed "s/^X//" >'./Master' <<'END_OF_FILE' Xsb ocrwiI iHc sb 0 0 1 3 1 END_OF_FILE if test 27 -ne `wc -c <'./Master'`; then echo shar: \"'./Master'\" unpacked with wrong size! fi # end of './Master' fi if test -f './Name' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Name'\" else echo shar: Extracting \"'./Name'\" \(20 characters\) sed "s/^X//" >'./Name' <<'END_OF_FILE' XSoundBlaster Driver END_OF_FILE if test 20 -ne `wc -c <'./Name'`; then echo shar: \"'./Name'\" unpacked with wrong size! fi # end of './Name' fi if test -f './Node' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Node'\" else echo shar: Extracting \"'./Node'\" \(48 characters\) sed "s/^X//" >'./Node' <<'END_OF_FILE' Xsb sbcms c 0 Xsb sbfm c 1 Xsb sbdsp c 2 END_OF_FILE if test 48 -ne `wc -c <'./Node'`; then echo shar: \"'./Node'\" unpacked with wrong size! fi # end of './Node' fi if test -f './README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./README'\" else echo shar: Extracting \"'./README'\" \(3663 characters\) sed "s/^X//" >'./README' <<'END_OF_FILE' X X Sound Blaster(tm) Driver X (Copyright 1991, Brian Smith) X X XREQUIREMENTS X XThis driver and the associated user programs require a 386/486 system Xrunning System V 3.2 Unix. It has been tested on ISC Unix versions X2.0.2 through 2.2.1. I believe it will work correctly on Esix, Intel, Xand AT&T Unix. SCO is a mystery to me (as well as many others). I do Xnot believe it will work in SysV 4.0 and above, but the modifications Xshould be fairly minimal. Remember, though, THERE IS NO WARRANTY. X X XGENERAL INFORMATION X XThis driver is for the Sound Blaster sound card designed by Creative XLabs, Incorporated. The Sound Blaster is a sound card for the XIBM-PC(tm) type I/O bus. The card is capable of sampling sound from a Xmicrophone jack from 4KHz to 23KHz (or 24KHz, depending upon which Xportion of the manual you believe) at 8 raw bits of resolution. It is Xalso capable of playing samples at speeds from 4KHz up to 12KHz. The Xboard can play raw 8 bit samples, or 2 bit, 2.6 bit, or 4 bit ADPCM Xpacked samples. ADCPM is a lossy method of data compression. The Xsampling and output may be directly driven by the CPU, or it may be Xdriven by DMA. The card is also capable of playing music through an Xon-board FM synthesizer chip. The chip may play 9 simultaneous Xinstruments, or it can play 6 simultaneous voices with 5 additional Xrhythm instruments. In addition, the board (but NOT my driver) also Xsupports the addition of 2 C/MS chips. For more information, read the Xadvertising blurb, errr... manual which comes with the Sound Blaster. X XThe driver is capable of utilizing only a subset of the capabilities Xof the Sound Blaster card. The driver is accessed through three Xdevice nodes. X XThe /dev/sbdsp node accesses the DSP chip which controls sampling and Xsample playback. Only 8-bit sound is supported thus far. The driver Xutilizes DMA, and therefore is very unobtrusive to the system load. XThe ls utility is harder upon the system. Read(2) and write(2) upon X/dev/sbdsp sample sound and play back sound samples, respectively. XSeveral ioctl(2)'s control sampling/playback speed, resets, etc... XThe play_snd utility demonstrates the use of the /dev/sbdsp node. X XThe /dev/sbfm node accesses the FM chips. The only access to the FM Xchips are through ioctl(2)'s. The play_cmf utility demonstrates the Xuse of the FM chips by (mostly) interpreting and playing CMF files. XThe various options controlling the voices can be dumped from a CMF Xfile by the get_instruments utility. Those familiar with synthesizers Xcan then learn how to create their own instruments. I can't provide Xdirect documentation, as I believe that would be a violation of XCreative Lab's copyrights. Those having questions, send me e-mail. I Xthink it would be OK to answer questions. X XThe /dev/sbcms node accesses absolutely nothing. I do not have the XC/MS chips with which to experiment. X XThis driver is merely the rough outlines of what it could be. Support Xcould be added for oodles of features, like efficiency improvements, and XADCPM interpretion for the /dev/sbdsp node. If you wish to add to this Xdriver, please be my guest (after reading the license file). When you Xhave patches, send those to me. I will then integrate, do rudimentary Xtesting, and send the patches to Usenet. That way, there won't be Xbillions of versions of this driver to contend with. X XI am not requiring donations to my, no doubt worthy cause, however, Xthey are willingly accepted. :-) They will help me in future Xprojects, and if there are enough requests (loudness does not count), XI will continue work on this driver and write more software to use Xit. END_OF_FILE if test 3663 -ne `wc -c <'./README'`; then echo shar: \"'./README'\" unpacked with wrong size! fi # end of './README' fi if test -f './Space.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./Space.c'\" else echo shar: Extracting \"'./Space.c'\" \(374 characters\) sed "s/^X//" >'./Space.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X X#include X Xushort sb_configured = SB; Xushort sb_dma_chan = SB_CHAN; Xushort sb_interrupt = SB_0_VECT; Xstruct iobuf sbtab[3]; END_OF_FILE if test 374 -ne `wc -c <'./Space.c'`; then echo shar: \"'./Space.c'\" unpacked with wrong size! fi # end of './Space.c' fi if test -f './System' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./System'\" else echo shar: Extracting \"'./System'\" \(34 characters\) sed "s/^X//" >'./System' <<'END_OF_FILE' Xsb Y 3 6 3 5 220 22F 0 0 END_OF_FILE if test 34 -ne `wc -c <'./System'`; then echo shar: \"'./System'\" unpacked with wrong size! fi # end of './System' fi if test -f './apps/Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/Makefile'\" else echo shar: Extracting \"'./apps/Makefile'\" \(1472 characters\) sed "s/^X//" >'./apps/Makefile' <<'END_OF_FILE' X# X# Programs using Sound Blaster(tm) Driver X# (Copyright 1991, Brian Smith) X# X XSHELL=/bin/sh XCC= gcc -fpcc-struct-return XCFLAGS = # -O XLIBS= -lc_s X XPROGRAMS= play_snd set_speed play_cmf record_snd snd_norm XTESTS= play_cleanup tst_fm_open tst_fm_note get_instr tst_instr X Xall: $(PROGRAMS) $(TESTS) X Xrecord_snd: record_snd.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o record_snd record_snd.c $(LIBS) X Xplay_snd: play_snd.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o play_snd play_snd.c $(LIBS) X Xplay_cleanup: play_cleanup.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o play_cleanup play_cleanup.c $(LIBS) X Xget_instr: get_instr.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o get_instr get_instr.c $(LIBS) X Xset_speed: set_speed.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o set_speed set_speed.c $(LIBS) X Xtst_fm_open: tst_fm_open.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o tst_fm_open tst_fm_open.c $(LIBS) X Xtst_fm_note: tst_fm_note.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o tst_fm_note tst_fm_note.c $(LIBS) X Xplay_cmf: play_cmf.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o play_cmf play_cmf.c -linet $(LIBS) X Xtst_instr: tst_instr.c /usr/include/sys/sb.h X $(CC) $(CFLAGS) -o tst_instr tst_instr.c $(LIBS) X Xsnd_norm: snd_norm.c X $(CC) $(CFLAGS) -o snd_norm snd_norm.c $(LIBS) X Xinstall: $(PROGRAMS) X for i in $(PROGRAMS); do \ X mcs -d $$i ; \ X strip $$i ; \ X (echo $$i | cpio -pdlmv /usr/local/bin) ; \ X done X Xclean: X /bin/rm -f $(PROGRAMS) $(TESTS) END_OF_FILE if test 1472 -ne `wc -c <'./apps/Makefile'`; then echo shar: \"'./apps/Makefile'\" unpacked with wrong size! fi # end of './apps/Makefile' fi if test -f './apps/get_instr.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/get_instr.1'\" else echo shar: Extracting \"'./apps/get_instr.1'\" \(377 characters\) sed "s/^X//" >'./apps/get_instr.1' <<'END_OF_FILE' X.TH GET_INSTR 1 "3 June 1991" X.UC 4 X.SH NAME Xget_instr \- decodes and prints instrument info from CMF files X.SH SYNOPSIS X.B get_instr X[ X.I file X] X.PP XThe argument must be the CMF file to be examined. X.SH DESCRIPTION X.B get_instr Xreads the portion of the CMF file detailing the instruments used, and Xthen prints out the breakdown of that information. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 377 -ne `wc -c <'./apps/get_instr.1'`; then echo shar: \"'./apps/get_instr.1'\" unpacked with wrong size! fi # end of './apps/get_instr.1' fi if test -f './apps/get_instr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/get_instr.c'\" else echo shar: Extracting \"'./apps/get_instr.c'\" \(4479 characters\) sed "s/^X//" >'./apps/get_instr.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X#include X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X int cmf_fd; X X if (argc != 2) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* open cmf file */ X cmf_fd = open(argv[1], O_RDONLY); X if (cmf_fd == -1) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* verify that file is a cmf file */ X if (!verify_cmf(cmf_fd)) X { X printf("file was not a cmf file\n"); X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* print out info on instruments in cmf file */ X print_instruments(cmf_fd); X X return(0); X} X X X/* check for "CTMF" in first four bytes of file */ Xint verify_cmf(fd) Xint fd; X{ X char idbuf[5]; X X /* get id */ X lseek(fd, 0, SEEK_SET); X if (read(fd, idbuf, 4) != 4) X return(FALSE); X X /* compare to standard id */ X idbuf[4] = (char)0; X if (strcmp(idbuf, "CTMF") != 0) X return(FALSE); X X return(TRUE); X} X Xint print_instruments(fd) Xint fd; X{ X int offset; X int num_instruments; X int i; X int j; X unsigned char tmp_byte; X unsigned char instrument_buf[16]; X X#define lobyte(X) (((unsigned char *)&X)[0]) X#define hibyte(X) (((unsigned char *)&X)[1]) X X /* get offset of instrument block */ X offset = 0; X lseek(fd, 0x06, SEEK_SET); X read(fd, &tmp_byte, 1); X lobyte(offset) = tmp_byte; X read(fd, &tmp_byte, 1); X hibyte(offset) = tmp_byte; X X /* get number of instruments */ X num_instruments = 0; X lseek(fd, 0x24, SEEK_SET); X read(fd, &tmp_byte, 1); X lobyte(num_instruments) = tmp_byte; X read(fd, &tmp_byte, 1); X hibyte(num_instruments) = tmp_byte; X X /* read each instrument */ X lseek(fd, offset, SEEK_SET); X for (i=0; i< num_instruments; i++) X { X read(fd, instrument_buf, 16); X printf("instrument: 0x%02x\n", i); X X for (j=0; j<16; j++) X printf("0x%02x ", (unsigned int)instrument_buf[j]); X printf("\n"); X X /* byte 0 */ X printf("\tModulator: 0x%02x\n", (unsigned int)instrument_buf[0]); X X /* byte 1 */ X printf("\tCarrier Sound Characteristic\n"); X if (instrument_buf[1] & (1<<7)) X printf("\tPitch Vibrato: On\n"); X else X printf("\tPitch Vibrato: Off\n"); X if (instrument_buf[1] & (1<<6)) X printf("\tAmplitude Vibrato: On\n"); X else X printf("\tAmplitude Vibrato: Off\n"); X if (instrument_buf[1] & (1<<5)) X printf("\tSustaining Sound: On\n"); X else X printf("\tSustaining Sound: Off\n"); X if (instrument_buf[1] & (1<<4)) X printf("\tEnvelope Scaling: On\n"); X else X printf("\tEnvelope Scaling: Off\n"); X printf("\tFrequency Multiplier: 0x%02x\n", instrument_buf[1] & 0x0F); X X /* byte 2 */ X printf("\tModulator Level Scaling: 0x%02x\n", instrument_buf[2] >> 4); X printf("\tModulator Output Level: 0x%02x\n", instrument_buf[2] & 0x3f); X X /* byte 3 */ X printf("\tCarrier Level Scaling: 0x%02x\n", instrument_buf[3] >> 4); X printf("\tCarrier Output Level: 0x%02x\n", instrument_buf[3] & 0x3f); X X /* byte 4 */ X printf("\tModulator Attack Rate 0x%02x\n", instrument_buf[5] >> 4); X printf("\tModulator Decay Rate 0x%02x\n", instrument_buf[5] & 0xF); X X /* byte 5 */ X printf("\tCarrier Attack Rate 0x%02x\n", instrument_buf[5] >> 4); X printf("\tCarrier Decay Rate 0x%02x\n", instrument_buf[5] & 0xF); X X /* byte 6 */ X printf("\tModulator Sustain Level 0x%02x\n", instrument_buf[6] >> 4); X printf("\tModulator Release Level 0x%02x\n", instrument_buf[6] >> 4); X X /* byte 7 */ X printf("\tCarrier Sustain Level 0x%02x\n", instrument_buf[7] >> 4); X printf("\tCarrier Release Level 0x%02x\n", instrument_buf[7] >> 4); X X /* byte 8 */ X printf("\tModulator Wave Select 0x%02x\n", instrument_buf[8] & 0x03); X X /* byte 9 */ X printf("\tCarrier Wave Select 0x%02x\n", instrument_buf[9] & 0x03); X X /* byte A */ X printf("\tModulator FeedBack 0x%02x\n", X (instrument_buf[0xA] >> 1) & 0x07); X } X X return(0); X} END_OF_FILE if test 4479 -ne `wc -c <'./apps/get_instr.c'`; then echo shar: \"'./apps/get_instr.c'\" unpacked with wrong size! fi # end of './apps/get_instr.c' fi if test -f './apps/play_cleanup.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/play_cleanup.c'\" else echo shar: Extracting \"'./apps/play_cleanup.c'\" \(767 characters\) sed "s/^X//" >'./apps/play_cleanup.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X X#define NUMBUFS 2 X#define SHM_BUFSIZ (8*4096) X#define SHM_KEY 1796 X Xtypedef struct { X int not_last_segment[NUMBUFS]; X int unlocked[NUMBUFS]; X char buf[NUMBUFS*SHM_BUFSIZ]; X} buf_struct; X X Xmain() X{ X int rc; X int shmid; X X shmid = shmget(SHM_KEY, sizeof(buf_struct), IPC_CREAT | 0644); X if (shmid == -1) X { X perror("creating shared-mem buffer"); X exit(-1); X } X X rc = shmctl(shmid, IPC_RMID, 0); X if (rc == -1) X perror("removing segment"); X X exit(0); X} END_OF_FILE if test 767 -ne `wc -c <'./apps/play_cleanup.c'`; then echo shar: \"'./apps/play_cleanup.c'\" unpacked with wrong size! fi # end of './apps/play_cleanup.c' fi if test -f './apps/play_cmf.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/play_cmf.1'\" else echo shar: Extracting \"'./apps/play_cmf.1'\" \(450 characters\) sed "s/^X//" >'./apps/play_cmf.1' <<'END_OF_FILE' X.TH PLAY_CMF 1 "3 June 1991" X.UC 4 X.SH NAME Xplay_cmf \- decodes and plays a CMF music file. X.SH SYNOPSIS X.B play_cmf X[ X.I file X] X.PP XThe argument must be the CMF file to be played. X.SH DESCRIPTION X.B play_cmf XAttempts to play a CMF file. X.SH BUGS XMany CMF files attempt to use Control Change events not understood by the Xauthor. Therefore, the program does not implement whatever these Xcontrol changes are supposed to do. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 450 -ne `wc -c <'./apps/play_cmf.1'`; then echo shar: \"'./apps/play_cmf.1'\" unpacked with wrong size! fi # end of './apps/play_cmf.1' fi if test -f './apps/play_snd.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/play_snd.1'\" else echo shar: Extracting \"'./apps/play_snd.1'\" \(657 characters\) sed "s/^X//" >'./apps/play_snd.1' <<'END_OF_FILE' X.TH PLAY_SND 1 "3 June 1991" X.UC 4 X.SH NAME Xplay_snd \- plays a raw 8-bit sound file X.SH SYNOPSIS X.B play_snd X[ X.I file X] X.PP XThe argument must be the sound file to be played. X.SH DESCRIPTION X.B play_snd XPlays raw 8-bit sound files, using shared memory and two processes Xto double buffer reads and writes. Feel free to use SIGINT (usually Xcontrol-C) to interrupt the play. Do NOT, however, use SIGKILL or any Xother signal to terminate the program. This leaves unwanted Xleft-overs, in the form of a shared memory segment. Use play_cleanup Xif this happens accidentally. X XUse set_speed to change the playing rate of the samples. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 657 -ne `wc -c <'./apps/play_snd.1'`; then echo shar: \"'./apps/play_snd.1'\" unpacked with wrong size! fi # end of './apps/play_snd.1' fi if test -f './apps/record_snd.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/record_snd.1'\" else echo shar: Extracting \"'./apps/record_snd.1'\" \(670 characters\) sed "s/^X//" >'./apps/record_snd.1' <<'END_OF_FILE' X.TH RECORD_SND 1 "3 June 1991" X.UC 4 X.SH NAME Xrecord_snd \- records a raw 8-bit sound file X.SH SYNOPSIS X.B record_snd X[ X.I file X] X.PP XThe argument must be the sound file to contain the recording. X.SH DESCRIPTION X.B record_snd XRecords raw 8-bit sound files, using shared memory and two processes Xto double buffer reads and writes. Use SIGINT (usually control-C) to Xstop the recording. Do NOT, however, use SIGKILL or any other signal Xto terminate the program. This leaves unwanted left-overs, in the Xform of a shared memory segment. Use play_cleanup if this happens Xaccidentally. X XUse set_speed to change the recording rate of the samples. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 670 -ne `wc -c <'./apps/record_snd.1'`; then echo shar: \"'./apps/record_snd.1'\" unpacked with wrong size! fi # end of './apps/record_snd.1' fi if test -f './apps/set_speed.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/set_speed.1'\" else echo shar: Extracting \"'./apps/set_speed.1'\" \(520 characters\) sed "s/^X//" >'./apps/set_speed.1' <<'END_OF_FILE' X.TH SET_SPEED 1 "3 June 1991" X.UC 4 X.SH NAME Xset_speed \- changes the speed of recording and playing on Sound XBlaster X.SH SYNOPSIS X.B set_speed X] X.I speed X] X.PP XThe argument must be the speed (in HZ) for sampling or playing. X.SH DESCRIPTION X.B set_speed XSets the speed of the sampling and playing of the Sound Blaster Xdriver. The speed must be greater than (or equal) to 4000Hz, and less Xthan 24000Hz. Speeds in excess of 13000Hz will be truncated to Xapproximately 13000Hz by any recording. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 520 -ne `wc -c <'./apps/set_speed.1'`; then echo shar: \"'./apps/set_speed.1'\" unpacked with wrong size! fi # end of './apps/set_speed.1' fi if test -f './apps/set_speed.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/set_speed.c'\" else echo shar: Extracting \"'./apps/set_speed.c'\" \(778 characters\) sed "s/^X//" >'./apps/set_speed.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X int fd; X int speed; X X if (argc != 2) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X speed = atoi(argv[1]); X if ((speed < 4000) || (speed > 24000)) X { X printf("usage: %s \n", argv[0]); X printf("\tspeed must be between 4000 and 24000"); X exit(-1); X } X X fd = open("/dev/sbdsp", O_RDONLY); X if (fd == -1) X { X perror("opening SoundBlaster"); X exit(-1); X } X X ioctl(fd, DSP_IOCTL_SPEED, speed); X X exit(0); X} END_OF_FILE if test 778 -ne `wc -c <'./apps/set_speed.c'`; then echo shar: \"'./apps/set_speed.c'\" unpacked with wrong size! fi # end of './apps/set_speed.c' fi if test -f './apps/snd_norm.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/snd_norm.1'\" else echo shar: Extracting \"'./apps/snd_norm.1'\" \(492 characters\) sed "s/^X//" >'./apps/snd_norm.1' <<'END_OF_FILE' X.TH SND_NORM 1 "3 June 1991" X.UC 4 X.SH NAME Xsnd_norm \- normalizes a sound file X.SH SYNOPSIS X.B snd_norm X[ X.I old file X] X[ X.I new file X] X.PP XThe arguments are the input and output of the normalization. X.SH DESCRIPTION X.B snd_norm XThe input file is normalized, such that the larget amplitude 127, thus Xobtaining the larget volume from a file (for a given volume setting on Xthe actual Sound Blaster). Usefull for post-processing recordings Xwhich are barely audible. X.SH AUTHOR X.PP XBrian Smith END_OF_FILE if test 492 -ne `wc -c <'./apps/snd_norm.1'`; then echo shar: \"'./apps/snd_norm.1'\" unpacked with wrong size! fi # end of './apps/snd_norm.1' fi if test -f './apps/snd_norm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/snd_norm.c'\" else echo shar: Extracting \"'./apps/snd_norm.c'\" \(1777 characters\) sed "s/^X//" >'./apps/snd_norm.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int fd, new_fd, rc, max_wave; X unsigned char tmp_byte; X int tmp_int; X int i; X double augmentation; X X if (argc != 3) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X X fd = open(argv[1], O_RDONLY); X if (fd == -1) X { X perror("opening oldfile"); X exit(-1); X } X X new_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); X if (new_fd == -1) X { X perror("opening newfile"); X exit(-1); X } X X printf("normalizing from input file.."); X fflush(stdout); X i = 0; X max_wave = 0; X while(1) X { X i++ ; i &= 0x7FFF; X if (!i) X write(1, ".", 1); X X rc = read(fd, &tmp_byte, 1); X if (rc == 0) X break; X tmp_int = tmp_byte - 128; X if (abs(tmp_int) > max_wave) X max_wave = abs(tmp_int); X } X write(1, "\n", 1); X X augmentation = (double)0x80 / (double)max_wave; X printf("max_wave\t%d\n", max_wave); X printf("augmentation\t%f\n", augmentation); X X X /* write out new file */ X lseek(fd, 0, SEEK_SET); X while (1) X { X rc = read(fd, &tmp_byte, 1); X if (rc == 0) X break; X X tmp_int = tmp_byte - 128; X tmp_int *= augmentation; X tmp_int += 128; X X tmp_byte = tmp_int; X X rc = write(new_fd, &tmp_byte, 1); X if (rc != 1) X { X perror("writing to new_fd"); X exit(-1); X } X } X X X return(0); X} END_OF_FILE if test 1777 -ne `wc -c <'./apps/snd_norm.c'`; then echo shar: \"'./apps/snd_norm.c'\" unpacked with wrong size! fi # end of './apps/snd_norm.c' fi if test -f './apps/tst_fm_note.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/tst_fm_note.c'\" else echo shar: Extracting \"'./apps/tst_fm_note.c'\" \(2049 characters\) sed "s/^X//" >'./apps/tst_fm_note.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X#include X#include X Xvoid handler() X{ X return; X} X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X int fd; X int rc; X int i; X int note; X int fnum; X int block; X static unsigned char instrument_buf[16] = { X 0x11, 0x01, 0x8a, 0x40, X 0xf1, 0xf1, 0x11, 0xb3, X 0x00, 0x00, 0x06, 0x00, X 0x00, 0x00, 0x00, 0x00 X }; X sb_fm_character note_character; X X sigset(SIGINT, handler); X X fd = open("/dev/sbfm", O_WRONLY); X if (fd == -1) X { X perror("opening fm device"); X return(-1); X } X X /* test reset */ X rc = ioctl(fd, FM_IOCTL_RESET); X if (rc == -1) X { X perror("fm chips reset"); X exit(-1); X } X X /* test setting an instrument */ X for (i=0 ; i<9; i++) X { X /* set instrument characteristics */ X note_character.voice_num = i; X memset(note_character.data, (char)0, 16); X memcpy(note_character.data, instrument_buf, 16); X rc = ioctl(fd, FM_IOCTL_SET_VOICE, (int)¬e_character); X if (rc == -1) X { X perror("fm chips voice set"); X exit(-1); X } X X /* set note to play */ X fnum = 686; X block = i; X note_num(note) = i; X fnum_low(note) = fnum & 0xFF; X keyon_blk_fnum(note) = 0; X keyon_blk_fnum(note) |= 1<<5; /* KEYON bit */ X keyon_blk_fnum(note) |= (block & 7) << 2; /* block/octave */ X keyon_blk_fnum(note) |= (fnum & 0x3FF) >> 8; /* top 2 bits of fnum */ X X /* test note on/off */ X rc = ioctl(fd, FM_IOCTL_NOTE_ON, note); X if (rc == -1) X { X perror("fm chips voice on"); X exit(-1); X } X } X X /* wait for ^C */ X sigpause(SIGINT); X close(fd); X return(0); X} END_OF_FILE if test 2049 -ne `wc -c <'./apps/tst_fm_note.c'`; then echo shar: \"'./apps/tst_fm_note.c'\" unpacked with wrong size! fi # end of './apps/tst_fm_note.c' fi if test -f './apps/tst_fm_open.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/tst_fm_open.c'\" else echo shar: Extracting \"'./apps/tst_fm_open.c'\" \(415 characters\) sed "s/^X//" >'./apps/tst_fm_open.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X int fd; X X fd = open("/dev/sbfm", O_WRONLY); X if (fd == -1) X perror("opening fm device"); X else X close(fd); X X return(0); X} END_OF_FILE if test 415 -ne `wc -c <'./apps/tst_fm_open.c'`; then echo shar: \"'./apps/tst_fm_open.c'\" unpacked with wrong size! fi # end of './apps/tst_fm_open.c' fi if test -f './apps/tst_instr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./apps/tst_instr.c'\" else echo shar: Extracting \"'./apps/tst_instr.c'\" \(4064 characters\) sed "s/^X//" >'./apps/tst_instr.c' <<'END_OF_FILE' X/* X * Copyrighted as an unpublished work. X * (c) Copyright 1991 Brian Smith X * All rights reserved. X * X * Read the LICENSE file for details on distribution and use. X * X */ X X#include X#include X#include X#include X X#define lobyte(X) (((unsigned char *)&X)[0]) X#define hibyte(X) (((unsigned char *)&X)[1]) X X/* Globals */ Xint fm_herz; /* clock ticks per second */ Xint tempo; /* clock ticks per quarter note */ Xint fm_fd; X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X int cmf_fd; X X if (argc != 2) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* open cmf file */ X cmf_fd = open(argv[1], O_RDONLY); X if (cmf_fd == -1) X { X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* verify that file is a cmf file */ X if (!verify_cmf(cmf_fd)) X { X printf("file was not a cmf file\n"); X printf("usage: %s \n", argv[0]); X exit(-1); X } X X /* read and set instruments from cmf file */ X set_instruments(cmf_fd); X X /* play song */ X play_song(cmf_fd); X X return(0); X} X X X/* check for "CTMF" in first four bytes of file */ Xint verify_cmf(fd) Xint fd; X{ X char idbuf[5]; X X /* get id */ X lseek(fd, 0, SEEK_SET); X if (read(fd, idbuf, 4) != 4) X return(FALSE); X X /* compare to standard id */ X idbuf[4] = (char)0; X if (strcmp(idbuf, "CTMF") != 0) X return(FALSE); X X return(TRUE); X} X Xint set_instruments(fd) Xint fd; X{ X int offset; X int num_instruments; X int i; X int rc; X int fnum, block, note; X unsigned char tmp_byte; X sb_fm_character note_character; X X /* open soundblaster fm chips */ X fm_fd = open("/dev/sbfm", O_WRONLY); X if (fm_fd == -1) X { X perror("opening fm chips"); X exit(-1); X } X X /* get offset of instrument block */ X offset = 0; X lseek(fd, 0x06, SEEK_SET); X read(fd, &tmp_byte, 1); X lobyte(offset) = tmp_byte; X read(fd, &tmp_byte, 1); X hibyte(offset) = tmp_byte; X X /* get number of instruments */ X num_instruments = 0; X lseek(fd, 0x24, SEEK_SET); X read(fd, &tmp_byte, 1); X lobyte(num_instruments) = tmp_byte; X read(fd, &tmp_byte, 1); X hibyte(num_instruments) = tmp_byte; X X if (num_instruments > 9) X num_instruments = 9; X printf("loading %d instruments\n", num_instruments); X X /* read each instrument */ X lseek(fd, offset, SEEK_SET); X for (i=0; i< num_instruments; i++) X { X /* set instrument characteristics */ X note_character.voice_num = i; X read(fd, note_character.data, 16); X printf("loading instrument: 0x%02x\n", i); X rc = ioctl(fm_fd, FM_IOCTL_SET_VOICE, (int)¬e_character); X if (rc == -1) X { X perror("fm chips voice set"); X exit(-1); X } X X /* set note to regular C note */ X fnum = 686; X block = 4; X note_num(note) = i; X fnum_low(note) = fnum & 0xFF; X keyon_blk_fnum(note) = 0; X keyon_blk_fnum(note) |= 1<<5; /* KEYON bit */ X keyon_blk_fnum(note) |= (block & 7) << 2; /* block/octave */ X keyon_blk_fnum(note) |= (fnum & 0x3FF) >> 8; /* top 2 bits of fnum */ X ioctl(fm_fd, FM_IOCTL_NOTE_ON, note); X sleep(1); X ioctl(fm_fd, FM_IOCTL_NOTE_ON, i); X } X X return(0); X} X X X/* X * get and set timing parameters X */ Xvoid set_timing(fd) Xint fd; X{ X unsigned char tmp_byte; X X /* get tempo */ X tempo = 0; X lseek(fd, 0x0C, SEEK_SET); X read(fd, &tmp_byte, 1); X tempo = (unsigned int)tmp_byte; X read(fd, &tmp_byte, 1); X tempo += (unsigned int)tmp_byte << 8; X X /* get herz of timing clock */ X fm_herz = 0; X lseek(fd, 0x0C, SEEK_SET); X read(fd, &tmp_byte, 1); X tempo = (unsigned int)fm_herz; X read(fd, &tmp_byte, 1); X tempo += (unsigned int)fm_herz << 8; X X return; X} X X X/* X * seek to the midi stream and handle midi events for the song X */ Xint play_song(fd) Xint fd; X{ X return(0); X} END_OF_FILE if test 4064 -ne `wc -c <'./apps/tst_instr.c'`; then echo shar: \"'./apps/tst_instr.c'\" unpacked with wrong size! fi # end of './apps/tst_instr.c' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.