home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
msdos
/
asmutl
/
bluebook.arc
/
SOUND.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-08
|
9KB
|
354 lines
COMMENT ~
SOUND.ASM -- Sound Generation Routines
From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
by Christopher L. Morgan
Copyright (C) 1984 by The Waite Group, Inc.
SOUND.ASM contains a collection of assembly language routines for producing
sound in MS/PCDOS 8088 assembly language, using MASM. These routines are
FAR PROCEDURES.
Contents:
---------
DELAY -- Delay for a specified time interval
FREQ -- Convert from frequency to period
GLISSNDO -- Make a glissando (sliding tone)
LINSCALE -- Provide linear scaling
PITCH -- Convert from pitch number
PLAY -- Play music from a table
TONE -- Make a tone
TONE_INIT -- Initialize speaker timer
TONE_OFF -- Turn off tone
TONE_ON -- Turn on tone
TONE_SET -- Set the tone on the speaker
>>>>> See SOUND.DOC for complete descriptions of these routines <<<<<
_____________________________ SOUND ROUTINES_________________________________
It is best to include this data in the source code calling these routines,
and then commenting out this next section. ~
DATAS SEGMENT PUBLIC
NOTES DW 4186 ;C
DW 4435 ;C#/D-
DW 4699 ;D
DW 4978 ;D#/E-
DW 5274 ;E
DW 5588 ;F
DW 5920 ;F#/G-
DW 6272 ;G
DW 6645 ;G#/A-
DW 7040 ;A
DW 7459 ;A#/B-
DW 7902 ;B
WHOLE DW 0
F_START DW 0
F_END DW 0
DATAS ENDS
;------------------------------------------------------------------------------
CODES SEGMENT
PUBLIC DELAY,FREQ,GLISSANDO,LINSCALE,PITCH,PLAY
PUBLIC TONE,TONE_INIT,TONE_OFF,TONE_ON,TONE_SET
ASSUME CS:CODES,DS:DATAS
;------------------------------------------------------------------------------
;Routine to set tone
;
TONE_INIT PROC FAR
PUSH AX ;Save register
;
;Define control bit field parameters for the timer chip
SC = 2 ;Use counter 2
RL = 3 ;Mode load period 1 byte/time
MODE = 3 ;Square wave generator
BCD = 0 ;Not BCD, use binary values
;
;Form control word
CNWORD = SC * 40H + RL * 10H + MODE * 2 + BCD
;
;Send control word to 8253 timer chip
MOV AL,CNWORD ;Select the above control word
OUT 43H,AL ;Send it to the control port
POP AX ;Restore register
RET
TONE_INIT ENDP
;------------------------------------------------------------------------------
;Routine to select tone
;
TONE_SET PROC FAR
PUSH AX ;Save register
;
;Load the time period into the timer
MOV AL,CL ;Lower byte
OUT 42H,AL ;Out to timer
MOV AL,CH ;Upper byte
OUT 42H,AL ;Out to timer
POP AX ;Restore register
RET
TONE_SET ENDP
;------------------------------------------------------------------------------
;Routine to turn on tone
;
TONE_ON PROC FAR
PUSH AX ;Save register
;
;Turn speaker and timer on
IN AL,61H ;Get contents of system port B
OR AL,3 ;Turn speaker and timer on
OUT 61H,AL ;Send out new values to port B
POP AX ;Restore register
RET
TONE_ON ENDP
;------------------------------------------------------------------------------
;Routine to turn Tone off
;
TONE_OFF PROC FAR
PUSH AX ;Save register
;
;Turn off timer 2 and speaker
IN AL,61H ;Get port B again
AND AL,11111100B ;Turn off timer & speaker
OUT 61H,AL ;Now do it
POP AX ;Restore register
RET
TONE_OFF ENDP
;------------------------------------------------------------------------------
;Routine to delay a specified number of milliseconds
;
DELAY PROC FAR
PUSH CX ;Save register
DELAY1:
PUSH CX ;Save counter
MOV CX,260 ;Timing constant
DELAY2:
LOOP DELAY2 ;Small loop
POP CX ;Restore counter
LOOP DELAY1 ;Loop to count milliseconds
POP CX ;Restore register
RET
DELAY ENDP
;------------------------------------------------------------------------------
;Routine to convert from frequency to period
;
FREQ PROC FAR
PUSH DX ;Save registers
PUSH AX
MOV DX,12H ;Upper part of numerator
MOV AX,34DEH ;Lower part of numerator
DIV CX ;Divide by frequency
MOV CX,AX ;The quotient is the output
POP AX ;Restore registers
POP DX
RET
FREQ ENDP
;------------------------------------------------------------------------------
;Routine to make a tone
;
TONE PROC FAR
PUSH DX ;Save registers
PUSH CX
PUSH AX
;
;Compute the frequency and set up the tone
CALL FREQ ;Convert the frequency
CALL TONE_SET ;Set up the tone
;
;Turn on the tone
CALL TONE_ON ;Turn it on
;
;Wait for proper delay
MOV CX,DX ;Get delay length
CALL DELAY
;
;Turn off the tone
CALL TONE_OFF ;Turn it off
POP AX ;Restore registers
POP CX
POP DX
RET
TONE ENDP
;------------------------------------------------------------------------------
;Routine to scale linearly
;
LINSCALE PROC FAR
PUSH DX ;Save registers
PUSH AX
;
;Compute width
MOV AX,F_END ;Get F_END
SUB AX,F_START ;Subtract F_START
;
;Multiply width by input parameter
MUL CX ;Multiply
MOV CX,DX ;Move top part of quotient
; ; into CX
;Add lower limit
ADD CX,F_START ;Add F_START
POP AX ;Restore registers
POP DX
RET
LINSCALE ENDP
;------------------------------------------------------------------------------
;Routine to determine pitch
;
PITCH PROC FAR
PUSH CX ;Save registers
PUSH BX
PUSH AX
MOV AH,0 ;Extend pitch no. to 16 bits
MOV CL,12 ;Divisor of 12
DIV CL ;Divide
MOV DL,AL ;Quotient determines the octave
MOV AL,AH ;Remainder is the pitch within
CBW ; 16-bit needed for look up
SAL AX,1 ; 2 bytes/item
MOV BX,AX ; into BX
MOV CX,NOTES[BX] ;Look it up
CALL FREQ ;Convert the frequency
XCHG CX,DX ;Octave in CL, period in DX
NEG CL ;8 - octave = shift count
ADD CL,8
SAL DX,CL
POP AX ;Restore registers
POP BX
POP CX
RET
PITCH ENDP
;------------------------------------------------------------------------------
;Routine to make glissando
;
GLISSANDO PROC FAR
PUSH SI ;Save registers
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV F_START,BX ;FROM limit of frequencies
MOV F_END,CX ; TO limit of frequencies
CALL TONE_ON ;Turn on tone
;
;Set up the loop parameters
MOV SI,1 ;Increment for loop
CMP BX,CX ;Up or down?
JLE GLISS1 ;Skip if up
NEG SI ;Decrement freq in the loop
GLISS1:
MOV CX,BX ;Get the frequency
CALL FREQ ;Convert to clock cycles
CALL TONE_SET ;Set the tone
MOV CX,DX ;Delay parameter > slows slide
GLISS2:
LOOP GLISS2
CMP BX,F_END ;Check if done
JE GLISS3 ;If so, go
ADD BX,SI ;Else update the frequency
JMP GLISS1
;
;Turn off the tone
GLISS3:
CALL TONE_OFF ;Turn it off
POP AX ;Restore registers
POP BX
POP CX
POP DX
POP SI
RET
GLISSANDO ENDP
;------------------------------------------------------------------------------
;Routine to play music
;
PLAY PROC FAR
PUSH DS ;Save registers
PUSH SI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
;
;Command pointer is in SI
MOV WHOLE,2000 ;Whole note = 2000 milliseconds
CLD ;Forward direction
;
;Main loop starts here
CHEK_END: ;Get command code and go
; through the cases
LODSB ;Get the byte
;
;End command
CMP AL,'X' ;Is it End command?
JNE CHEK_TEMPO
JMP PLAY_XIT
;
;Tempo command
CHEK_TEMPO:
CMP AL,'T' ;Is it Tempo command?
JNE CHEK_NOTE
LODSB ;Get the tempo
MOV CL,AL ;Set in CX
MOV CH,0
MOV AX,60000 ;No. of milliseconds/minute
MOV DX,0 ;Clear upper part
DIV CX ;Divide into time
MOV WHOLE,AX ;No. of milliseconds/whole note
JMP CHEK_END ;Back for more
;
;Note command
CHEK_NOTE:
CMP AL,'N' ;Is it Note command?
JNE CHEK_REST
LODSB ;Get the pitch
CALL PITCH ;Convert
MOV CX,DX ; and move result into CX
CALL TONE_SET ;Set the frequency
CALL TONE_ON ;Turn on the tone
MOV CX,WHOLE ;No. of milliseconds/whole note
LODSB ;Get the duration
MOV AH,AL ;Set up duration as multiplier
MOV AL,0
SAL CX,1 ;Scale factor 1
MUL CX ;Multiply
MOV CX,DX ;Total count for the note
LODSB ;Get style
MOV AH,AL ;Set up style as multiplier
MOV AL,0
MUL CX ;Multiply by style
MOV F_START,DX ;Store count for note
SUB CX,DX ;Count for rest
MOV F_END,CX ;Store count for rest
MOV CX,F_START ;Audible part of note
CALL DELAY ;Delay
CALL TONE_OFF ;Turn off the tone
MOV CX,F_END ;Inaudible part of tone
CALL DELAY ;Delay
JMP CHEK_END ;Back for more
;
;Rest command
CHEK_REST:
CMP AL,'R' ;Is it Rest command?
JNE PLAY_XIT
MOV CX,WHOLE ;No. of milliseconds/whole note
LODSB ;Get the duration
MOV AH,AL ;Set up duration as multiplier
MOV AL,0
SAL CX,1 ;Scale factor of 1
MUL CX ;Multiply
MOV CX,DX ;Total count
CALL DELAY ;Delay
JMP CHEK_END ;Back for more
;
;Anything else end it
PLAY_XIT:
POP AX ;Restore registers
POP BX
POP CX
POP DX
POP SI
POP DS
RET
PLAY ENDP
;-----------------------------------------------------------------------------
CODES ENDS
;
END
;_____________________________________________________________________________
;>>>>>Physical EOF SOUND.ASM<<<<<