[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]
UNIT Tone; {$S-,R-,D-,L-}
(* TONE.PAS - Sound Module for Turbo Pascal 6.0 - Turbo Vision
* Written by Richard R. Sands
* Compuserve ID 70274,103
* January 1991
*
* NOTE: Do Not Overlay
*)
INTERFACE
Procedure Sound(Hz:Word);
Procedure NoSound;
Procedure Delay(MS : Word);
Procedure Beep(Hz, MS:Word);
{ Same as
Sound(Hz);
Delay(MS);
NoSound; ...but with more efficient code. }
Procedure BoundsBeep;
{ Used for signalling a boundry or invalid command }
Procedure ErrorBeep;
{ Used for signalling an error condition }
Procedure AttentionBeep;
{ Used for signalling the user }
IMPLEMENTATION
VAR
OneMS : Word;
{ ------------------------------------------------------------------------- }
Procedure Beep(Hz, MS:Word); assembler;
{ Make the Sound at Frequency Hz for MS milliseconds }
ASM
MOV BX,Hz
MOV AX,34DDH
MOV DX,0012H
CMP DX,BX
JNC @Stop
DIV BX
MOV BX,AX
IN AL,61H
TEST AL,3
JNZ @99
OR AL,3
OUT 61H,AL
MOV AL,0B6H
OUT 43H,AL
@99:
MOV AL,BL
OUT 42H,AL
MOV AL,BH
OUT 42H,AL
@Stop:
{$IFOPT G+}
PUSH MS
{$ELSE }
MOV AX, MS { push delay time }
PUSH AX
{$ENDIF }
CALL Delay { and wait... }
IN AL, $61 { Now turn off the speaker }
AND AL, $FC
OUT $61, AL
end;
{ ------------------------------------------------------------------------- }
Procedure BoundsBeep; assembler;
asm
{$IFOPT G+ }
PUSH 1234 { Pass the Frequency }
PUSH 10 { Pass the delay time }
{$ELSE}
MOV AX, 1234 { Pass the Frequency }
PUSH AX
MOV AX, 10 { Pass the delay time }
PUSH AX
{$ENDIF }
CALL Beep
end;
{ ------------------------------------------------------------------------- }
Procedure ErrorBeep; assembler;
asm
{$IFOPT G+ }
PUSH 800 { Pass the Frequency }
PUSH 75 { Pass the delay time }
{$ELSE}
MOV AX, 800 { Pass the Frequency }
PUSH AX
MOV AX, 75 { Pass the delay time }
PUSH AX
{$ENDIF }
CALL Beep
end;
{ ------------------------------------------------------------------------- }
Procedure AttentionBeep; assembler;
asm
{$IFOPT G+ }
PUSH 660 { Pass the Frequency }
PUSH 50 { Pass the delay time }
{$ELSE}
MOV AX, 660 { Pass the Frequency }
PUSH AX
MOV AX, 50 { Pass the delay time }
PUSH AX
{$ENDIF }
CALL Beep
end;
{ ------------------------------------------------------------------------- }
Procedure Sound(Hz:Word); assembler;
ASM
MOV BX,Hz
MOV AX,34DDH
MOV DX,0012H
CMP DX,BX
JNC @DONE
DIV BX
MOV BX,AX
IN AL,61H
TEST AL,3
JNZ @99
OR AL,3
OUT 61H,AL
MOV AL,0B6H
OUT 43H,AL
@99: MOV AL,BL
OUT 42H,AL
MOV AL,BH
OUT 42H,AL
@DONE:
end;
{ ------------------------------------------------------------------------- }
Procedure NoSound; assembler;
asm
IN AL, $61
AND AL, $FC
OUT $61, AL
end;
{ ------------------------------------------------------------------------- }
procedure DelayOneMS; assembler;
asm
PUSH CX { Save CX }
MOV CX, OneMS { Loop count into CX }
@1:
LOOP @1 { Wait one millisecond }
POP CX { Restore CX }
end;
{ ------------------------------------------------------------------------- }
Procedure Delay(ms:Word); assembler;
asm
MOV CX, ms
JCXZ @2
@1:
CALL DelayOneMS
LOOP @1
@2:
end;
{ ------------------------------------------------------------------------- }
Procedure Calibrate_Delay; assembler;
asm
MOV AX,40h
MOV ES,AX
MOV DI,6Ch { ES:DI is the low word of BIOS timer count }
MOV OneMS,55 { Initial value for One MS's time }
XOR DX,DX { DX = 0 }
MOV AX,ES:[DI] { AX = low word of timer }
@1:
CMP AX,ES:[DI] { Keep looking at low word of timer }
JE @1 { until its value changes... }
MOV AX,ES:[DI] { ...then save it }
@2:
CAll DelayOneMs { Delay for a count of OneMS (55) }
INC DX { Increment loop counter }
CMP AX,ES:[DI] { Keep looping until the low word }
JE @2 { of the timer count changes again }
MOV OneMS, DX { DX has new OneMS }
end;
BEGIN
Calibrate_Delay
END.
{ ============================== DEMO ==================================}
Program ToneTest;
USES Tone;
begin
ErrorBeep;
Delay(500);
AttentionBeep;
Delay(500);
BoundsBeep;
Delay(500);
Beep(440, 250);
end.
[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]