SST - SPARCstation Sound Tools - part 1 of 2

Jef Poskanzer jef at well.UUCP
Tue Nov 21 20:03:25 AEST 1989


Here's a simple sound toolbox for the SPARCstation-1 built-in speaker.
---
Jef
                                   
  Jef Poskanzer  jef at well.sf.ca.us  {ucbvax, apple, hplabs}!well!jef
                     "Grow your own, for Victory!"

#! /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 the files:
#	README
#	Makefile
#	libst.h
#	libst.c
#	libsst.h
#	libsst.c
#	libfft.h
#	libfft.c
#	echoplex.c
#	echoplex.1
#	lintoulaw.c
#	lintoulaw.1
#	mix.c
#	mix.1
#	pitch.c
#	pitch.1
# This archive created: Mon Nov 20 22:01:20 1989
# By:	Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(2001 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X                       SPARCstation Sound Tools
X                     Beta Distribution of 20nov89
X                      Previous distribution NONE
X
X
XThis package contains some simple sound tools for the SPARCstation-1.
XThe SPARCstation can record and playback telephone-quality sound using
Xthe Am79C30A audio chip from AMD.  Telephone-quality means 8192 samples
Xper second and eight bits per sample, so don't expect Hi-Fi.  The chip
Xhas a few interesting abilities other than record and playback, such as
Xtone generation.  For full details call AMD's "literature center" at
X(408)749-2264 and ask for the spec, publication #09893.
X
XIn addition to the tools that directly manipulate the sound chip, this
Xpackage includes some simple filters for manipulating sound files.
X
XFeedback is welcome; send bug reports, enhancements, checks, money
Xorders, etc. to the addresses below.  Be sure to mention what version
Xyou have when sending bug reports!
X
X    Jef Poskanzer
X    jef at well.sf.ca.us
X    {ucbvax, lll-crg, sun!pacbell, apple, hplabs}!well!jef
X
X
XFiles in sst.shar:
X
X    README		this
X    Makefile		guess
X
X    libst.h		header file for portable sound tool library
X    libst.c		portable sound tool library
X    libsst.h		header file for SPARC sound tool library
X    libsst.c		SPARC sound tool library
X    libfft.h		header file for FFT library
X    libfft.c		FFT library
X
X    echoplex.c		echo generator
X    lintoulaw.c		convert linear to ulaw
X    mix.c		mix multiple sound files
X    pitch.c		change the pitch of a sound file
X    speed.c		change the speed of a sound file
X    ulawtolin.c		convert ulaw to linear
X    volume.c		change the volume of a sound file
X    vox.c		simple silence-deletion filter
X    dial.c		generate DTMF dialing codes on the speaker
X    listen.c		hardware loopback, connect microphone to speaker
X    play.c		play a sound file on the speaker
X    record.c		record from the microphone input
X    tones.c		play sine-wave tones on the speaker
X
X    *.1			manual entries for all the above tools
SHAR_EOF
if test 2001 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 2001 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(1602 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XCFLAGS =	-O
XLDLAGS =	-s
X
XPOBJS =		echoplex lintoulaw mix speed ulawtolin volume vox
XFOBJS =		pitch
XSOBJS =		dial listen play record tones
X
XOBJS = $(POBJS) $(FOBJS) $(SOBJS)
X
Xall:		$(OBJS)
X
X$(POBJS):	libst.h libst.o
X	$(CC) $(CFLAGS) $(LDFLAGS) $@.c libst.o -o $@
X
X$(FOBJS):	libst.h libst.o libfft.h libfft.o
X	$(CC) $(CFLAGS) $(LDFLAGS) $@.c libst.o libfft.o -lm -o $@
X
X$(SOBJS):	libst.h libst.o libsst.h libsst.o
X	$(CC) $(CFLAGS) $(LDFLAGS) $@.c libst.o libsst.o -o $@
X
Xechoplex:	echoplex.c
Xlintoulaw:	lintoulaw.c
Xmix:		mix.c
Xspeed:		speed.c
Xulawtolin:	ulawtolin.c
Xvolume:		volume.c
Xvox:		vox.c
Xpitch:		pitch.c
Xdial:		dial.c
Xlisten:		listen.c
Xplay:		play.c
Xrecord:		record.c
Xtones:		tones.c
X
X
Xlibst.o:	libst.c libst.h
X	$(CC) $(CFLAGS) -c libst.c
X
Xlibfft.o:	libfft.c libfft.h
X	$(CC) $(CFLAGS) -c libfft.c
X
Xlibsst.o:	libsst.c libsst.h
X	$(CC) $(CFLAGS) -c libsst.c
X
X
Xclean:
X	rm -f $(OBJS) *.o
X
Xshar:		sst.shar
Xsst.shar:	sst.shar1 sst.shar2
Xsst.shar1:	README Makefile libst.h libst.c libsst.h libsst.c libfft.h \
X		libfft.c echoplex.c echoplex.1 lintoulaw.c lintoulaw.1 mix.c \
X		mix.1 pitch.c pitch.1
X	shar -v -c -p X README Makefile libst.h libst.c libsst.h libsst.c libfft.h libfft.c echoplex.c echoplex.1 lintoulaw.c lintoulaw.1 mix.c mix.1 pitch.c pitch.1 > $@
Xsst.shar2:	speed.c speed.1 ulawtolin.c ulawtolin.1 volume.c volume.1 \
X		vox.c vox.1 dial.c dial.1 listen.c listen.1 play.c play.1 \
X		record.c record.1 tones.c tones.1
X	shar -v -c -p X speed.c speed.1 ulawtolin.c ulawtolin.1 volume.c volume.1 vox.c vox.1 dial.c dial.1 listen.c listen.1 play.c play.1 record.c record.1 tones.c tones.1 > $@
SHAR_EOF
if test 1602 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1602 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libst.h'" '(3224 characters)'
if test -f 'libst.h'
then
	echo shar: will not over-write existing file "'libst.h'"
else
sed 's/^X//' << \SHAR_EOF > 'libst.h'
X/* libst.h - include file for portable sound tools library
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#define SAMPLES_PER_SECOND 8192
X
X#define MINLIN -32768
X#define MAXLIN 32767
X#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
X
Xunsigned char st_linear_to_ulaw( /* int sample */ );
Xint st_ulaw_to_linear_slow( /* unsigned char ulawbyte */ );
X
X/*
X** This macro converts from ulaw to 16 bit linear, faster.
X**
X** Jef Poskanzer
X** 23 October 1989
X**
X** Input: 8 bit ulaw sample
X** Output: signed 16 bit linear sample
X*/
X#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
X
Xstatic int ulaw_table[256] = {
X    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
X    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
X    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
X    -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
X     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
X     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
X     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
X     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
X     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
X     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
X      -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
X      -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
X      -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
X      -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
X      -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
X       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
X     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
X     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
X     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
X     11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
X      7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
X      5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
X      3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
X      2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
X      1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
X      1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
X       876,    844,    812,    780,    748,    716,    684,    652,
X       620,    588,    556,    524,    492,    460,    428,    396,
X       372,    356,    340,    324,    308,    292,    276,    260,
X       244,    228,    212,    196,    180,    164,    148,    132,
X       120,    112,    104,     96,     88,     80,     72,     64,
X	56,     48,     40,     32,     24,     16,      8,      0 };
SHAR_EOF
if test 3224 -ne "`wc -c < 'libst.h'`"
then
	echo shar: error transmitting "'libst.h'" '(should have been 3224 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libst.c'" '(3471 characters)'
if test -f 'libst.c'
then
	echo shar: will not over-write existing file "'libst.c'"
else
sed 's/^X//' << \SHAR_EOF > 'libst.c'
X/* libst.c - portable sound tools library
X*/
X
X/*
X** This routine converts from linear to ulaw.
X**
X** Craig Reese: IDA/Supercomputing Research Center
X** Joe Campbell: Department of Defense
X** 29 September 1989
X**
X** References:
X** 1) CCITT Recommendation G.711  (very difficult to follow)
X** 2) "A New Digital Technique for Implementation of Any
X**     Continuous PCM Companding Law," Villeret, Michel,
X**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
X**     1973, pg. 11.12-11.17
X** 3) MIL-STD-188-113,"Interoperability and Performance Standards
X**     for Analog-to_Digital Conversion Techniques,"
X**     17 February 1987
X**
X** Input: Signed 16 bit linear sample
X** Output: 8 bit ulaw sample
X*/
X
X#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
X#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
X#define CLIP 32635
X
Xunsigned char
Xst_linear_to_ulaw( sample )
Xint sample;
X    {
X    static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
X                               4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
X                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
X                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
X                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
X                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
X                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
X                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
X                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
X    int sign, exponent, mantissa;
X    unsigned char ulawbyte;
X
X    /* Get the sample into sign-magnitude. */
X    sign = (sample >> 8) & 0x80;		/* set aside the sign */
X    if ( sign != 0 ) sample = -sample;		/* get magnitude */
X    if ( sample > CLIP ) sample = CLIP;		/* clip the magnitude */
X
X    /* Convert from 16 bit linear to ulaw. */
X    sample = sample + BIAS;
X    exponent = exp_lut[( sample >> 7 ) & 0xFF];
X    mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
X    ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
X#ifdef ZEROTRAP
X    if ( ulawbyte == 0 ) ulawbyte = 0x02;	/* optional CCITT trap */
X#endif
X
X    return ulawbyte;
X    }
X
X/*
X** This routine converts from ulaw to 16 bit linear.
X**
X** Craig Reese: IDA/Supercomputing Research Center
X** 29 September 1989
X**
X** References:
X** 1) CCITT Recommendation G.711  (very difficult to follow)
X** 2) MIL-STD-188-113,"Interoperability and Performance Standards
X**     for Analog-to_Digital Conversion Techniques,"
X**     17 February 1987
X**
X** Input: 8 bit ulaw sample
X** Output: signed 16 bit linear sample
X*/
X
Xint
Xst_ulaw_to_linear_slow( ulawbyte )
Xunsigned char ulawbyte;
X    {
X    static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
X    int sign, exponent, mantissa, sample;
X
X    ulawbyte = ~ ulawbyte;
X    sign = ( ulawbyte & 0x80 );
X    exponent = ( ulawbyte >> 4 ) & 0x07;
X    mantissa = ulawbyte & 0x0F;
X    sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
X    if ( sign != 0 ) sample = -sample;
X
X    return sample;
X    }
SHAR_EOF
if test 3471 -ne "`wc -c < 'libst.c'`"
then
	echo shar: error transmitting "'libst.c'" '(should have been 3471 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libsst.h'" '(904 characters)'
if test -f 'libsst.h'
then
	echo shar: will not over-write existing file "'libsst.h'"
else
sed 's/^X//' << \SHAR_EOF > 'libsst.h'
X/* libsst.h - include file for SPARC sound tools library
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <sys/ioctl.h>
X#include <sbusdev/audioreg.h>
X#include <sun/audioio.h>
X
X#define SAMPLES_PER_SECOND 8192
X
Xint sst_open( );
Xvoid sst_close( /* int fd */ );
X
Xvoid sst_set_ger( /* int fd, value */ );
Xvoid sst_set_gr( /* int fd, value */ );
Xvoid sst_set_gx( /* int fd, value */ );
X
Xvoid sst_tones( /* int fd, dhz1, dhz2, thz, rhz, usec */ );
Xvoid sst_dtmf( /* int fd, char *dial, int usecper, usecpause */ );
SHAR_EOF
if test 904 -ne "`wc -c < 'libsst.h'`"
then
	echo shar: error transmitting "'libsst.h'" '(should have been 904 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libsst.c'" '(10463 characters)'
if test -f 'libsst.c'
then
	echo shar: will not over-write existing file "'libsst.c'"
else
sed 's/^X//' << \SHAR_EOF > 'libsst.c'
X/* libsst.c - SPARC sound tools library
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include "libsst.h"
X
X#define AUDBUF 1024
X
Xint
Xsst_open( )
X    {
X    int fd, i, play_level, record_level, gr, ger, gx;
X    struct audio_ioctl ai;
X    char *getenv(), *ep;
X
X    fd = open( "/dev/audio", O_RDWR );
X    if ( fd < 0 )
X	{
X	perror( "sst_open: open /dev/audio" );
X	exit( 1 );
X	}
X
X    /* Shrink audio device's queue size, to cut down time delay. */
X    i = AUDBUF;
X    if ( ioctl( fd, AUDIOSETQSIZE, &i ) < 0 )
X	{
X	perror( "sst_open: SETQSIZE" );
X	exit( 1 );
X	}
X
X    /* Set gains.  -10 <= ger <= 18,  -18 <= gr <= 12,  -18 <= gx <= 12. */
X    play_level = 75;
X    record_level = 75;
X    if ( (ep = getenv( "SST_PLAY" )) != NULL )
X	{
X	play_level = atoi( ep );
X	if ( play_level < 0 || play_level > 99 )
X	    {
X	    fprintf( stderr, "sst_open: SST_PLAY must be between 0 and 99\n" );
X	    exit( 1 );
X	    }
X	}
X    if ( (ep = getenv( "SST_RECORD" )) != NULL )
X	{
X	record_level = atoi( ep );
X	if ( record_level < 0 || record_level > 99 )
X	    {
X	    fprintf( stderr, "sst_open: SST_RECORD must be between 0 and 99\n" );
X	    exit( 1 );
X	    }
X	}
X
X    play_level = play_level * 59 / 100 - 28;
X    ger = play_level / 2;
X    gr = play_level - ger;
X    if ( ger < -10 )
X	{
X	ger = -10;
X	gr = play_level - ger;
X	}
X    if ( gr > 12 )
X	{
X	gr = 12;
X	ger = play_level - gr;
X	}
X    gx = record_level * 31 / 100 - 18;
X    sst_set_gr( fd, gr );
X    sst_set_ger( fd, ger );
X    sst_set_gx( fd, gx );
X
X    /*  Initialize the MMR2 register to send the output to either
X    **  the speaker or the earphone jack, depending on SST_EARPHONES.
X    */
X    ai.control = AUDIO_MAP_MMR2;
X    if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
X	{
X	perror( "sst_open: GETREG MMR2" );
X	exit( 1 );
X	}
X    if ( (ep = getenv( "SST_EARPHONES" )) != NULL )
X	ai.data[0] &= ~AUDIO_MMR2_BITS_LS;
X    else
X	ai.data[0] |= AUDIO_MMR2_BITS_LS;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_open: SETREG MMR2" );
X	exit( 1 );
X	}
X
X    return fd;
X    }
X
Xvoid
Xsst_close( fd )
Xint fd;
X    {
X    struct audio_ioctl ai;
X
X    ai.control = AUDIO_MAP_MMR1;
X    ai.data[0] = 0;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_close: SETREG MMR1" );
X	exit( 1 );
X	}
X    ai.control = AUDIO_MAP_MMR2;
X    ai.data[0] = 0;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_close: SETREG MMR2" );
X	exit( 1 );
X	}
X    close( fd );
X    }
X
X/* These are tables of values to be loaded into various gain registers.
X*/
X
Xstatic unsigned char ger_table[][2] = {
X    0xaa,	0xaa,	/* -10db */
X    0x79,	0xac,
X    0x41,	0x99,
X    0x9c,	0xde,
X    0x74,	0x9c,	/* -6db */
X    0x6a,	0xae,
X    0xab,	0xdf,
X    0x64,	0xab,
X    0x2a,	0xbd,
X    0x5c,	0xce,
X    0x00,	0x99,	/* 0db */
X    0x43,	0xdd,
X    0x52,	0xef,
X    0x55,	0x42,
X    0x31,	0xdd,
X    0x43,	0x1f,
X    0x40,	0xdd,	/* 6db */
X    0x44,	0x0f,
X    0x31,	0x1f,
X    0x10,	0xdd,
X    0x41,	0x0f,
X    0x60,	0x0b,
X    0x42,	0x10,	/* 12db */
X    0x11,	0x0f,
X    0x72,	0x00,
X    0x21,	0x10,
X    0x22,	0x00,
X    0x00,	0x0b,
X    0x00,	0x0f,	/* 18db */
X    };
X
X
Xstatic unsigned char gr_gx_table[][2] = {
X    0x8b,	0x7c,	/* -18db */
X    0x8b,	0x35,
X    0x8b,	0x24,
X    0x91,	0x23,
X    0x91,	0x2a,
X    0x91,	0x3b,
X    0x91,	0xf9,	/* -12db */
X    0x91,	0xb6,
X    0x91,	0xa4,
X    0x92,	0x32,
X    0x92,	0xaa,
X    0x93,	0xb3,
X    0x9f,	0x91,	/* -6db */
X    0x9b,	0xf9,
X    0x9a,	0x4a,
X    0xa2,	0xa2,
X    0xaa,	0xa3,
X    0xbb,	0x52,
X    0x08,	0x08,	/* 0db */
X    0x3d,	0xac,
X    0x25,	0x33,
X    0x21,	0x22,
X    0x12,	0xa2,
X    0x11,	0x3b,
X    0x10,	0xf2,	/* 6db */
X    0x02,	0xca,
X    0x01,	0x5a,
X    0x01,	0x12,
X    0x00,	0x32,
X    0x00,	0x13,
X    0x00,	0x0e,	/* 12db */
X    };
X
Xvoid
Xsst_set_ger( fd, value )
Xint fd, value;
X    {
X    struct audio_ioctl ai;
X
X    if ( ( value < -10 ) || ( value > 18 ) )
X	{
X	fprintf( stderr, "sst_set_ger: GER %d out of range\n", value );
X	return;
X	}
X
X    /*  Add 10 to the value to get the index into the table.  */
X    ai.control = AUDIO_MAP_GER;
X    ai.data[0] = ger_table[value + 10][1];
X    ai.data[1] = ger_table[value + 10][0];
X
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_ger: SETREG GER" );
X	exit( 1 );
X	}
X
X    ai.control = AUDIO_MAP_MMR1;
X    if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_ger: GETREG MMR1" );
X	exit( 1 );
X	}
X    ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GER;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_ger: SETREG MMR1" );
X	exit( 1 );
X	}
X    }
X
Xvoid
Xsst_set_gr( fd, value )
Xint fd, value;
X    {
X    struct audio_ioctl ai;
X
X    if ( ( value < -18 ) || ( value > 12 ) )
X	{
X	fprintf( stderr, "sst_set_gr: GR %d out of range\n", value );
X	return;
X	}
X
X    ai.control = AUDIO_MAP_GR;
X    ai.data[0] = gr_gx_table[value + 18][1];
X    ai.data[1] = gr_gx_table[value + 18][0];
X
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gr: SETREG GR" );
X	exit( 1 );
X	}
X
X    ai.control = AUDIO_MAP_MMR1;
X    if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gr: GETREG MMR1" );
X	exit( 1 );
X	}
X    ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GR;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gr: SETREG MMR1" );
X	exit( 1 );
X	}
X    }
X
Xvoid
Xsst_set_gx( fd, value )
Xint fd, value;
X    {
X    struct audio_ioctl ai;
X
X    if ( ( value < -18 ) || ( value > 12 ) )
X	{
X	fprintf( stderr, "sst_set_gx: GX %d out of range\n", value );
X	return;
X	}
X
X    /*  We add 18 to get the index into the table, since entry 0 represents
X    *  -18db.
X    */
X    ai.control = AUDIO_MAP_GX;
X    ai.data[0] = gr_gx_table[value + 18][1];
X    ai.data[1] = gr_gx_table[value + 18][0];
X
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gx: SETREG GX" );
X	exit( 1 );
X	}
X
X    ai.control = AUDIO_MAP_MMR1;
X    if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gx: GETREG MMR1" );
X	exit( 1 );
X	}
X    ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GX;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_set_gx: SETREG MMR1" );
X	exit( 1 );
X	}
X    }
X
Xvoid
Xsst_tones( fd, dhz1, dhz2, thz, rhz, usec )
Xint fd, dhz1, dhz2, thz, rhz, usec;
X    {
X    struct audio_ioctl ai;
X    int dval1, dval2, tval, rval;
X    unsigned char oldmmr2, newmmr2;
X
X    if ( dhz1 == 0 )
X	dval1 = 0;
X    else
X	{
X	dval1 = ( dhz1 * 128 + 63 ) / 1000;
X	if ( ( dval1 < 1 ) || ( dval1 > 255 ) )
X	    {
X	    fprintf(stderr, "sst_tones: dhz1 %d out of range\n", dhz1 );
X	    return;
X	    }
X	}
X
X    if ( dhz2 == 0 )
X	dval2 = 0;
X    else
X	{
X	dval2 = ( dhz2 * 128 + 63 ) / 1000;
X	if ( ( dval2 < 1 ) || ( dval2 > 255 ) )
X	    {
X	    fprintf(stderr, "sst_tones: dhz2 %d out of range\n", dhz2 );
X	    return;
X	    }
X	}
X
X    if ( thz == 0 )
X	tval = 0;
X    else
X	{
X	tval = ( thz * 128 + 63 ) / 2000;
X	if ( ( tval < 1 ) || ( tval > 255 ) )
X	    {
X	    fprintf(stderr, "sst_tones: thz %d out of range\n", thz );
X	    return;
X	    }
X	}
X
X    if ( rhz == 0 )
X	rval = 0;
X    else
X	{
X	rval = ( rhz * 128 + 63 ) / 2000;
X	if ( ( rval < 1 ) || ( rval > 255 ) )
X	    {
X	    fprintf(stderr, "sst_tones: rhz %d out of range\n", dhz2 );
X	    return;
X	    }
X	}
X
X    if ( ( dval1 != 0 || dval2 != 0 ) && ( tval != 0 || rval != 0 ) )
X	{
X	fprintf(stderr, "sst_tones: cannot use DTMF and TONE or RINGER at the same time\n", dhz2 );
X	return;
X	}
X
X    if ( tval != 0 && rval != 0 )
X	{
X	fprintf(stderr, "sst_tones: cannot use TONE and RINGER at the same time\n", dhz2 );
X	return;
X	}
X
X    ai.control = AUDIO_MAP_MMR2;
X    if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
X	{
X	perror( "sst_tones: GETREG MMR2" );
X	exit( 1 );
X	}
X    oldmmr2 = newmmr2 = ai.data[0];
X
X    if ( dval1 != 0 || dval2 != 0 )
X	{
X	newmmr2 |= AUDIO_MMR2_BITS_DTMF;
X	ai.control = AUDIO_MAP_FTGR;
X	ai.data[0] = dval1;
X	ai.data[1] = dval2;
X	if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	    {
X	    perror( "sst_tones: SETREG FTGR" );
X	    exit( 1 );
X	    }
X	}
X
X    if ( tval != 0 )
X	{
X	newmmr2 |= AUDIO_MMR2_BITS_TONE;
X	ai.control = AUDIO_MAP_FTGR;
X	ai.data[0] = tval;
X	ai.data[1] = 0;
X	if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	    {
X	    perror( "sst_tones: SETREG FTGR" );
X	    exit( 1 );
X	    }
X	}
X
X    if ( rval != 0 )
X	{
X	newmmr2 |= AUDIO_MMR2_BITS_RINGER;
X	ai.control = AUDIO_MAP_FTGR;
X	ai.data[0] = rval;
X	ai.data[1] = 0;
X	if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	    {
X	    perror( "sst_tones: SETREG FTGR" );
X	    exit( 1 );
X	    }
X	}
X
X    ai.control = AUDIO_MAP_MMR2;
X    ai.data[0] = newmmr2;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_tones: SETREG MMR2" );
X	exit( 1 );
X	}
X
X    usleep( usec );
X
X    ai.data[0] = oldmmr2;
X    if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
X	{
X	perror( "sst_tones: SETREG MMR2" );
X	exit( 1 );
X	}
X    }
X
Xvoid
Xsst_dtmf( fd, dial, usecper, usecpause )
Xint fd, usecper, usecpause;
Xchar *dial;
X    {
X    char *cp;
X
X    for ( cp = dial; *cp != '\0'; cp++ )
X	{
X	switch ( *cp )
X	    {
X	    case '1': sst_tones( fd, 703, 1211, 0, 0, usecper ); break;
X	    case '2': sst_tones( fd, 703, 1336, 0, 0, usecper ); break;
X	    case '3': sst_tones( fd, 703, 1492, 0, 0, usecper ); break;
X	    case 'A': sst_tones( fd, 703, 1648, 0, 0, usecper ); break;
X	    case '4': sst_tones( fd, 773, 1211, 0, 0, usecper ); break;
X	    case '5': sst_tones( fd, 773, 1336, 0, 0, usecper ); break;
X	    case '6': sst_tones( fd, 773, 1492, 0, 0, usecper ); break;
X	    case 'B': sst_tones( fd, 773, 1648, 0, 0, usecper ); break;
X	    case '7': sst_tones( fd, 859, 1211, 0, 0, usecper ); break;
X	    case '8': sst_tones( fd, 859, 1336, 0, 0, usecper ); break;
X	    case '9': sst_tones( fd, 859, 1492, 0, 0, usecper ); break;
X	    case 'C': sst_tones( fd, 859, 1648, 0, 0, usecper ); break;
X	    case '*': sst_tones( fd, 945, 1211, 0, 0, usecper ); break;
X	    case '0': sst_tones( fd, 945, 1336, 0, 0, usecper ); break;
X	    case '#': sst_tones( fd, 945, 1492, 0, 0, usecper ); break;
X	    case 'D': sst_tones( fd, 945, 1648, 0, 0, usecper ); break;
X
X	    case ' ': case '-': case '(': case ')': case '+':
X	    continue;	/* ignore */
X
X	    case ',': usleep( usecper ); break;	/* big pause */
X
X	    default:
X	    fprintf( stderr, "sst_dtmf: unknown dialing code '%c'\n", *cp );
X	    }
X	usleep( usecpause );
X	}
X    }
SHAR_EOF
if test 10463 -ne "`wc -c < 'libsst.c'`"
then
	echo shar: error transmitting "'libsst.c'" '(should have been 10463 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libfft.h'" '(526 characters)'
if test -f 'libfft.h'
then
	echo shar: will not over-write existing file "'libfft.h'"
else
sed 's/^X//' << \SHAR_EOF > 'libfft.h'
X/* libfft.h - include file for fast Fourier transform library
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
Xvoid initfft();
Xvoid fft();
SHAR_EOF
if test 526 -ne "`wc -c < 'libfft.h'`"
then
	echo shar: error transmitting "'libfft.h'" '(should have been 526 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'libfft.c'" '(2380 characters)'
if test -f 'libfft.c'
then
	echo shar: will not over-write existing file "'libfft.c'"
else
sed 's/^X//' << \SHAR_EOF > 'libfft.c'
X/* libfft.c - fast Fourier transform library
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <math.h>
X
X#define MAXFFTSIZE 32768
X#define LOG2_MAXFFTSIZE 15
X
Xstatic int bitreverse[MAXFFTSIZE], bits;
X
X/* initfft - initialize for fast Fourier transform
X**
X** b    power of two such that 2**nu = number of samples
X*/
Xvoid
Xinitfft( b )
Xint b;
X    {
X    register int i, j, k;
X
X    bits = b;
X    if ( bits > LOG2_MAXFFTSIZE )
X	{
X	fprintf(
X	    stderr, "%d is too many bits, max is %d\n", bits, LOG2_MAXFFTSIZE );
X	exit( 1 );
X	}
X
X    for ( i = ( 1 << bits ) - 1; i >= 0; --i )
X	{
X	k = 0;
X	for ( j = 0; j < bits; ++j )
X	    {
X	    k *= 2;
X	    if ( i & ( 1 << j ) )
X		k += 1;
X	    }
X	bitreverse[i] = k;
X	}
X    }
X
X/* fft - a fast Fourier transform routine
X**
X** xr   real part of data to be transformed
X** xi   imaginary part (normally zero, unless inverse transform in effect)
X** inv  flag for inverse
X*/
X
Xvoid
Xfft( xr, xi, inv )
Xfloat xr[], xi[];
Xint inv;
X    {
X    int n, n2, i, k, kn2, l, p;
X    float ang, s, c, tr, ti;
X    double ds, dc;
X
X    n = 1 << bits;
X    n2 = n / 2;
X
X    for ( l = 0; l < bits; ++l )
X	{
X	for ( k = 0; k < n; k += n2 )
X	    {
X	    for( i = 0; i < n2; ++i, ++k )
X		{
X		p = bitreverse[k / n2];
X		ang = 6.283185 * p / n;
X#ifdef notdef
X		c = cos( ang );
X		s = sin( ang );
X#else notdef
X		sincos( ang, &ds, &dc );
X		s = ds;
X		c = dc;
X#endif notdef
X		kn2 = k + n2;
X		if ( inv )
X		    s = -s;
X		tr = xr[kn2] * c + xi[kn2] * s;
X		ti = xi[kn2] * c - xr[kn2] * s;
X		xr[kn2] = xr[k] - tr;
X		xi[kn2] = xi[k] - ti;
X		xr[k] += tr;
X		xi[k] += ti;
X		}
X	    }
X	n2 /= 2;
X	}
X
X    for ( k = 0; k < n; ++k )
X	{
X	i = bitreverse[k];
X	if ( i <= k )
X	    continue;
X	tr = xr[k];
X	ti = xi[k];
X	xr[k] = xr[i];
X	xi[k] = xi[i];
X	xr[i] = tr;
X	xi[i] = ti;
X	}
X
X    /* Finally, multiply each value by 1/n, if this is the forward transform. */
X    if ( ! inv )
X	{
X	register float f;
X
X	f = 1.0 / n;
X	for( i = 0; i < n ; ++i )
X	    {
X	    xr[i] *= f;
X	    xi[i] *= f;
X	    }
X	}
X    }
SHAR_EOF
if test 2380 -ne "`wc -c < 'libfft.c'`"
then
	echo shar: error transmitting "'libfft.c'" '(should have been 2380 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'echoplex.c'" '(2880 characters)'
if test -f 'echoplex.c'
then
	echo shar: will not over-write existing file "'echoplex.c'"
else
sed 's/^X//' << \SHAR_EOF > 'echoplex.c'
X/* echoplex.c - echo generator
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "libst.h"
X
X#define abs(a) ((a) >= 0 ? (a) : -(a))
X
X#define FADE_THRESH 30
X#define MYBUFSIZ 256
X#define DELAYBUFSIZ ( 50 * SAMPLES_PER_SECOND )
X#define MAXDELAYS 1000
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *f;
X    char mybuf[MYBUFSIZ];
X    int argn, numdelays;
X    register int i, j, c, lc, plc, pplc, ppplc;
X    static int delaybuf[DELAYBUFSIZ];
X    float delay[MAXDELAYS], atten[MAXDELAYS];
X    int samples[MAXDELAYS], maxsamples;
X    double atof();
X    char *usage = "usage:  %s <delay> <atten> [<delay> <atten>] ... [<file>]\n";
X
X    argn = 1;
X    numdelays = 0;
X    maxsamples = 0;
X
X    while ( argn + 1 < argc )
X	{
X	delay[numdelays] = atof( argv[argn++] );
X	atten[numdelays] = atof( argv[argn++] );
X	samples[numdelays] = delay[numdelays] * SAMPLES_PER_SECOND;
X	if ( samples[numdelays] < 1 )
X	    {
X	    fprintf( stderr, "%s: delay must positive, aye!\n", argv[0] );
X	    exit( 1 );
X	    }
X	if ( samples[numdelays] > DELAYBUFSIZ )
X	    {
X	    fprintf(
X		stderr, "%s: delay must be less than %g seconds\n",
X		argv[0], DELAYBUFSIZ / (float) SAMPLES_PER_SECOND );
X	    exit( 1 );
X	    }
X	if ( atten[numdelays] < 0.0 )
X	    {
X	    fprintf( stderr, "%s: attenuation must positive, aye!\n", argv[0] );
X	    exit( 1 );
X	    }
X	if ( samples[numdelays] > maxsamples )
X	    maxsamples = samples[numdelays];
X	++numdelays;
X	}
X
X    if ( argn == argc )
X	f = stdin;
X    else
X	{
X	f = fopen( argv[argn], "r" );
X	if ( f == NULL )
X	    {
X	    perror( argv[argn] );
X	    exit( 1 );
X	    }
X	++argn;
X	}
X
X    if ( argn != argc )
X	{
X	fprintf( stderr, usage, argv[0] );
X	exit( 1 );
X	}
X
X
X    setbuffer( stdout, mybuf, MYBUFSIZ );
X
X    for ( i = 0; i < maxsamples; ++i )
X	delaybuf[i] = 0;
X
X    for ( i = 0; (c = getc( f )) != EOF; i = ( i + 1 ) % maxsamples )
X	{
X	lc = st_ulaw_to_linear( c );
X	for ( j = 0; j < numdelays; ++j )
X	    lc = lc + delaybuf[( i + maxsamples - samples[j] ) % maxsamples] * atten[j];
X	LINCLIP( lc );
X	delaybuf[i] = lc;
X	putchar( st_linear_to_ulaw( lc ) );
X	}
X
X    for ( ppplc = pplc = plc = MAXLIN;
X	  abs(lc) + abs(plc) + abs(pplc) + abs(ppplc) > FADE_THRESH / 4;
X	  i = ( i + 1 ) % maxsamples )
X	{
X	lc = 0;
X	for ( j = 0; j < numdelays; ++j )
X	    lc = lc + delaybuf[( i + maxsamples - samples[j] ) % maxsamples] * atten[j];
X	LINCLIP( lc );
X	delaybuf[i] = lc;
X	putchar( st_linear_to_ulaw( lc ) );
X	ppplc = pplc;
X	pplc = plc;
X	plc = lc;
X	}
X
X    exit( 0 );
X    }
SHAR_EOF
if test 2880 -ne "`wc -c < 'echoplex.c'`"
then
	echo shar: error transmitting "'echoplex.c'" '(should have been 2880 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'echoplex.1'" '(871 characters)'
if test -f 'echoplex.1'
then
	echo shar: will not over-write existing file "'echoplex.1'"
else
sed 's/^X//' << \SHAR_EOF > 'echoplex.1'
X.TH echoplex 1 "20 November 1989"
X.SH NAME
Xechoplex - echo generator for sound files
X.SH SYNOPSIS
Xechoplex <delay> <atten> [<delay> <atten>] ... [<file>]
X.SH DESCRIPTION
XFilters input to output with an echo added for each <delay> <atten> pair
Xspecified.
X<delay> is in seconds, while <atten> is an attenuation factor between
Xzero and one.
XWhen using multiple delays, be careful that the attenuations sum to
Xless than one, or positive feedback may result.
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 871 -ne "`wc -c < 'echoplex.1'`"
then
	echo shar: error transmitting "'echoplex.1'" '(should have been 871 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lintoulaw.c'" '(1080 characters)'
if test -f 'lintoulaw.c'
then
	echo shar: will not over-write existing file "'lintoulaw.c'"
else
sed 's/^X//' << \SHAR_EOF > 'lintoulaw.c'
X/* lintoulaw.c - convert linear to ulaw
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "libst.h"
X
X#define MYBUFSIZ 256
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *f;
X    char mybuf[MYBUFSIZ];
X    double atof();
X    int c;
X    float lc;
X
X    if ( argc == 1 )
X	f = stdin;
X    else if ( argc == 2 )
X	{
X	f = fopen( argv[1], "r" );
X	if ( f == NULL )
X	    {
X	    perror( argv[1] );
X	    exit( 1 );
X	    }
X	}
X    else
X	{
X	fprintf( stderr, "usage:  %s [<file>]\n", argv[0] );
X	exit( 1 );
X	}
X    setbuffer( stdout, mybuf, MYBUFSIZ );
X
X    while ( fscanf( f, "%g", &lc ) == 1 )
X	{
X	c = st_linear_to_ulaw( (int) lc );
X	putchar( c );
X	}
X
X    exit( 0 );
X    }
SHAR_EOF
if test 1080 -ne "`wc -c < 'lintoulaw.c'`"
then
	echo shar: error transmitting "'lintoulaw.c'" '(should have been 1080 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lintoulaw.1'" '(695 characters)'
if test -f 'lintoulaw.1'
then
	echo shar: will not over-write existing file "'lintoulaw.1'"
else
sed 's/^X//' << \SHAR_EOF > 'lintoulaw.1'
X.TH lintoulaw 1 "20 November 1989"
X.SH NAME
Xlintoulaw - convert linear sound file to ulaw
X.SH SYNOPSIS
Xlintoulaw [<file>]
X.SH DESCRIPTION
XConverts a file of numbers between -32768 and 32767, as produced for example
Xby ulawtolin(1), into ulaw format.
X.SH "SEE ALSO"
Xulawtolin(1)
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 695 -ne "`wc -c < 'lintoulaw.1'`"
then
	echo shar: error transmitting "'lintoulaw.1'" '(should have been 695 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mix.c'" '(1627 characters)'
if test -f 'mix.c'
then
	echo shar: will not over-write existing file "'mix.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mix.c'
X/* mix.c - mix multiple sound files
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include <strings.h>
X#include "libst.h"
X
X#define MAXFILES 64	/* the kernel's got a limit, why shouldn't I? */
X#define MYBUFSIZ 256
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *files[MAXFILES];
X    char mybuf[MYBUFSIZ];
X    int nfiles, i, c, sum, gotone;
X
X    nfiles = argc - 1;
X    if ( nfiles < 2 )
X	{
X	fprintf( stderr, "usage:  %s <file1> <file2> [<fileN> ...]\n", argv[0] );
X	exit( 1 );
X	}
X
X    for ( i = 0; i < nfiles; ++i )
X	{
X	if ( strcmp( argv[i + 1], "-" ) == 0 )
X	    files[i] = stdin;
X	else
X	    {
X	    files[i] = fopen( argv[i + 1], "r" );
X	    if ( files[i] == NULL )
X		{
X		perror( argv[i + 1] );
X		exit( 1 );
X		}
X	    }
X	}
X    setbuffer( stdout, mybuf, MYBUFSIZ );
X    
X    for ( ; ; )
X	{
X	sum = 0;
X	gotone = 0;
X	for ( i = 0; i < nfiles; ++i )
X	    {
X	    if ( files[i] != NULL )
X		{
X		c = getc( files[i] );
X		if ( c == EOF )
X		    {
X		    fclose( files[i] );
X		    files[i] = NULL;
X		    }
X		else
X		    {
X		    gotone = 1;
X		    sum += st_ulaw_to_linear( (unsigned char) c );
X		    }
X		}
X	    }
X	if ( gotone == 0 )
X	    break;
X	LINCLIP( sum );
X	putchar( st_linear_to_ulaw( sum ) );
X	}
X
X    exit( 0 );
X    }
SHAR_EOF
if test 1627 -ne "`wc -c < 'mix.c'`"
then
	echo shar: error transmitting "'mix.c'" '(should have been 1627 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mix.1'" '(665 characters)'
if test -f 'mix.1'
then
	echo shar: will not over-write existing file "'mix.1'"
else
sed 's/^X//' << \SHAR_EOF > 'mix.1'
X.TH mix 1 "20 November 1989"
X.SH NAME
Xmix - mix multiple sound files
X.SH SYNOPSIS
Xmix <file1> <file2> ...
X.SH DESCRIPTION
XCombines multiple sound files into one.
XThe combination is done by converting to linear, adding, and
Xconverting back to ulaw.
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 665 -ne "`wc -c < 'mix.1'`"
then
	echo shar: error transmitting "'mix.1'" '(should have been 665 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pitch.c'" '(2825 characters)'
if test -f 'pitch.c'
then
	echo shar: will not over-write existing file "'pitch.c'"
else
sed 's/^X//' << \SHAR_EOF > 'pitch.c'
X/* pitch.c - change the pitch of a sound file
X**
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <stdio.h>
X#include "libst.h"
X
X#define MYBUFSIZ 256
X
X#define SAMPLES_PER_CHUNK 1024
X#define LOG2_SPC 10
X#define HALF_SPC 512
X
X#define CHUNK_USE_FRAC 0.333333  /* only use the middle 1/3 of each chunk */
X
Xmain( argc, argv )
Xint argc;
Xchar *argv[];
X    {
X    FILE *f;
X    char mybuf[MYBUFSIZ];
X    float scale;
X    double atof();
X    int c, i, j, k, pstart, pend, plen;
X    int linbuf[SAMPLES_PER_CHUNK];
X    float xr[SAMPLES_PER_CHUNK], xi[SAMPLES_PER_CHUNK];
X
X    if ( argc < 2 || argc > 3 )
X	{
X	fprintf( stderr, "usage:  %s <factor> [<file>]\n", argv[0] );
X	exit( 1 );
X	}
X
X    scale = atof( argv[1] );
X    if ( scale == 0.0 )
X	{
X	fprintf( stderr, "%s: scale factor required\n", argv[0] );
X	exit( 1 );
X	}
X
X    if ( argc == 2 )
X	f = stdin;
X    else if ( argc == 3 )
X	{
X	f = fopen( argv[2], "r" );
X	if ( f == NULL )
X	    {
X	    perror( argv[2] );
X	    exit( 1 );
X	    }
X	}
X    initfft( LOG2_SPC );
X
X    i = 0;
X    pstart = 0;
X    pend = SAMPLES_PER_CHUNK * 0.5 + SAMPLES_PER_CHUNK * CHUNK_USE_FRAC * 0.5;
X    while ( (c = getc( f )) != EOF )
X	{
X	linbuf[i] = st_ulaw_to_linear( c );
X	++i;
X	if ( i == SAMPLES_PER_CHUNK )
X	    {
X	    shiftchunk( linbuf, i, scale, pstart, pend );
X	    if ( pstart == 0 )
X		{
X		pstart = SAMPLES_PER_CHUNK * 0.5 - SAMPLES_PER_CHUNK * CHUNK_USE_FRAC * 0.5;
X		plen = pend - pstart;
X		}
X	    for ( j = 0, k = j + plen; k < SAMPLES_PER_CHUNK; j++, k++ )
X		linbuf[j] = linbuf[k];
X	    i -= plen;
X	    }
X	}
X    if ( i > 0 )
X	{
X	pend = i;
X	shiftchunk( linbuf, i, scale, pstart, pend );
X	}
X
X    exit( 0 );
X    }
X
Xshiftchunk( linbuf, i, scale, pstart, pend )
Xint linbuf[SAMPLES_PER_CHUNK];
Xfloat scale;
Xint i, pstart, pend;
X    {
X    register int j, k;
X    float xr[SAMPLES_PER_CHUNK], xi[SAMPLES_PER_CHUNK];
X    float sxr[SAMPLES_PER_CHUNK], sxi[SAMPLES_PER_CHUNK];
X
X    for ( j = 0; j < i; ++j )
X	{
X	xr[j] = linbuf[j];
X	xi[j] = 0.0;
X	}
X    for ( ; j < SAMPLES_PER_CHUNK; ++j )
X	{
X	xr[j] = 0.0;
X	xi[j] = 0.0;
X	}
X
X    fft( xr, xi, 0 );
X
X    for ( j = 0; j < SAMPLES_PER_CHUNK; ++j )
X	{
X	k = (int) ( ( j - HALF_SPC ) * scale + 0.5 ) + HALF_SPC;
X	if ( k >= 0 && k < SAMPLES_PER_CHUNK )
X	    {
X	    sxr[j] = xr[k];
X	    sxi[j] = xi[k];
X	    }
X	else
X	    {
X	    sxr[j] = 0.0;
X	    sxi[j] = 0.0;
X	    }
X	}
X
X    fft( sxr, sxi, 1 );
X
X    for ( j = pstart; j < pend; ++j )
X	putchar( st_linear_to_ulaw( (int) sxr[j] ) );
X    }
SHAR_EOF
if test 2825 -ne "`wc -c < 'pitch.c'`"
then
	echo shar: error transmitting "'pitch.c'" '(should have been 2825 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pitch.1'" '(830 characters)'
if test -f 'pitch.1'
then
	echo shar: will not over-write existing file "'pitch.1'"
else
sed 's/^X//' << \SHAR_EOF > 'pitch.1'
X.TH pitch 1 "20 November 1989"
X.SH NAME
Xpitch - change the pitch of a sound file
X.SH SYNOPSIS
Xpitch <factor> [<file>]
X.SH DESCRIPTION
XUses the fast Fourier transform to scale the frequencies in a sound file
Xby the specified factor.
X.SH "SEE ALSO"
Xspeed(1), volume(1)
X.SH BUGS
XDoesn't work.  Perhaps someone will be kind enough to send me a fixed version,
XI admit my understanding of the FFT is extremely limited.
X.SH AUTHOR
XCopyright (C) 1989 by Jef Poskanzer.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
SHAR_EOF
if test 830 -ne "`wc -c < 'pitch.1'`"
then
	echo shar: error transmitting "'pitch.1'" '(should have been 830 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0



More information about the Alt.sources mailing list