[comp.sources.amiga] v90i018: chatterbox - play sounds when certain events occur, Part01/02

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (01/17/90)

Submitted-by: karl@sugar.hackercorp.com (Karl Lehenbauer)
Posting-number: Volume 90, Issue 018
Archive-name: audio/chatterbox/part01

Chatterbox allows one to load and play sounds on the occurrence of several 
detectable events, such as disk insertion and deletion, calling
the DisplayBeep function, a time interval elapsing, preferences changing
and activation and deactivation of Chatterbox's window.

In order that it not eat up your precious "chip" RAM, chatterbox uses your 
"fast" RAM (if you have any) to cache the loaded sounds, only copying them 
to chip RAM when it's time to play them.

[ The binary posting includes, ``some small samples for use with
  chatterbox and other programs that can read IFF 8SVX sound files.''
  ...tad ]


#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  Makefile README blather.c channels.h chatter.h
#   chatterbox.info.uu cleanup.c config.c deferredload.c display.c
#   iff.c loop.c main.c menus.c rando.c rerandom.c sample.h
#   samplechip.c setwait.c signals.c timer.c windows.pw.uu
# Wrapped by tadguy@xanth on Tue Jan 16 21:23:12 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1511 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS=	+p +Irad:sounds/includes.pre
X#CFLAGS=	-n +p +Irad:sounds/includes.pre
X#CFLAGS=	-n +p +Irad:sounds/includes.pre -DDEBUG
X
X#
X# Do a -DTRACKER to enable tracking of all AllocMem and FreeMem calls
X#
X
X#SDBFLAG= -g
XSDBFLAG=
X
XPREFLAGS= +p
X
XHFILES= chatter.h channels.h sample.h
X
XOFILES= 8svx.o cleanup.o iff.o tracker.o main.o player.o setwait.o \
Xloop.o timer.o windows.o display.o blather.o config.o samplechip.o \
Xrando.o signals.o rerandom.o deferredload.o menus.o
X
X# these are for 'make shar'
XCFILES1= 8svx.c cleanup.c iff.c tracker.c main.c player.c setwait.c
X
XCFILES2=  config.c samplechip.c \
Xloop.c timer.c windows.c display.c blather.c \
Xrando.c signals.c rerandom.c deferredload.c menus.c
X
X.c.o:
X	cc $(CFLAGS) $*.c
X
Xall:	chatterbox
X	say "ready"
X
Xclean:
X	-delete #?.o
X	-delete #?.bak
X	-delete includes.pre
X	-delete #?.dbg
X
Xscratch:	clean	all
X
Xchatterbox:	rad:sounds/includes.pre $(OFILES)
X	ln $(SDBFLAG) +Q -o chatterbox $(OFILES) -lcl32
X
Xincludes.pre:	includes.c $(HFILES)
X	cc $(PREFLAGS) +Hincludes.pre includes.c
X
Xrad:sounds/includes.pre:	includes.pre
X	-makedir rad:sounds
X	copy includes.pre rad:sounds/includes.pre
X
Xshar:
X	uuencode >chatterbox.info.uu chatterbox.info chatterbox.info
X	uuencode >windows.pw.uu windows.pw windows.pw
X	shar >rad:chatterbox1.shar README Makefile $(HFILES) $(CFILES1)
X	shar >rad:chatterbox2.shar $(HFILES) $(CFILES2) \
Xchatterbox.info.uu windows.pw.uu
X	uuencode >chatterbox.uu chatterbox chatterbox
X	shar >rad:chatterboxbin.shar README chatterbox.info.uu chatterbox.uu
END_OF_FILE
if test 1511 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(12043 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
Xchatterbox - have the Amiga play IFF audio sample files when events occur
X
XVersion 1.0 -- first public release
X
XCopyright (C) 1989 by Karl Lehenbauer, All Rights Reserved
X  This code is freely redistributable (and reusable) for 
X  noncommercial purposes providing this notice is retained.
X
X
XIntro
X-----
X
XChatterbox is largely the result of two evenings work, the 22nd and 23rd 
Xof May, 1989.  One reason for the fast start was that I was able to reuse
Xa lot of code from some other Amiga programs I've written.
X
XIn any case, Chatterbox allows one to load and play sounds on the occurence
Xof several detectable events, such as disk insertion and deletion, calling
Xthe DisplayBeep function, a time interval elapsing, preferences chaging,
Xactivation and deactivation of Chatterbox's window, and eventually, other 
Xevents as well.  In order that it not eat up your precious "chip" RAM,
Xchatterbox uses your "fast" RAM (if you have any) to cache the loaded
Xsounds, only copying them to chip RAM when it's to play them.
X
XThere are a maximum of 32 sounds that may be defined for each type of
Xevent that Chatterbox can play sounds for, although hard disk users may
Xhave many more sounds triggered by timer events (more on this later).
X
X
XRunning Chatterbox
X------------------
X
XIf you got Chatterbox on a disk and everything's set up properly, you should
Xbe able to click open the disk, then doubleclick on the chatterbox icon, and
Xoff it goes.  If you downloaded this from somewhere or something, you may
Xhave to set it up yourself.  If so, please examine the "Configuring 
XChatterbox" section following this one.
X
XChatterbox can also be run from the CLI.  Thus, it could be started
Xautomatically by your boot sequence (by starting it from your 
Xs:startups-sequence).  You'll need to do a "run" or "runback" on it
Xif you do start it in the startup sequence, as it does not return
Xuntil you exit it by clicking the close gadget in the Chatterbox window,
Xselect the "quit" option in Chatterbox's pull-down menu or entering
XControl-C in the window of the CLI from which Chatterbox was started.
X
X
XConfiguring Chatterbox
X----------------------
X
XChatterbox looks in ChatterBox: for a configuration file named "config.data".
XChatterBox: should be the name of the floppy containing the config file and
Xall the sounds, or it can be an assign to a directory on your hard disk,
Xfloppy, RAM disk, or whatever.  The format for config.data is very simple.
XA number of keywords may occur in column one of a line.  After a line
Xcontaining a keyword (and possibly, optional parameters), a number of file
Xnames are specified, with a blank in column one and the name starting in
Xcolumn two.  Chatterbox is pretty stupid about this, so it is important
Xthat you adhere to this format.  For example, if you wanted to play the
Xsound of a toilet flush (named "Toilet") or a car crash (named "CarCrash")
Xwhen a disk is removed while chatterbox is running, you would put the
Xfollowing three lines in your config.data file:
X
Xdiskout
X Toilet
X CarCrash
X
XNote that the keywords must be all lower case.  The keywords and their
Xfunctions are explained below:
X
X	diskin - play a sound when a disk is inserted
X	diskout - play a sound when a disk is removed
X	activate - play a sound when chatterbox's window is activated
X	deactivate - play a sound when chatterbox's window is deactivated
X	beep - play a sound on the next occurence of a DisplayBeep
X	timer - play a sound every so often (default is every five minutes)
X	preferences - play a sound when preferences change (weird, but hey)
X
XFollowing the keyword, specify the names of the sample files, one to a
Xline with a blank in column one and the name starting in column two,
Xup to 32 sounds.  If a sound is repeated in more than one event's list,
Xit will still only be loaded once.  A sample config.data file occurs at 
Xthe end of this document.
X
X
XMemory Considerations
X---------------------
X
XThere are two types of memory on the Amiga, "chip" and "fast."  So-called
Xchip RAM is memory that can be accessed by the custom chips in the Amiga.
XWhen a sound is played, it must reside in chip RAM.  Graphics displays
Xmust reside in chip RAM when they are being displayed, and some other
Xthings as well. Sounds, too, must reside in chip RAM when they're being
Xplayed.  Amigas right now have 512K bytes of chip RAM, although 
Xthe forthcoming "fat Agnes" will raise that limit to one megabyte.
X
X"Fast" RAM is basically any RAM that is not "chip."  Unlike chip RAM, the
Xcustom chips cannot access fast RAM.  Fast RAM is called "fast" because
Xthe 68000 microprocessor can access this memory without delays caused by
Xthe custom chips stealing memory cycles from the CPU.  (Don't worry at
Xthe idea of the custom chips slowing the 68000, as the blitter, for example,
Xis much more efficient doing what it does that the 68000 would be in the
Xsame number of cycles.)  Note that not all fast RAM is fast.  Specifically,
Xthe second 512K of RAM that comes in the Amiga 2000 and the internal 512K
XRAM upgrade for the Amiga 500 are wired to ultimately support the "fat Agnes"
Xchip.  As such, they still incur the performance hits when the blitter is
Xin heavy use and/or lots of other DMA (hires display, etc) is occuring.
X
XAs mentioned before, if you have fast RAM (or any non-chip RAM, as above),
XChatterbox loads and maintains its sounds in non-chip RAM, copying them
Xto chip RAM only as needed, and freeing them when they're done playing.
XIt's rather clever about it, like it won't free until it's completely
Xdone if it's playing multiple times.
X
XChatterbox tries to chew up as much memory as you ask it to.  This means
Xit can cause low memory situations on your machine.  If you run into 
Xproblems, don't ask it to load as many sounds.  It would be a relatively
Xtrivial thing for Chatterbox to insure that and adequate amount of memory
Xremained by refusing to load any more sounds when the available memory
Xdropped below a certain limit.  It would be driven by a line in the command
Xfile.  But I'm burnt out on it and will be saving that for a new version.
X
X
XSound File Format
X-----------------
X
XSounds files are expected to be in IFF 8SVX format.  Perfect Sound and
XAudiomaster files are known to be compatible.
X
X
XUsing Chatterbox with a Hard Disk
X---------------------------------
X
XTo install Chatterbox on a hard disk, simply create a directory containing
Xall the sample files you want to use and a config.data file, and do an
X'assign ChatterBox:' to that directory.  (For example, if the sounds were
Xin fs1:data/sounds, use 'assign ChatterBox: fs1:data/sounds')  Then, put
Xchatterbox in your C: or run it explicitly in your s:startup-sequence, or
Xwhatever, and, as long as no floppy is inserted called ChatterBox at the
Xtime (and perhaps later), you'll get your samples off hard disk.
X
XAn additional feature for hard disk users is the "noload" option for sounds
Xthat are to play when the timer event trips.  Noload is selected by having
Xit be the first word after 'timer' on the timer command line.  If minimum
Xand maximum time intervals are specified on the line, they come after
Xthe "noload" keyword.  If "noload" is selected, Chatterbox will defer
Xloading in any of the sounds associated with the timer event until needed.
X(This is not useful for floppy-only operation unless you can dedicate a
Xdrive to sounds or don't mind randomly obeying requesters for them.)
X
XIf noload is selected, Chatterbox loads and plays the sound at the time
Xit is to play it, rather than the usual loading of all the sounds at the
Xbeginning and random play from them.  When it is finished, it deallocates
Xthe sound.  When "noload" is selected and certain sounds in the list of
Xsounds to play for the timer event are the same as sounds for other events,
XChatterbox plays but does not load the sound from disk (as it is already 
Xmemory-resident), nor does it deallocate the sound when finished.
X
XA total of 256 deferred timer sounds may be defined.
X
X
XConfiguring The Timer Event
X---------------------------
X
XIn addition to the "noload" option, the "timer" keyword can additionally
Xhave a low and high number of seconds.  The specifies the range of time
Xchatterbox will want between speaking.  For example,
X
Xtimer noload 300 600
X
X...would tell chatterbox not to load the sounds defined for timer events
Xuntil they're played, and to wait from between five and ten minutes between
Xplaying them.
X
Xtimer 3600 3600
X
X...would tell chatterbox to play a sound once an hour, and the abcense of
Xthe "noload" option tells it to load in all the sounds listed to be played
Xon the occurence of timer events.
X
X
XChatterbox's Sound Selection Algorithms
X---------------------------------------
X
XChatterbox implements "random selection without replacement" in determining
Xwhat sample to play next when more than one sample is defined to play for
Xa given function.  What this means is that each sound will play at least
Xone time before a given sound repeats, for a given "pass" through the list
Xof sounds.  Note that sounds may still occasionally occur back-to-back.  
XFor example, if there are four sounds for a certain event type and 
Xchatterbox plays the third sound last, then after playing the last sound, 
Xchatterbox rerandomizes the sounds (as it does) and, by chance, ends up 
Xwith the third sound first, the third sound will be heard to play twice in 
Xa row.  Nonetheless, you will hear all the other sounds defined for that 
Xevent before you hear the third sound an additional time.  This may be
Xchanged later -- it's an easy fix.
X
XNote that if 'noload' is selected, Chatterbox does not do random selection
Xwithout repacement for timer events.  The idea is that you have a boatload
Xof samples on disk and they're not playing that often, so you don't really 
Xcare so much about hearing repeats.
X
X
XSource Code
X-----------
X
XThe source code is included, at least it was when I shipped it out.
XThe code was written to run under Manx Aztec C 3.6a.  You should be
Xable to compile and go.
X
XNote that the file windows.pw is a Power Windows 2.0 file.  Power Windows
Xwas used to generate the file windows.c, which is included in the
Xdistribution.
X
X
X
XOnly A Programmer Would Say "That's not a bug."
X-----------------------------------------------
X
XIf you exit Chatterbox by clicking in its "close window" gadget and the
XChatterbox window was not active, Chatterbox will begin playing a sound
Xthen kill it right away as it exits.  This is because when you click the
Xclose gadget on an inactive window, Intuition sends a "window activated" 
Xmessage (which can trigger Chatterbox to play a sound) then it sends a 
X"close window" message which tells Chatterbox to exit.  I suppose the
Xfix would be to receive the window activate and delay a bit before starting
Xthe sound, allowing the receipt of a close to cancel the sound, but that
Xwould mean a delay in starting the sound on the activate.  Alternatively,
Xit could wait until all sounds had finished playing on a "close window"
Xbefore exiting. I'm just gonna leave it the way it is, at least for now.
X
X
XAnyway, have fun with it.
X
X
XKarl Lehenbauer @ The Hacker's Haven, 26-May-89
X(Usenet: uunet!sugar!karl, Internet/BITNET: karl@sugar.hackercorp.com)
X3918 Panorama
XMissouri City, Texas  77459
X(713) 274-5184 (daytime)
X
X
X
XSample config.data file
X-----------------------
X
XThis sample file plays the sound "disk_inserted" when a disk inserted
Xmessage is received by Chatterbox, "disk_removed" when one is removed,
X"window_activated" when the Chatterbox window is activated, 
X"window_deactivated" when it is deactivated, preferences_changed when
Xpreferences change, "low_bell" when a DisplayBeep call is made, and
X"bass_snap", "bell", "drip", "hammer", "rise", "whip", "synth_echo",
X"low_bell", or "low_smash" once every 20 to 120 seconds, loading the
Xtimer sounds from hard disk when they're needed.
X
Xdiskin
X disk_inserted
Xdiskout
X disk_removed
Xtimer noload 20 120
X bass_snap
X bell
X drip
X hammer
X rise
X whip
X synth_echo
X low_bell
X low_smash
Xbeep
X low_bell
Xactivate
X window_activated
Xdeactivate
X window_deactivated
Xpreferences
X preferences_changed
END_OF_FILE
if test 12043 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'blather.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'blather.c'\"
else
echo shar: Extracting \"'blather.c'\" \(1052 characters\)
sed "s/^X//" >'blather.c' <<'END_OF_FILE'
X/* sound effect gimmick player - blather (output) routine */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "assert.h"
X
X#include "iff.h"
X#include "8svx.h"
X
X#include "sample.h"
X#include "chatter.h"
X
Xextern int timer_noload;
X
Xextern  struct gab_info gab_data[N_GAB_TYPES];
X
Xblather(gab_type)
Xint gab_type;
X{
X	struct gab_info *gabp;
X	int nitems;
X	Sample *sampleptr;
X
X	/* if it's a timer event and they've specified deferred loading
X	 * of samples for timer events, play a deferred sound.  
X	 */
X	if ((gab_type == GAB_EVERY_SO_OFTEN) && (timer_noload))
X	{
X		PlayDeferredSound();
X		return;
X	}
X
X	/* otherwise play a loaded sound */
X
X	gabp = &gab_data[gab_type];
X
X	nitems = gabp->n_gab_items;
X
X	if (nitems == 0)
X		return;
X
X	sampleptr = gabp->Samples[gabp->next_play_gab_item++];
X
X	ASSERT_SAMPLE_MAGIC(sampleptr);
X
X	PlayChannelSample(sampleptr,64,rando(2));
X
X	if (gabp->next_play_gab_item >= gabp->n_gab_items)
X		rerandomize(gab_type);
X}
END_OF_FILE
if test 1052 -ne `wc -c <'blather.c'`; then
    echo shar: \"'blather.c'\" unpacked with wrong size!
fi
# end of 'blather.c'
fi
if test -f 'channels.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'channels.h'\"
else
echo shar: Extracting \"'channels.h'\" \(1353 characters\)
sed "s/^X//" >'channels.h' <<'END_OF_FILE'
X/* channels.h - karl's smus structure that defines stuff about channels */
X
X/* define the IOB array entries in sound structures */
X
X#define MAX_CHANNELS 4
X
X#define MAX_CHANNEL_IOBS 7
X
X#define ALLOC_IOB 0		/* Use this IOB when allocating a channel */
X#define ONESHOT_IOB 1	/* Used for oneshot portion of musical notes */
X#define LOOP_IOB 2		/* Use to play the looped part of the sound */
X#define STOP_IOB 3		/* Use this IOB to stop playing the sound */
X#define PERVOL_IOB 4	/* Use to change a playing sound's period & volume */
X#define PRECEDENCE_IOB 5	/* Use to change a playing sound's precedence */
X#define FREE_IOB 6		/* Use to release the allocated channel */
X
Xtypedef struct ChannelStruct
X{
X	int flags;
X	struct SMUS_IOAudio
X	{
X		struct IOAudio smusIOB;
X		struct ChannelStruct *channelp;
X	} *IOBs[MAX_CHANNEL_IOBS];
X	Sample *samptr;
X} Channel;
X
X/* definitions of Amiga's sound port bits */
X
X#define LEFT0 1
X#define RIGHT0 2
X#define RIGHT1 4
X#define LEFT1 8
X#define LEFTSIDE (LEFT0 | LEFT1)
X#define RIGHTSIDE (RIGHT0 | RIGHT1)
X
X/* flag bits for Track.flags */
X
X#define SHOT_PLAYING 1
X#define LOOP_PLAYING 2
X#define PRECEDENCE_QUEUED 4
X#define LEFT 8			/* user parameter, which channel? */
X#define RIGHT 0			/* placeholder user parameter, opposite of LEFT */
X#define EITHER 16		/* user parameter, don't care which channel */
X
X/* end of channels.h */
X
END_OF_FILE
if test 1353 -ne `wc -c <'channels.h'`; then
    echo shar: \"'channels.h'\" unpacked with wrong size!
fi
# end of 'channels.h'
fi
if test -f 'chatter.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chatter.h'\"
else
echo shar: Extracting \"'chatter.h'\" \(511 characters\)
sed "s/^X//" >'chatter.h' <<'END_OF_FILE'
X
X
X/* define things I chatter about */
X#define GAB_DISKOUT 0
X#define GAB_DISKIN 1
X#define GAB_WINDOWACTIVE 2
X#define GAB_WINDOWINACTIVE 3
X#define GAB_EVERY_SO_OFTEN 4
X#define GAB_NEW_PREFERENCES 5
X#define GAB_BEEP 6
X
X#define N_GAB_TYPES 7
X
X#define MAX_GAB_ITEMS 32
X
Xstruct gab_info
X{
X	int n_gab_items;
X	int next_new_gab_item;
X	int next_play_gab_item;
X	Sample *Samples[MAX_GAB_ITEMS];
X};
X
X
X#define MAX_DEFERRED_FILES 256
X
Xstruct deferred_load_info
X{
X	char *filename[MAX_DEFERRED_FILES];
X	int n_deferred_items;
X};
END_OF_FILE
if test 511 -ne `wc -c <'chatter.h'`; then
    echo shar: \"'chatter.h'\" unpacked with wrong size!
fi
# end of 'chatter.h'
fi
if test -f 'chatterbox.info.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chatterbox.info.uu'\"
else
echo shar: Extracting \"'chatterbox.info.uu'\" \(348 characters\)
sed "s/^X//" >'chatterbox.info.uu' <<'END_OF_FILE'
Xbegin 644 chatterbox.info
XMXQ   0      )@ 1 #\ "  %  ,  0 AJ                           
XM     _X              !0    &             "         _  @  @ "
XM'  #                 #__W___?__X/__?__]P #@__]___W__^#__W___
XM?__X/__?__]___@8        ,           ?_________S  "   (  !L  
XM(   C__&P  @  "   ;, "   (  9L  (   @  &9________\P\        
X!>   
X 
Xend
END_OF_FILE
if test 348 -ne `wc -c <'chatterbox.info.uu'`; then
    echo shar: \"'chatterbox.info.uu'\" unpacked with wrong size!
fi
# end of 'chatterbox.info.uu'
fi
if test -f 'cleanup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cleanup.c'\"
else
echo shar: Extracting \"'cleanup.c'\" \(1419 characters\)
sed "s/^X//" >'cleanup.c' <<'END_OF_FILE'
X/* cleanup - Peter and Karl's standard cleanup management
X *
X * "cleaned up" the documentation  3/1/88
X *
X */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <stdio.h>
X
Xstruct _clean 
X{
X	int (*function)();
X	struct _clean *next;
X} *cleanlist = NULL;
X
X/* add_cleanup
X * given a function, add it to a list of functions to call when cleanup
X * is executed
X */
Xadd_cleanup(function)
Xint (*function)();
X{
X	struct _clean *ptr;
X
X	ptr = AllocMem(sizeof(struct _clean), MEMF_PUBLIC);
X	if(!ptr)
X		return 0;
X	ptr->function = function;
X	ptr->next = cleanlist;
X	cleanlist = ptr;
X}
X
X/* cleanup
X * call all the functions that were passed as arguments to add_cleanup
X * this run
X */
Xcleanup()
X{
X	struct _clean *ptr;
X	int (*f)();
X
X	fflush(stdout);
X	fflush(stderr);
X
X	while(cleanlist) 
X	{
X		/* locate the next cleanup function and get the function pointer */
X		ptr = cleanlist;
X		cleanlist = cleanlist->next;
X		f = ptr->function;
X
X		/* cleanup must clean up after itself */
X		FreeMem(ptr, sizeof(struct _clean));
X
X		/* execute the function */
X		(*f)();
X
X		fflush(stdout);
X		fflush(stderr);
X	}
X}
X
X/* panic - abort with an error message */
X
Xshort panic_in_progress = 0;
X
Xpanic(s)
Xchar *s;
X{
X	fflush(stdout);
X	fprintf(stderr,"panic: %s\n",s);
X	fflush(stderr);
X	if (!panic_in_progress)
X	{
X		cleanup();
X		exit(10);
X	}
X	fprintf(stderr,"double panic!\n");
X}
X
X_abort()
X{
X	panic("^C or other C library abort");
X}
END_OF_FILE
if test 1419 -ne `wc -c <'cleanup.c'`; then
    echo shar: \"'cleanup.c'\" unpacked with wrong size!
fi
# end of 'cleanup.c'
fi
if test -f 'config.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.c'\"
else
echo shar: Extracting \"'config.c'\" \(3170 characters\)
sed "s/^X//" >'config.c' <<'END_OF_FILE'
X/* sound effect gimmick player - config routine */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "assert.h"
X
X#include "iff.h"
X#include "8svx.h"
X
X#include "sample.h"
X#include "chatter.h"
X
X#define MATCH 0
X
XSample *Load8SVX();
X
Xint gab_interval = 300;
X
Xint total_loaded = 0;
X
Xstruct gab_info gab_data[N_GAB_TYPES];
X
Xint minimum_timer_interval, maximum_timer_interval;
X
Xint timer_noload = NO;
Xchar timer_loadopt[20];
X
XInitGabData()
X{
X	register int i, j;
X
X	for (i = 0; i < N_GAB_TYPES; i++)
X	{
X		gab_data[i].n_gab_items = 0;
X		gab_data[i].next_new_gab_item = 0;
X		gab_data[i].next_play_gab_item = 0;
X
X		for (j = 0; j < MAX_GAB_ITEMS; j++)
X			gab_data[i].Samples[j] = NULL;
X	}
X}
X
XConfig()
X{
X	FILE *fp;
X	char s[80];
X	int gab_type = -1;
X	struct gab_info *gabp;
X	int nconverted;
X
X 	if ((fp = fopen("ChatterBox:config.data","r")) == NULL)
X 		panic("ChatterBox:config.data config file doesn't exist");
X
X	while (fgets(s,80,fp) != NULL)
X	{
X		s[strlen(s)-1] = '\0';	/* cream the newline */
X
X		if (s[0] != ' ')
X		{
X			if (strncmp(s,"diskin",6) == MATCH)
X				gab_type = GAB_DISKIN;
X			else if (strncmp(s,"diskout",7) == MATCH)
X				gab_type = GAB_DISKOUT;
X			else if (strncmp(s,"timer",5) == MATCH)
X			{
X				gab_type = GAB_EVERY_SO_OFTEN;
X
X 				nconverted = sscanf(&s[5],"%s %d %d",timer_loadopt,&minimum_timer_interval,&maximum_timer_interval);
X
X 				timer_noload = (strcmp(timer_loadopt,"noload") == MATCH);
X
X 
X				if (nconverted != 3)
X					sscanf(&s[6],"%d %d",&minimum_timer_interval,&maximum_timer_interval);
X
X				if ((minimum_timer_interval > maximum_timer_interval) 
X				  || (minimum_timer_interval <= 0) || (maximum_timer_interval <= 0))
X				{
X					if ((minimum_timer_interval != 0) || (maximum_timer_interval != 0))
X						printf("config file 'timer' line is bad, using 5 minute default value\n");
X					minimum_timer_interval = maximum_timer_interval = 300;
X				}
X			}
X			else if (strncmp(s,"preferences",11) == MATCH)
X				gab_type = GAB_NEW_PREFERENCES;
X			else if (strncmp(s,"activate",8) == MATCH)
X				gab_type = GAB_WINDOWACTIVE;
X			else if (strncmp(s,"deactivate",10) == MATCH)
X				gab_type = GAB_WINDOWINACTIVE;
X			else if (strncmp(s,"beep",4) == MATCH)
X				gab_type = GAB_BEEP;
X			else
X			{
X				printf("'%s' should be 'diskin', 'diskout', 'timer', 'preferences', 'activate',\n",s);
X				printf("'deactivate', or 'beep'\n");
X				gab_type = -1;
X			}
X		}
X		else
X		{
X			if (gab_type == -1)
X			{
X				printf("ignored '%s'",s);
X			}
X			else
X			{
X				gabp = &gab_data[gab_type];
X				if ((gab_type == GAB_EVERY_SO_OFTEN) && (timer_noload == YES))
X				{
X					AddDeferredSound(s);
X				}
X				else if (gabp->next_new_gab_item < MAX_GAB_ITEMS)
X				{
X					gabp->Samples[gabp->next_new_gab_item] = Load8SVX(&s[1]);
X
X					if (gabp->Samples[gabp->next_new_gab_item])
X					{
X						gabp->n_gab_items++;
X						gabp->next_new_gab_item++;
X						total_loaded++;
X					}
X				}
X				else
X				{
X					printf("too many entries for one type, '%s' ignored\n",&s[1]);
X				}
X			}
X		}
X	}
X	fclose(fp);
X	if (total_loaded == 0)
X		panic("no sample files loaded");
X}
X
X/* end of config.c */
END_OF_FILE
if test 3170 -ne `wc -c <'config.c'`; then
    echo shar: \"'config.c'\" unpacked with wrong size!
fi
# end of 'config.c'
fi
if test -f 'deferredload.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'deferredload.c'\"
else
echo shar: Extracting \"'deferredload.c'\" \(1618 characters\)
sed "s/^X//" >'deferredload.c' <<'END_OF_FILE'
X
Xint sample_was_in_cache;
X
Xstruct deferred_load_info deferred_stuff;
X
XSample *Load8SVX();
X
XDeferredStuffCleanup()
X{
X	int i;
X
X	for (i = 0; i < MAX_GAB_ITEMS; i++)
X	{
X		if (deferred_stuff.filename[i])
X		{
X			FreeMem(deferred_stuff.filename[i],strlen(deferred_stuff.filename[i]) + 1);
X			deferred_stuff.filename[i] = NULL;
X		}
X	}
X	deferred_stuff.n_deferred_items = 0;
X}
X
XInitDeferredStuff()
X{
X	int i;
X
X	for (i = 0; i < MAX_GAB_ITEMS; i++)
X	{
X		deferred_stuff.filename[i] = NULL;
X	}
X
X	add_cleanup(DeferredStuffCleanup);
X}
X
XAddDeferredSound(s)
Xchar *s;
X{
X	char *t;
X
X	if (deferred_stuff.n_deferred_items >= MAX_GAB_ITEMS)
X	{
X		printf("too many deferred timer sounds, '%s' ignored\n",s);
X		return;
X	}
X
X	/* note: normally you would need to allocmem strlen(s)+1 to leave
X	 * room for the terminating NULL character, but in this case we
X	 * have a blank in column one that we don't want, so that accounts
X	 * for the extra char needed to be allocated */
X
X	if ((t = AllocMem(strlen(s),0)) == NULL)
X		panic("couldn't alloc mem for deferred sound");
X
X	strcpy(t,&s[1]);
X	deferred_stuff.filename[deferred_stuff.n_deferred_items++] = t;
X
X}
X
XPlayDeferredSound()
X{
X	Sample *sampleptr;
X	int one_i_want;
X
X	one_i_want = rando(deferred_stuff.n_deferred_items);
X
X	sampleptr = Load8SVX(deferred_stuff.filename[one_i_want]);
X
X	if (sampleptr == NULL)
X		return;
X
X	/* if the sample wasn't in the RAM cache, we wan't to purge it
X	 * when finished (code that receives the play_complete message
X	 * checks this bit) */
X	if (!sample_was_in_cache)
X		sampleptr->sample_flags |= PURGE_SAMPLE_AFTER_PLAYING;
X
X	PlayChannelSample(sampleptr,64,rando(2));
X}
END_OF_FILE
if test 1618 -ne `wc -c <'deferredload.c'`; then
    echo shar: \"'deferredload.c'\" unpacked with wrong size!
fi
# end of 'deferredload.c'
fi
if test -f 'display.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'display.c'\"
else
echo shar: Extracting \"'display.c'\" \(999 characters\)
sed "s/^X//" >'display.c' <<'END_OF_FILE'
X#include <functions.h>
X#include <exec/types.h>
X#include <exec/devices.h>
X#include <graphics/gfx.h>
X#include <intuition/intuition.h>
X#include <ctype.h>
X
Xextern struct NewWindow XNewWindowStructure1;
Xextern struct Menu XMenu1;
Xstruct Window *win = NULL;
X
Xstruct GfxBase *GfxBase = NULL;
Xstruct IntuitionBase *IntuitionBase = NULL;
X
Xint display_up;
X
Xtrash_libs()
X{
X	if (GfxBase) 
X		CloseLibrary(GfxBase);
X	if (IntuitionBase) 
X		CloseLibrary(IntuitionBase);
X}
X
XInitLibraries()
X{
X	add_cleanup(trash_libs);
X
X	if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L))) 
X		panic("Can't open graphics.library");
X
X	if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L)))
X		panic("Can't open intuition.library");
X}
X
Xtrash_window()
X{
X	if (win)
X	{
X		ClearMenuStrip(win);
X		CloseWindow(win);
X	}
X}
X
XInitWindow()
X{
X	int i;
X
X	win = 0;
X
X	if (!(win = OpenWindow(&XNewWindowStructure1)))
X		panic("can't open window");
X
X	SetMenuStrip(win,&XMenu1);
X
X	add_cleanup(trash_window);
X}
X
END_OF_FILE
if test 999 -ne `wc -c <'display.c'`; then
    echo shar: \"'display.c'\" unpacked with wrong size!
fi
# end of 'display.c'
fi
if test -f 'iff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'iff.c'\"
else
echo shar: Extracting \"'iff.c'\" \(4021 characters\)
sed "s/^X//" >'iff.c' <<'END_OF_FILE'
X/* general purpose IFF file cracking routines for Karl's 
X * Audio Stuff by Karl Lehenbauer, based originally on public domain IFF 
X * code from Electronic Arts, 2/24/88
X */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "assert.h"
X
X#include "iff.h"
X
XPutID(id)
XID id;
X{
X    fprintf(stderr,"%c%c%c%c",
X	   (char)((id>>24L) & 0x7f),
X	   (char)((id>>16L) & 0x7f),
X	   (char)((id>>8)   & 0x7f),
X	   (char)(id        & 0x7f) );
X}
X
XUBYTE *MyAllocMem(bytes, type)
XULONG bytes, type;
X{
X	UBYTE *tmp;
X
X		tmp = AllocMem(bytes, type);
X	return tmp;
X}
X
X/* return chunktype of next chunk */
X/* every time nextchunk is executed and returns that it found a chunk,
X * either readchunk or skipchunk must be called and only one time!
X */
XULONG nextchunk(fd,chunksize)
Xint fd;
Xint *chunksize;
X{
X	int sawsize;
X	ChunkHeader mychunkheader;
X
X	if ((sawsize = read(fd,&mychunkheader,sizeof(mychunkheader))) != 
X		sizeof(mychunkheader))
X	{
X		if (sawsize != 0)
X			fprintf(stderr,"Something's wrong with nextchunk! (sawsize %d)\n", sawsize);
X		*chunksize = 0;
X		return(0);
X	}
X#ifdef MAJORDEBUG
X	fputs("nextchunk: checking ",stderr);
X	PutID(mychunkheader.ckID);
X	fprintf(stderr,", size is %d\n",mychunkheader.ckSize);
X#endif
X
X	*chunksize = mychunkheader.ckSize;
X	return(mychunkheader.ckID);
X}
X
X/* read next chunk into buffer supplied, size must be value returned by
X * nextchunk
X * zero is returned on failure, one on success
X */
Xreadchunk(fd,buf,size)
Xint fd;
Xchar *buf;
XLONG size;
X{
X	if (read(fd,buf,size) != size) 
X	{
X		fputs("readchunk: read of IFF chunk failed\n",stderr);
X		return(0);
X	}
X	if (size & 1)
X		lseek(fd,1L,1);
X	return(1);
X}
X
X/* skip non-header portion of chunk, chunksize must have been returned
X * by nextchunk
X */
Xskipchunk(fd,chunksize)
Xint fd;
XLONG chunksize;
X{
X	/* skip over chunk data and skip an extra byte if length is odd */
X	lseek(fd,(long)chunksize,1);
X	if (chunksize & 1)
X		lseek(fd,1L,1);
X}
X
X/* OpenIFF
X * given file name, open the IFF file.
X * read the header, return failure if it's not a FORM
X * (someday we'll handle the more complex types)
X * read the form type, return failure if it's not the type requested
X * success, return the file descriptor
X */
X
Xint OpenIFF(fname,expected_formtype)
Xchar *fname;
XLONG expected_formtype;
X{
X	int iffile;
X	ChunkHeader chunkhead;
X	LONG formtype;
X
X	/* open the file */
X	if ((iffile = open(fname, O_RDONLY)) < 0)
X		return(-1);
X
X	/* read the header chunk */
X	if (read(iffile, &chunkhead, sizeof(chunkhead)) < 0)
X	{
X		fprintf(stderr,"OpenIFF: initial read from IFF file %s failed!\n",fname);
X		return(-1);
X	}
X
X	/* return if the header chunk doesn't say it's IFF FORM */
X	if (chunkhead.ckID != ID_FORM)
X	{
X		fprintf(stderr,"OpenIFF: File %s isn't IFF, is too complex, or doesn't start with FORM\n",fname);
X		return(-1);
X	}
X#ifdef DEBUG
X	fprintf(stderr,"OpenIFF: FORM found, size is %d\n",chunkhead.ckSize);
X#endif
X
X	/* read the form type */
X	read(iffile, &formtype, sizeof(formtype));
X
X	/* return if the form type isn't the type requested */
X	if (formtype != expected_formtype)
X	{
X		fprintf(stderr,"OpenIFF: File %s is IFF ");
X		PutID(formtype);
X		fprintf(stderr," rather than the requested ");
X		PutID(expected_formtype);
X		fprintf(stderr,"\n");
X		return(-1);
X	}
X	return(iffile);
X}
X
X/* read chunks until one of type chunktype is found or EOF
X * note that after a successful call to chunkuntil,
X * skipchunk or readchunk must be performed or the IFF reading
X * software will get lost on the next nextchunk
X * chunksize is returned on success, -1 otherwise
X * The caller should probably check the return explicitly for -1.
X * If checking only for less than zero, chunks larger than
X * two gigabytes will cause your code to break.
X */
X
XLONG chunkuntil(fd,chunktype)
Xint fd;
XULONG chunktype;
X{
X	ULONG currentchunk;
X	LONG chunksize;
X
X	while ((currentchunk = nextchunk(fd,&chunksize)) != NULL)
X	{
X		if (currentchunk == chunktype)
X			return(chunksize);
X		skipchunk(fd,chunksize);
X	}
X	return(-1);
X}
X
X/* end of iff.c */
END_OF_FILE
if test 4021 -ne `wc -c <'iff.c'`; then
    echo shar: \"'iff.c'\" unpacked with wrong size!
fi
# end of 'iff.c'
fi
if test -f 'loop.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'loop.c'\"
else
echo shar: Extracting \"'loop.c'\" \(2212 characters\)
sed "s/^X//" >'loop.c' <<'END_OF_FILE'
X#include <exec/types.h>
X#include <exec/devices.h>
X#include <exec/memory.h>
X#include <devices/timer.h>
X#include <functions.h>
X#include <stdio.h> 
X#include <libraries/dos.h>
X#include <intuition/intuition.h>
X
X#include "hackercore.h"
X
X#include "chatter.h"
X#include "channels.h"
X
Xextern struct timerequest *CreateTimer();
X
Xstruct timerequest *tr = NULL;
X
Xstruct IntuiMessage *msg;
X
Xextern int gab_interval;
Xextern int minimum_timer_interval, maximum_timer_interval;
X
Xshort KeepGoing;
X
Xextern struct Window *win;
X
X#define CheckMsg(m) (m->mp_MsgList.lh_Head->ln_Succ != 0L)
X
Xextern struct SMUS_IOAudio *SMUS_GetMsg();
X
Xextern long beep_sigmask;
X
Xloop()
X{
X	ULONG waitflags;
X	ULONG timermask;
X	struct SMUS_IOAudio *audio_msg_ptr;
X
X	KeepGoing = YES;
X
X	timermask = (1 << (long)tr->tr_node.io_Message.mn_ReplyPort->mp_SigBit);
X
X	determine_and_set_wait_seconds();
X
X	/* main loop */
X
X	while (KeepGoing)
X	{
X		/* wait for an event */
X		/* (we want for -1 to reduce the overhead of looking up all our
X		 * sigbits */
X
X		waitflags = Wait(-1L);
X
X		/* timer message */
X	    if (waitflags & timermask)
X		{
X			/* if there's really a timer message */
X			if (GetMsg(tr->tr_node.io_Message.mn_ReplyPort) != (struct Message *)NULL) 
X			{
X				blather(GAB_EVERY_SO_OFTEN);
X				determine_and_set_wait_seconds();
X			}
X		}
X
X		while ((audio_msg_ptr = SMUS_GetMsg()) != NULL)
X			StopChannelNote(audio_msg_ptr->channelp);
X
X		if (waitflags & beep_sigmask)
X			blather(GAB_BEEP);
X
X		if (waitflags & SIGBREAKF_CTRL_C)
X			KeepGoing = NO;
X
X		if (CheckMsg(win->UserPort) && (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
X		{
X			switch(msg->Class)
X			{
X				case CLOSEWINDOW:
X					KeepGoing = NO;
X					break;
X
X				case NEWPREFS:
X					blather(GAB_NEW_PREFERENCES);
X					break;
X				
X				case DISKINSERTED:
X					blather(GAB_DISKIN);
X					break;
X
X				case DISKREMOVED:
X					blather(GAB_DISKOUT);
X					break;
X
X				case ACTIVEWINDOW:
X					blather(GAB_WINDOWACTIVE);
X					break;
X
X				case INACTIVEWINDOW:
X					blather(GAB_WINDOWINACTIVE);
X					break;
X
X				case MENUPICK:
X					ProcessMenu(msg->Code);
X					break;
X
X				default:
X					printf("default %lx\n",msg->Class);
X					break;
X			}
X			ReplyMsg(msg);
X		}
X	}
X	AbortIO(tr);
X} 
X
XQuit()
X{
X	KeepGoing = NO;
X}
END_OF_FILE
if test 2212 -ne `wc -c <'loop.c'`; then
    echo shar: \"'loop.c'\" unpacked with wrong size!
fi
# end of 'loop.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(618 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* sound effect gimmick player - main routine */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "assert.h"
X#include "iff.h"
X#include "8svx.h"
X
X#include "sample.h"
X#include "chatter.h"
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	InitLibraries();
X	Init8SVX();
X	InitAudio();
X	InitTimer();
X	InitGabData();
X	InitDeferredStuff();
X	Config();
X	srand(time(0));
X	InitSignals();
X	randomize_all();
X	InitWindow();
X
X	loop();
X
X	cleanup();
X
X#ifdef TRACKER
X	TrackerExitReport();
X	Delay(100);
X#endif
X
X	exit(0);
X}
X
END_OF_FILE
if test 618 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'menus.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'menus.c'\"
else
echo shar: Extracting \"'menus.c'\" \(542 characters\)
sed "s/^X//" >'menus.c' <<'END_OF_FILE'
X
Xextern struct Menu XMenu1;
X
Xextern int KeepGoing;
X
X
XProcessMenu(menunumber)
Xint menunumber;
X{
X	struct MenuItem *ItemAddress();
X
X	while (menunumber != MENUNULL && KeepGoing)
X	{
X		/* printf("menu number %d, item number %d, subitem %d\n",MENUNUM(menunumber),ITEMNUM(menunumber),SUBNUM(menunumber)); */
X
X		assert(MENUNUM(menunumber) == 0);
X
X		switch (ITEMNUM(menunumber))
X		{
X			case 2:
X				KeepGoing = NO;
X				break;
X
X			default:
X				blather(rando(N_GAB_TYPES));
X				break;
X		}
X		menunumber = ItemAddress(&XMenu1, menunumber)->NextSelect;
X	}
X}
END_OF_FILE
if test 542 -ne `wc -c <'menus.c'`; then
    echo shar: \"'menus.c'\" unpacked with wrong size!
fi
# end of 'menus.c'
fi
if test -f 'rando.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rando.c'\"
else
echo shar: Extracting \"'rando.c'\" \(103 characters\)
sed "s/^X//" >'rando.c' <<'END_OF_FILE'
X
X
Xrando(i)
Xint i;
X{
X	assert(i >= 0);
X
X	if (i == 0)
X		return(0);
X
X	return((rand() & 0x7FFFFFFF) % i);
X}
END_OF_FILE
if test 103 -ne `wc -c <'rando.c'`; then
    echo shar: \"'rando.c'\" unpacked with wrong size!
fi
# end of 'rando.c'
fi
if test -f 'rerandom.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rerandom.c'\"
else
echo shar: Extracting \"'rerandom.c'\" \(1621 characters\)
sed "s/^X//" >'rerandom.c' <<'END_OF_FILE'
X/* sound effect gimmick player - rerandomize routines to do random
X * selection without replacement */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "assert.h"
X#include "iff.h"
X#include "8svx.h"
X
X#include "sample.h"
X#include "chatter.h"
X
Xextern struct gab_info gab_data[N_GAB_TYPES];
X
X/* rerandomize randomizes the sample play order for a given gab type
X * It is called by Blather() and by startup code to randomize the
X * list of sample pointers.  By then walking through the list, and
X * rerandomizing every time we finish playing all the samples in the
X * list, we implement random selection without replacement reasonably
X * efficiently.
X *
X * The reason we don't use pure random selection is that it is too
X * annoying to get the same sample a whole bunch of times
X */
Xrerandomize(gab_type)
Xint gab_type;
X{
X	register struct gab_info *gabp;
X	register int i, one_to_switch;
X	register Sample *samptemp;
X
X	gabp = &gab_data[gab_type];
X
X	gabp->next_play_gab_item = 0;
X
X	for (i = 0; i < gabp->n_gab_items; i++)
X	{
X		one_to_switch = rando(gabp->n_gab_items);
X		if (one_to_switch != i)
X		{
X			samptemp = gabp->Samples[i];
X			assert(samptemp && gabp->Samples[one_to_switch]);
X			gabp->Samples[i] = gabp->Samples[one_to_switch];
X			gabp->Samples[one_to_switch] = samptemp;
X		}
X	}
X}
X
X/* note:  Config() must have been called, and all samples loaded, before
X * calling randomize_all()
X */
Xrandomize_all()
X{
X	int gab_type;
X
X	for (gab_type = 0; gab_type < N_GAB_TYPES; gab_type++)
X		rerandomize(gab_type);
X}
END_OF_FILE
if test 1621 -ne `wc -c <'rerandom.c'`; then
    echo shar: \"'rerandom.c'\" unpacked with wrong size!
fi
# end of 'rerandom.c'
fi
if test -f 'sample.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sample.h'\"
else
echo shar: Extracting \"'sample.h'\" \(821 characters\)
sed "s/^X//" >'sample.h' <<'END_OF_FILE'
X/* front-end include file for Amiga audio samples created by Karl's
X * IFF 8SVX to C source converter.  19 June 87
X */
X
X#ifndef SAMPLE_H
X
X#define SAMPLE_H
X
X#ifndef I8SVX_H
X#include "8svx.h"
X#endif
X
X/* sample flags */
X#define SAMPLE_ALLOCATED_IN_CHIP_RAM 1
X#define SAMPLE_ALLOCATED_IN_FAST_RAM 2
X#define SAMPLE_COPIED_INTO_CHIP_RAM 4
X#define PURGE_SAMPLE_AFTER_PLAYING 8
X
Xtypedef struct sample_struct
X{
X	struct Node node;
X	Voice8Header sampleheader;
X	struct sample_struct *nextsample;
X	short sample_flags;
X	char *sampledata;
X	char *fastsampledata;
X	LONG samplebytes;
X	int chip_use_count;
X#ifndef NOAUDIT
X	short magic;
X#endif
X} Sample;
X
X
X
X#define SAMPLE_MAGIC 17385
X
X#ifndef NOAUDIT
X#define ASSERT_SAMPLE_MAGIC(x) assert(x->magic == SAMPLE_MAGIC);
X#else
X#define ASSERT_SAMPLE_MAGIC(x)
X#endif
X
X#endif
X
X/* end of sample.h */
END_OF_FILE
if test 821 -ne `wc -c <'sample.h'`; then
    echo shar: \"'sample.h'\" unpacked with wrong size!
fi
# end of 'sample.h'
fi
if test -f 'samplechip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'samplechip.c'\"
else
echo shar: Extracting \"'samplechip.c'\" \(3389 characters\)
sed "s/^X//" >'samplechip.c' <<'END_OF_FILE'
X
X
X
X
Xmake_sample_chip(samptr)
Xregister Sample *samptr;
X{
X	ASSERT_SAMPLE_MAGIC(samptr);
X
X	/* chip_use_count is the number of make_sample_chip calls that are
X	 * active for the sample.  It must never be less than 0 */
X	assert(samptr->chip_use_count >= 0);
X
X	/* if the use count is nonzero, someone else has already locked it
X	 * in.  merely increment the count and return.  the assert insures
X	 * that we're pointing at data */
X	if (samptr->chip_use_count)
X	{
X		samptr->chip_use_count++;
X		assert(samptr->sampledata);
X		return(1);
X	}
X
X	/* if we allocated it from chip RAM, we don't have to copy it down
X	 * there, so we can return 'success' */
X
X	if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
X	{
X		assert(samptr->sampledata);
X		return(1);
X	}
X
X	/* at this point, data should be in fast RAM and not chip RAM, and
X	 * the sampledata pointer should be NULL else there's a bug and
X	 * we'll be losing memory */
X	assert(samptr->sampledata == NULL);
X
X	/* alloc CHIP memory for the sample */
X	samptr->sampledata = (char *)AllocMem(samptr->samplebytes,MEMF_CHIP);
X
X	/* if it failed, return failure */
X	if (samptr->sampledata == NULL)
X	{
X		return(0);
X	}
X
X	/* copy the sample down, set flags indicated it has been copied
X	 * down, and set use count to 1 'cuz we're the first.  
X	 *
X	 * note, the program can call make_sample_chip multiple times
X	 * before a free because the free is performed when the sound is
X	 * finished and more than one request could be pending for the
X	 * sound, but we don't need a semaphore or anything because the
X	 * program isn't multithreaded and no other programs diddle with
X	 * this stuff
X	 */
X
X	movmem(samptr->fastsampledata,samptr->sampledata,samptr->samplebytes);
X	samptr->sample_flags |= SAMPLE_COPIED_INTO_CHIP_RAM;
X	samptr->chip_use_count = 1;
X
X#ifdef DEBUG
X	printf("copied sample to chip\n");
X#endif
X	return(1);
X}
X
Xfree_sample_chip(samptr)
Xregister Sample *samptr;
X{
X	ASSERT_SAMPLE_MAGIC(samptr);
X
X	if (samptr->chip_use_count > 1)
X	{
X		samptr->chip_use_count--;
X		return;
X	}
X
X	/* if it was allocated in CHIP RAM, no need to free */
X	if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
X	{
X		/* if the flag indicates we should free this from the cache
X		 * when done playing, do so (for demand-disk-loaded timer
X		 * events) */
X		if (samptr->sample_flags & PURGE_SAMPLE_AFTER_PLAYING)
X			UnloadSampleAt(samptr);
X
X		return;
X	}
X
X	/* if we got here, it must be the last free, i.e., the real free,
X	 * so insure it (for testing at least) with an assert */
X	assert(samptr->chip_use_count == 1);
X
X	/* we are the last user, zero the use count and free the CHIP ram */
X	samptr->chip_use_count = 0;
X
X	/* we insist that the sample being freed is currently in CHIP RAM */
X	assert(samptr->sample_flags & SAMPLE_COPIED_INTO_CHIP_RAM);
X
X	/* free the CHIP RAM */
X	FreeMem(samptr->sampledata,samptr->samplebytes);
X
X	/* clear the indication that it is loaded */
X	samptr->sample_flags &= ~(SAMPLE_COPIED_INTO_CHIP_RAM);
X
X	/* null out the data pointer, useful to make asserts trip when there
X	 * are bugs and helps keep us from playing garbage by accident */
X	samptr->sampledata = NULL;
X
X	/* if the flag indicates we should free this from the cache
X	 * when done playing, do so (for demand-disk-loaded timer
X	 * events) */
X	if (samptr->sample_flags & PURGE_SAMPLE_AFTER_PLAYING)
X		UnloadSampleAt(samptr);
X
X#ifdef DEBUG
X	printf("freed sample from chip RAM\n");
X#endif
X}
X
END_OF_FILE
if test 3389 -ne `wc -c <'samplechip.c'`; then
    echo shar: \"'samplechip.c'\" unpacked with wrong size!
fi
# end of 'samplechip.c'
fi
if test -f 'setwait.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'setwait.c'\"
else
echo shar: Extracting \"'setwait.c'\" \(657 characters\)
sed "s/^X//" >'setwait.c' <<'END_OF_FILE'
X#include <exec/types.h>
X#include <functions.h>
X#include <devices/timer.h>
X
X#define MATCH 0
X
Xextern int gab_interval;
Xextern int minimum_timer_interval, maximum_timer_interval;
X
Xextern struct timerequest *tr;
X
Xvoid set_wait_seconds(timer_request,delay_seconds)
Xstruct timerequest *timer_request;
Xlong delay_seconds;
X{
X	timer_request->tr_node.io_Command = TR_ADDREQUEST;
X
X	timer_request->tr_time.tv_secs = delay_seconds;
X	timer_request->tr_time.tv_micro = 0;
X
X	SendIO(timer_request);
X}
X
Xdetermine_and_set_wait_seconds()
X{
X	gab_interval = minimum_timer_interval
X	 + rando(maximum_timer_interval - minimum_timer_interval);
X	set_wait_seconds(tr,gab_interval);
X}
END_OF_FILE
if test 657 -ne `wc -c <'setwait.c'`; then
    echo shar: \"'setwait.c'\" unpacked with wrong size!
fi
# end of 'setwait.c'
fi
if test -f 'signals.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signals.c'\"
else
echo shar: Extracting \"'signals.c'\" \(1514 characters\)
sed "s/^X//" >'signals.c' <<'END_OF_FILE'
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/interrupts.h>
X#include <hardware/custom.h>
X#include <hardware/intbits.h>
X#include <libraries/dos.h>
X#include <stdio.h>
X
X#define LVODisplayBeep -96
X
Xlong beep_sigbit = 0;
Xlong beep_sigmask = 0;
Xstruct Task *chatterbox_task = NULL;
X
Xextern struct IntuitionBase *IntuitionBase;
X
Xextern struct gab_info gab_data[N_GAB_TYPES];
X
Xvoid (*OldBeep)() = NULL;
X
XMyBeep()
X{
X	assert((chatterbox_task != 0) && (beep_sigmask != 0));
X
X	Signal(chatterbox_task,beep_sigmask);
X}
X
XCleanupSignals()
X{
X	if (beep_sigbit)
X		FreeSignal(beep_sigbit);
X
X	if (OldBeep)
X		SetFunction(IntuitionBase,LVODisplayBeep,OldBeep);
X}
X
X/* Intuition library must have been opened before calling!
X * Config() must have run before calling to initialize the
X * number of samples that are to be called if beep is defined
X * in the config file.  If no samples are assigned to beep,
X * we do not replace the DisplayBeep function!
X */
XInitSignals()
X{
X
X	assert(IntuitionBase);
X
X	add_cleanup(CleanupSignals);
X
X	/* allocate a signal */
X	if ((beep_sigbit = AllocSignal(-1L)) < 0)
X		panic("can't alloc signal");
X
X	/* precompute the mask and store for convenience */
X	beep_sigmask = (1 << beep_sigbit);
X
X	/* get the task ID */
X	chatterbox_task = FindTask(NULL);
X
X	/* replace DisplayBeep with our beep routine, saving
X	 * the old vector so we can replace it when we leave
X	 */
X	if (gab_data[GAB_BEEP].n_gab_items > 0)
X		OldBeep = SetFunction(IntuitionBase,LVODisplayBeep,MyBeep);
X}
X
END_OF_FILE
if test 1514 -ne `wc -c <'signals.c'`; then
    echo shar: \"'signals.c'\" unpacked with wrong size!
fi
# end of 'signals.c'
fi
if test -f 'timer.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'timer.c'\"
else
echo shar: Extracting \"'timer.c'\" \(1134 characters\)
sed "s/^X//" >'timer.c' <<'END_OF_FILE'
X#include <exec/devices.h>
X#include <functions.h>
X#include <devices/timer.h>
X
Xstruct timerequest *timermsg;
Xstruct timerequest *CreateExtIO();
X
Xextern struct timerequest *tr;
X
Xextern int gab_interval;
X
Xstruct timerequest *CreateTimer(unit)
Xint unit;
X{
X	int error;
X
X	register struct MsgPort *timerport;
X	register struct timerequest *timermsg;
X
X	timerport = CreatePort(0L, 0L);
X
X	if(!timerport)
X		return 0;
X
X	timermsg =  CreateExtIO(timerport, (long)sizeof(struct timerequest));
X
X	if (!timermsg) 
X	{
X		DeletePort(timerport);
X		return 0;
X	}
X	error = OpenDevice(TIMERNAME, (long)unit, timermsg, 0L);
X	if(error)
X	{
X		DeleteTimer(timermsg);
X		return 0;
X	}
X	return timermsg;
X}
X
XDeleteTimer(tr)
Xregister struct timerequest *tr;
X{
X	register struct MsgPort *tp;
X
X	if (tr) 
X	{
X		tp = tr->tr_node.io_Message.mn_ReplyPort;
X		if(tp)
X			DeletePort(tp);
X		CloseDevice(tr);
X		DeleteExtIO(tr, (long)sizeof(struct timerequest));
X	}
X}
X
XTrashTimer()
X{
X	if (tr)
X	{
X		AbortIO(tr);
X		DeleteTimer(tr);
X	}
X}
X
XInitTimer()
X{
X	tr = (struct timerequest *)CreateTimer((int)UNIT_MICROHZ);
X	if (tr == NULL) 
X		panic("can't create timer");
X
X	add_cleanup(TrashTimer);
X}
END_OF_FILE
if test 1134 -ne `wc -c <'timer.c'`; then
    echo shar: \"'timer.c'\" unpacked with wrong size!
fi
# end of 'timer.c'
fi
if test -f 'windows.pw.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'windows.pw.uu'\"
else
echo shar: Extracting \"'windows.pw.uu'\" \(1941 characters\)
sed "s/^X//" >'windows.pw.uu' <<'END_OF_FILE'
Xbegin 644 windows.pw
XM4&]W97)7:6YD;W=S('8R+C @J3$Y.#<@8GD@24Y/5D%44D].24-3+"!)3D,N
XM(" @(" @(" @(" @(" @(" @(" @(" @(" @(" @   #]     D@  #_    
XM 0     !      YR860Z=VEN9&]W<RYC           !    #@ -PP  !0 %
XM H  R  AZZ@         (#3P       "6    0%C !8 I0 *  4 !?____\ 
XM   +0VAA='1E<F)O>   (:AX 0       $L    B+A          "%!R;VIE
XM8W0  "&HX  AJ3@    GH#@ (H!0$   )Z4(      $" P$            (
XM  @               9!8F]U=      !   GH(@ (>LP    )Z!@ ">@J   
XM   ! @,!       9    "  (               20VAA='1E<F)O>" M('8P
XM+C$      0  )Z#P "'LR    ">@R  GH1@      0(# 0      &0   1@ 
XM"               'V)Y($MA<FP@3&5H96YB875E<BP@2&%C:V5R8V]R<   
XM   !   A[D@ (>\     )Z$X ">B&      ! @,!       9 !@ B  (    
XM           .,SDQ."!086YO<F%M80     !   GHV@ (H)P    )Z-  ">C
XMD      ! @,!       9 "  B  (               936ES<V]U<FD@0VET
XM>2P@5%@@(#<W-#4Y      $  ">D:  B@P     GI$  )Z20      $" P$ 
XM     !D * #   @              !E5<V5N970Z('5U;F5T(7-U9V%R(6MA
XM<FP      0  )Z38 "*'B    ">DL            0(# 0      &0 P ,  
XM"               )$EN=&5R;F5T.B!K87)L0'-U9V%R+FAA8VME<F-O<G N
XM8V]M      $  "**6  BPB     GI2@ )ZI8$   )['0      $" P$     
XM    "0 H  @               ]2961I<W1R:6)U=&EO;@     !   GJJ  
XM(MWH    )ZIX ">JX      ! @,!      !A    "  (               S
XM1G)E96QY(')E9&ES=')I8G5T86)L92!F;W(@;F]N8V]M;65R8VEA;"!P=7)P
XM;W-E<RX      0  )ZL  ">P"    ">OX  GL!@      0(# 0      80  
XM :  "                0     !   GL&  )["@    )[ X ">PL      !
XM @,!      !A   !D  (               U0V]N=&%C="!M92!F;W(@:6YN
XM;W9A=&EV92P@;&EC96YS86)L92!A=61I;R!S;V9T=V%R90     !   GL/@ 
XM)[$X    )[#0 ">Q2      ! @,!      !A ! !H  (               S
XM*&EN8VQU9&EN9R!33553(&%N9"!-241)('!L87EE<G,I+"!C;VUP;W-I=&EO
XM;B!A;F0      0  )[&0 ">QP    ">Q:            0(# 0      80 8
XM :  "               )F%R<F%N9VEN9R!S97)V:6-E<RP@86YD('!R;R!S
XM86UP;&EN9RX      0  )[(8 ">R*    ">Q\      0             0(#
XG 0         2 '  "               !5%U:70     !5%U:70 
X 
Xend
END_OF_FILE
if test 1941 -ne `wc -c <'windows.pw.uu'`; then
    echo shar: \"'windows.pw.uu'\" unpacked with wrong size!
fi
# end of 'windows.pw.uu'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
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 need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
	amiga@cs.odu.edu	
or	amiga@xanth.cs.odu.edu	( obsolescent mailers may need this address )
or	...!uunet!xanth!amiga	( very obsolescent mailers need this address )

Comments, questions, and suggestions s should be addressed to ``amiga-request''
(only use ``amiga'' for submissions) at the above addresses.