!---------------------------------------------------------------------------- ! Sound An Inform 6 library by L. Ross Raszewski to handle ! Inform's sound capabilities. Requires sound card. ! CAUTION: MAY BEHAVE UNPREDICTABLY ON SOME INTERPRETERS ! ! Most notably, the "Sequencer" option intermittenly crashes Frotz on my ! system rather dramatically. I'm not sure if it's my interpreter or my ! computer. At any rate, be careful. I've had no trouble with the other ! operations, but that's no guarantee. ! ! This system consumes three global variables and one array: ! play_sounds - If play_sounds=1, sounds will be played, if 0, they will not. ! sound_vol - a number from 1 to 8, setting the volume ! playing - A bit array holding three bites used internally. ->0 indicates ! whether or not PlaySound has been called yet. ! ->1 indicates the currenly playing sound effect number ! ->2 is used by internal operations ! ! This library plays sound effects of the formats described in Stefan ! Jokisch's treatise on Infocom sound formats. The actual conventions of the ! format are handled by the interpreter, but, and there's a lot more on this in ! the Specification of the Z-Machine, sound_effects 1 and 2 are beeps, and 3 ! and up are sound files in an arcane and proprietary format. (There's a beta ! version of SOX that an write to them, however.) Once you have the files where ! your interpreter wants them (usually the "sound" subdirectory), the ! @sound_effect opcode plays these sounds. However, the nature of ! @sound_effect is such that its use isn't intuative. Indeed, there's three ! lines of assembly I had to stick in to make it work (liberally stolen from ! Sherlock) This library makes this useable. ! ! Usage: ! To play a sound: ! PlaySound(sound_number); ! Options: ! PlaySound(sound_number,reps); ! - plays a sound effect a set number of times ! PlaySound(sound_number,Routine,[option]); ! - Plays a sound effect, and runs Routine when the effect ! has finished. The third argument is stored in the global ! variable sequence. ! Features: ! If you're using my footnote library, a footnote will be called ! the first time PlaySound is used. The number of that footnote ! should be stored in a constant "SoundNote". Such a footnote ! could say something like "Type "SOUND OFF" to disable sounds" ! ! Routines included: ! Sequencer: Call PlaySound(Sequencer,array);. This will cause ! each sound effect in the array to be played in order. ! array->0 MUST be the number of sounds to play, however. ! Note: This only works about one time in five on my system ! if anyone could explain why, I'd be much obliged. ! Repeat and Fade: Call PlaySound(sound_number,RepAndFade); to ! cause a sound effect to repeat and fade out. ! Fade In: Call PlaySound(sound_number, FadeIn); and the sound effect ! will repeat while fading in. ! ! End-User Functions: ! Sound - Toggles sound on and off ! Sound On - Turns sound on ! Sound Off- Turns sound off ! Sound Up - Turns volume up ! Sound Down- Turns volume down ! Sound (number)- Sets volume ! ! Debugging Suite: ! Audio (number)- Plays the corresponding sound effect ! Audio (2 numbers) Plays the corresponding effect a number of times ! Audio FIN # - Fades in the sound effect ! Audio RF # - Repeats and fades sound effect ! global play_sounds=1; global sound_vol=5; global sequence; array playing -> 3; [ PlaySound i Rout k j l; if (play_sounds==0) rtrue; #IFDEF SoundNote; if (playing->0==0) print "^", (Note) SoundNote, "^"; playing->0=1; #ENDIF; if (i ofclass Routine) {sequence=Rout; indirect(i); rtrue;}; if (~~(Rout ofclass Routine)){j=Rout; Rout=0;}; if (j==0) j=1; if (Rout==0) Rout=StopSound; l=sound_vol; if (Rout==FadeIn) l=1; playing->1=i; sequence=k; @log_shift j 8 sp; @or sp l sp; @sound_effect i 2 sp Rout; ]; [ StopSound i; i=playing->1; @sound_effect i 4; ]; [ FadeIn; playing->2=1; FIner(); ]; [ FIner i j; playing->2=playing->2+1; i=playing->1; j=playing->2; @log_shift 1 8 sp; @or sp j sp; if (j<=sound_vol) @sound_effect i 2 sp FIner; ]; [ RepAndFade; playing->2=sound_vol; RnF(); ]; [ RnF j i; playing->2=playing->2-1; i=playing->1; j=playing->2; @log_shift 1 8 sp; @or sp j sp; if (j>=1) @sound_effect i 2 sp RnF; ]; [ Sequencer; playing->2=0; SeqNext(); ]; [ SeqNext j i k; playing->2=playing->2+1; j=playing->2; if (j>sequence->0) rtrue; i=sequence->j; @log_shift 1 8 k; @or k sound_vol k; @sound_effect i 2 k SeqNext; ]; [ SoundToggleSub; if (play_sounds==1) <>; if (play_sounds==0) <>; ]; [ SoundVolSub; if (noun>8 || noun <=0) "Please specify a volume level between 1 and 8."; sound_vol=noun; "Sound volume set to ", sound_vol, "."; ]; [ SoundUpSub; if (sound_vol==8) "Maximum volume"; sound_vol++; "Sound volume set to ", sound_vol, "."; ]; [ SoundDownSub; if (sound_vol==1) "Minimum volume"; sound_vol--; "Sound volume set to ", sound_vol, "."; ]; [ SoundsOnSub; play_sounds=1; "Sound on."; ]; [ SoundsOffSub; play_sounds=0; "Sound off."; ]; verb "sound" "sounds" "volume" * -> SoundToggle * "on" -> SoundsOn * "off" -> SoundsOff * "up" -> SoundUp * "down" -> SoundDown * number -> SoundVol; #IfDef DEBUG; [ AudioSub; PlaySound(noun); ]; [ AudioRSub; PlaySound(noun,RepAndFade); ]; [ AudioFINSub; PlaySound(noun,FadeIn); ]; [ AudioXRSub; PlaySound(noun,second); ]; verb "audio" * number ->Audio * number number ->AudioXR * "Fin" number ->AudioFIN * "RF" number ->AudioR; #ENDIF; !---------------------------------------------------------------------------