home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / bluebook.zip / SOUND.ASM < prev    next >
Assembly Source File  |  1986-05-08  |  9KB  |  354 lines

  1.                                         COMMENT ~
  2. SOUND.ASM -- Sound Generation Routines
  3.  
  4.    From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
  5.          by Christopher L. Morgan
  6.          Copyright (C) 1984 by The Waite Group, Inc.
  7.  
  8.   SOUND.ASM contains a collection of assembly language routines for producing
  9.     sound in MS/PCDOS 8088 assembly language, using MASM. These routines are
  10.     FAR PROCEDURES.
  11.  
  12.    Contents:
  13.    ---------
  14.    DELAY    --  Delay for a specified time interval    
  15.    FREQ        --  Convert from frequency to period
  16.    GLISSNDO    --  Make a glissando (sliding tone)
  17.    LINSCALE    --  Provide linear scaling
  18.    PITCH    --  Convert from pitch number    
  19.    PLAY        --  Play music from a table
  20.    TONE        --  Make a tone
  21.    TONE_INIT    --  Initialize speaker timer
  22.    TONE_OFF    --  Turn off tone
  23.    TONE_ON    --  Turn on tone
  24.    TONE_SET    --  Set the tone on the speaker
  25.    
  26.       >>>>> See SOUND.DOC for complete descriptions of these routines <<<<<
  27.  
  28.  _____________________________ SOUND ROUTINES_________________________________
  29.   It is best to include this data in the source code calling these routines,
  30.     and then commenting out this next section.                                ~
  31. DATAS    SEGMENT    PUBLIC
  32. NOTES    DW    4186    ;C
  33.     DW    4435    ;C#/D-
  34.     DW    4699    ;D
  35.     DW    4978    ;D#/E-
  36.     DW    5274    ;E
  37.     DW    5588    ;F
  38.     DW    5920    ;F#/G-
  39.     DW    6272    ;G
  40.     DW    6645    ;G#/A-
  41.     DW    7040    ;A
  42.     DW    7459    ;A#/B-
  43.     DW    7902    ;B
  44. WHOLE    DW    0
  45. F_START    DW    0
  46. F_END    DW    0
  47. DATAS    ENDS
  48. ;------------------------------------------------------------------------------
  49. CODES    SEGMENT
  50. PUBLIC    DELAY,FREQ,GLISSANDO,LINSCALE,PITCH,PLAY
  51. PUBLIC  TONE,TONE_INIT,TONE_OFF,TONE_ON,TONE_SET
  52.     ASSUME     CS:CODES,DS:DATAS
  53. ;------------------------------------------------------------------------------
  54. ;Routine to set tone
  55. ;
  56. TONE_INIT    PROC    FAR
  57.     PUSH    AX                ;Save register
  58. ;
  59. ;Define control bit field parameters for the timer chip
  60. SC    =    2                ;Use counter 2
  61. RL    =    3                ;Mode load period 1 byte/time
  62. MODE    =    3                ;Square wave generator
  63. BCD    =    0                ;Not BCD, use binary values
  64. ;
  65. ;Form control word
  66. CNWORD    =    SC * 40H + RL * 10H + MODE * 2 + BCD
  67. ;
  68. ;Send control word to 8253 timer chip
  69.     MOV    AL,CNWORD            ;Select the above control word
  70.     OUT    43H,AL                ;Send it to the control port
  71.     POP    AX                ;Restore register
  72.     RET
  73. TONE_INIT    ENDP
  74. ;------------------------------------------------------------------------------
  75. ;Routine to select tone
  76. ;
  77. TONE_SET    PROC    FAR
  78.     PUSH    AX                ;Save register
  79. ;
  80. ;Load the time period into the timer
  81.     MOV    AL,CL                ;Lower byte
  82.     OUT    42H,AL                ;Out to timer
  83.     MOV    AL,CH                ;Upper byte
  84.     OUT    42H,AL                ;Out to timer
  85.     POP    AX                ;Restore register
  86.     RET
  87. TONE_SET    ENDP
  88. ;------------------------------------------------------------------------------
  89. ;Routine to turn on tone
  90. ;
  91. TONE_ON    PROC    FAR
  92.     PUSH    AX                ;Save register
  93. ;
  94. ;Turn speaker and timer on
  95.     IN    AL,61H                ;Get contents of system port B
  96.     OR    AL,3                ;Turn speaker and timer on
  97.     OUT    61H,AL                ;Send out new values to port B
  98.     POP    AX                ;Restore register
  99.     RET
  100. TONE_ON    ENDP
  101. ;------------------------------------------------------------------------------
  102. ;Routine to turn Tone off
  103. ;
  104. TONE_OFF    PROC    FAR
  105.     PUSH    AX                ;Save register
  106. ;
  107. ;Turn off timer 2 and speaker
  108.     IN    AL,61H                ;Get port B again
  109.     AND    AL,11111100B            ;Turn off timer & speaker
  110.     OUT    61H,AL                ;Now do it
  111.     POP    AX                ;Restore register
  112.     RET
  113. TONE_OFF    ENDP
  114. ;------------------------------------------------------------------------------
  115. ;Routine to delay a specified number of milliseconds
  116. ;
  117. DELAY    PROC    FAR
  118.     PUSH    CX                ;Save register
  119. DELAY1:
  120.     PUSH    CX                ;Save counter
  121.     MOV    CX,260                ;Timing constant
  122. DELAY2:
  123.     LOOP    DELAY2                ;Small loop
  124.     POP    CX                ;Restore counter
  125.     LOOP    DELAY1                ;Loop to count milliseconds
  126.     POP    CX                ;Restore register
  127.     RET
  128. DELAY    ENDP
  129. ;------------------------------------------------------------------------------
  130. ;Routine to convert from frequency to period
  131. ;
  132. FREQ    PROC    FAR
  133.     PUSH    DX                ;Save registers
  134.     PUSH    AX
  135.     MOV    DX,12H                ;Upper part of numerator
  136.     MOV    AX,34DEH            ;Lower part of numerator
  137.     DIV    CX                ;Divide by frequency
  138.     MOV    CX,AX                ;The quotient is the output
  139.     POP    AX                ;Restore registers
  140.     POP    DX
  141.     RET
  142. FREQ    ENDP
  143. ;------------------------------------------------------------------------------
  144. ;Routine to make a tone
  145. ;
  146. TONE    PROC    FAR
  147.     PUSH    DX                ;Save registers
  148.     PUSH    CX        
  149.     PUSH    AX
  150. ;
  151. ;Compute the frequency and set up the tone
  152.     CALL    FREQ                ;Convert the frequency
  153.     CALL    TONE_SET            ;Set up the tone
  154. ;
  155. ;Turn on the tone
  156.     CALL    TONE_ON                ;Turn it on
  157. ;
  158. ;Wait for proper delay
  159.     MOV    CX,DX                ;Get delay length
  160.     CALL    DELAY                
  161. ;
  162. ;Turn off the tone
  163.     CALL    TONE_OFF            ;Turn it off
  164.     POP    AX                ;Restore registers
  165.     POP    CX    
  166.     POP    DX
  167.     RET
  168. TONE    ENDP
  169. ;------------------------------------------------------------------------------
  170. ;Routine to scale linearly
  171. ;
  172. LINSCALE    PROC    FAR
  173.     PUSH    DX                ;Save registers
  174.     PUSH    AX
  175. ;
  176. ;Compute width
  177.     MOV    AX,F_END            ;Get F_END
  178.     SUB    AX,F_START            ;Subtract F_START
  179. ;
  180. ;Multiply width by input parameter
  181.     MUL    CX                ;Multiply
  182.     MOV    CX,DX                ;Move top part of quotient
  183. ;                        ; into CX
  184. ;Add lower limit    
  185.     ADD    CX,F_START            ;Add F_START
  186.     POP    AX                ;Restore registers
  187.     POP    DX
  188.     RET
  189. LINSCALE    ENDP
  190. ;------------------------------------------------------------------------------
  191. ;Routine to determine pitch
  192. ;
  193. PITCH    PROC    FAR
  194.     PUSH    CX                ;Save registers
  195.     PUSH    BX
  196.     PUSH    AX
  197.     MOV    AH,0                ;Extend pitch no. to 16 bits
  198.     MOV    CL,12                ;Divisor of 12
  199.     DIV    CL                ;Divide
  200.     MOV    DL,AL                ;Quotient determines the octave
  201.     MOV    AL,AH                ;Remainder is the pitch within
  202.     CBW                    ; 16-bit needed for look up
  203.     SAL    AX,1                ; 2 bytes/item
  204.     MOV    BX,AX                ; into BX
  205.     MOV    CX,NOTES[BX]            ;Look it up
  206.     CALL    FREQ                ;Convert the frequency
  207.     XCHG    CX,DX                ;Octave in CL, period in DX
  208.     NEG    CL                ;8 - octave = shift count
  209.     ADD    CL,8    
  210.     SAL    DX,CL
  211.     POP    AX                ;Restore registers
  212.     POP    BX
  213.     POP    CX
  214.     RET
  215. PITCH    ENDP
  216. ;------------------------------------------------------------------------------
  217. ;Routine to make glissando
  218. ;
  219. GLISSANDO    PROC    FAR
  220.     PUSH    SI                ;Save registers
  221.     PUSH    DX
  222.     PUSH    CX
  223.     PUSH    BX
  224.     PUSH    AX
  225.     MOV    F_START,BX            ;FROM limit of frequencies
  226.     MOV    F_END,CX            ;  TO limit of frequencies
  227.     CALL    TONE_ON                ;Turn on tone
  228. ;
  229. ;Set up the loop parameters
  230.     MOV    SI,1                ;Increment for loop
  231.     CMP    BX,CX                ;Up or down?
  232.     JLE    GLISS1                ;Skip if up
  233.     NEG    SI                ;Decrement freq in the loop
  234. GLISS1:
  235.     MOV    CX,BX                ;Get the frequency
  236.     CALL    FREQ                ;Convert to clock cycles
  237.     CALL    TONE_SET            ;Set the tone
  238.     MOV    CX,DX                ;Delay parameter > slows slide
  239. GLISS2:
  240.     LOOP    GLISS2
  241.     CMP    BX,F_END            ;Check if done
  242.     JE    GLISS3                ;If so, go
  243.     ADD    BX,SI                ;Else update the frequency
  244.     JMP    GLISS1
  245. ;
  246. ;Turn off the tone
  247. GLISS3:
  248.     CALL    TONE_OFF            ;Turn it off
  249.     POP    AX                ;Restore registers
  250.     POP    BX
  251.     POP    CX
  252.     POP    DX
  253.     POP    SI
  254.     RET
  255. GLISSANDO    ENDP    
  256. ;------------------------------------------------------------------------------
  257. ;Routine to play music
  258. ;
  259. PLAY    PROC    FAR
  260.     PUSH    DS                ;Save registers
  261.     PUSH    SI
  262.     PUSH    DX
  263.     PUSH    CX
  264.     PUSH    BX
  265.     PUSH    AX
  266. ;
  267. ;Command pointer is in SI
  268.     MOV    WHOLE,2000            ;Whole note = 2000 milliseconds
  269.     CLD                    ;Forward direction
  270. ;
  271. ;Main loop starts here
  272. CHEK_END:                    ;Get command code and go
  273.                         ; through the cases
  274.     LODSB                    ;Get the byte
  275. ;
  276. ;End command
  277.     CMP    AL,'X'                ;Is it End command?
  278.     JNE    CHEK_TEMPO
  279.     JMP    PLAY_XIT
  280. ;
  281. ;Tempo command
  282. CHEK_TEMPO:
  283.     CMP    AL,'T'                ;Is it Tempo command?
  284.     JNE    CHEK_NOTE
  285.     LODSB                    ;Get the tempo
  286.     MOV    CL,AL                ;Set in CX
  287.     MOV    CH,0            
  288.     MOV    AX,60000            ;No. of milliseconds/minute
  289.     MOV    DX,0                ;Clear upper part
  290.     DIV    CX                ;Divide into time
  291.     MOV    WHOLE,AX            ;No. of milliseconds/whole note
  292.     JMP    CHEK_END            ;Back for more
  293. ;
  294. ;Note command
  295. CHEK_NOTE:
  296.     CMP    AL,'N'                ;Is it Note command?
  297.     JNE    CHEK_REST
  298.     LODSB                    ;Get the pitch
  299.     CALL    PITCH                ;Convert
  300.     MOV    CX,DX                ; and move result into CX
  301.     CALL    TONE_SET            ;Set the frequency
  302.     CALL    TONE_ON                ;Turn on the tone
  303.     MOV    CX,WHOLE            ;No. of milliseconds/whole note
  304.     LODSB                    ;Get the duration
  305.     MOV    AH,AL                ;Set up duration as multiplier
  306.     MOV    AL,0
  307.     SAL    CX,1                ;Scale factor 1
  308.     MUL    CX                ;Multiply
  309.     MOV    CX,DX                ;Total count for the note
  310.     LODSB                    ;Get style
  311.     MOV    AH,AL                ;Set up style as multiplier
  312.     MOV    AL,0                
  313.     MUL    CX                ;Multiply by style
  314.     MOV    F_START,DX            ;Store count for note
  315.     SUB    CX,DX                ;Count for rest
  316.     MOV    F_END,CX            ;Store count for rest
  317.     MOV    CX,F_START            ;Audible part of note
  318.     CALL    DELAY                ;Delay
  319.     CALL     TONE_OFF            ;Turn off the tone
  320.     MOV    CX,F_END            ;Inaudible part of tone
  321.     CALL    DELAY                ;Delay
  322.     JMP    CHEK_END            ;Back for more
  323. ;
  324. ;Rest command
  325. CHEK_REST:
  326.     CMP    AL,'R'                ;Is it Rest command?
  327.     JNE    PLAY_XIT
  328.     MOV    CX,WHOLE            ;No. of milliseconds/whole note
  329.     LODSB                    ;Get the duration
  330.     MOV    AH,AL                ;Set up duration as multiplier
  331.     MOV    AL,0                
  332.     SAL    CX,1                ;Scale factor of 1
  333.     MUL    CX                ;Multiply
  334.     MOV    CX,DX                ;Total count
  335.     CALL    DELAY                ;Delay
  336.     JMP    CHEK_END            ;Back for more
  337. ;
  338. ;Anything else end it
  339. PLAY_XIT:
  340.     POP    AX                ;Restore registers
  341.     POP    BX
  342.     POP    CX
  343.     POP    DX
  344.     POP    SI
  345.     POP    DS
  346.     RET
  347. PLAY    ENDP
  348. ;-----------------------------------------------------------------------------
  349. CODES    ENDS
  350. ;
  351.     END
  352. ;_____________________________________________________________________________
  353. ;>>>>>Physical EOF SOUND.ASM<<<<<    
  354.