home *** CD-ROM | disk | FTP | other *** search
- {
- Background sound generation unit for Turbo Pascal programs
-
- Originally written and released to Public Domain by:
-
- Nels Anderson
- 92 Bishop Drive
- Framingham, MA 01701
-
- Adopted for use with Melody Master by Alexei A. Efros, Jr.
- }
- unit Sounder;
- {
- This UNIT can be used with MELODY MASTER's "TP back-gr" output
- files to minimize the music development time. Please note,
- however, that you may have some problems when playing high
- notes. This happens when the note's frequency is greater than
- 255 (byte). To solve the problem try to lower your music: in
- MELODY MASTER press F9 and then "8 down". Then, output it
- again.
-
- To use this unit, the main program needs to do the following:
-
- uses Sounder, Crt;
- Begin
- GetIntVec($1C,Int1CSave); (save original interrupt vector)
- SetIntVec($1C,New1CInt); (install timer interrupt)
- .
- . (body of program)
- .
- StartSound(@ArrayName,N,S);
- (where: ArrayName is the name of the your melody,
- N is the number if repeats,
- S is the speed)
- .
- . (body of program)
- .
- SetIntVec($1C,Int1CSave); (restore original 1C interrupt)
- NoSound;
- end.
- }
-
- interface
-
- Uses
- Crt;
-
- {$I FILENAME.PAS} { <---- Insert your music file name here! }
-
- procedure StartSound(Notes: POINTER; Repeats: INTEGER; Speed: BYTE);
-
- { Sound Collection:
-
- Each sound is an array of pairs of bytes, where the first byte of each
- pair is the duration in 1/18th second units and the second byte of the
- pair is the note frequency in 10's of Hertz. To use a sound, include
- a command like the following in a program:
-
- StartSound(@PhaserSound,3,1); {do phaser sound 3 times}
-
- Type
- ByteArray = array[1..2] of BYTE;
- Var
- SoundSpeed: BYTE; {multiplier used to slow down sounds}
- SoundCount: BYTE; {counts how long current sound has been on}
- MySound: ^ByteArray; {points to array of notes and durations}
- New1CInt,{address of new interrupt}
- Int1CSave: POINTER; {saves original $1C interrupt}
- NumRepeats, {number of times to repeat sound}
- MyClock, {general purpose timer}
- SoundOff: INTEGER; {offset into note array}
- SndFlg, {set when sounds allowed}
- MakeSound: BOOLEAN; {set while sound is going}
-
- implementation
-
- procedure StartSound(Notes: POINTER; Repeats: INTEGER; Speed: BYTE);
- { Start generating the sound pointed to by Notes }
- begin
- SoundSpeed := Speed; {set speed}
- SoundOff := 1; {offset into sound array}
- SoundCount := 1; {counter for current note}
- MySound := Notes; {pointer to sound array}
- MakeSound := TRUE; {enable sounds}
- NumRepeats := Repeats; {number times to repeat sound}
- end; {StartSound procedure}
-
- procedure TimerInt;
- interrupt;
- { Clock tick interrupt
-
- BIOS interrupt $1C has been replaced with the following routine. This
- interrupt occurs on each clock tick (18 per second).
-
- The interrupt mainly handles sounds. When the MakeSound flag is true,
- the pointer MySound must be pointing to a byte array containing durations
- and frequencies of sounds to be generated. Sounds will be generated from
- the array until a duration of 0 is found.
-
- A general purpose timer is also incremented each time the interrupt
- occurs.
- }
- begin
- Inc(MyClock); {increment timer}
- if not SndFlg then begin {exit if sounds turned off}
- MakeSound := FALSE;
- Exit;
- end;
- if MakeSound then begin {if making a sound...}
- Dec(SoundCount);
- if SoundCount <= 0 then begin {if current sound done...}
- NoSound;
- SoundCount := SoundSpeed * MySound^[SoundOff];{get duration of next one}
- if SoundCount > 0 then begin {if there is a next one...}
- Inc(SoundOff);
- Sound(10*MySound^[SoundOff]); {start it up}
- Inc(SoundOff);
- end
- else begin {if end of sound array...}
- Dec(NumRepeats); {decrement number of repeats}
- if NumRepeats > 0 then begin {if we must repeat...}
- SoundOff := 3; {reset offset into array}
- SoundCount := MySound^[1]; {get duration of first note}
- Sound(10*MySound^[2]); {start it up}
- end
- else begin {if all repeats now done...}
- NoSound; {stop all sound}
- MakeSound := FALSE; {reset flag}
- end;
- end;
- end; {if SoundCount = 0}
- end; {if making a sound}
- end; {TimerInt interrupt procedure}
-
- begin
-
- SndFlg := TRUE; {sounds are allowed}
- MakeSound := FALSE; {sound initially off}
- MyClock := 0; {reset timer}
- New1CInt := @TimerInt; {get address of interrupt}
-
- end.
-