title    Talker
;        Modified from TPSPCH.ARC found on CompuServe IBMPro forum, DL 5
;        David Neal Dubois
;        Michael Day
;        released to public domain by authors 
;        as of 22 April 1989

ideal
model tpascal
codeseg
public Talker

; Outputs sound sample beginning at address Start, and continuing for
; Count bytes.

proc Talker far Start:dword,Count:word,Speed:word,Resolve:word,Sound:word
            uses DS

      in    Al, 61h              ; Save state of speaker
      push  AX
      mov   AH,AL
      and   AH,0FFH-3            ; weed out the speaker control bits

      mov   ES, [ Speed ]        ; Get speed delay 
      lds   SI, [ Start ]        ; Get address of Start
      mov   DI, [ Count ]        ; Get count
      mov   BX, [ Resolve ]      ; resolution of speech
      mov   CX, [ Sound ]        ; generate sound or cal only?
      cmp   BL, 3                ; 1 or 2 is OK
      jb    OutByteX             ; 3 becomes 4
      cmp   BL,6                 ; 4 is OK
      jb    OutByte4
      mov   BL,8                 ; anything else becomes 8
      jmp   OutByteX

OutByte4:
      mov   BL, 4                ; must be 1, 2, 4, or 8 only
OutByteX:
      cmp   CL, 0                ; 0 = no sound
      jz    NoByte               ; nz = do sound

OutByte:
      lodsb                      ; Get a byte
      mov   DH, AL               ; save it in DH
      mov   DL, 8                ; DL will hold number of bits left in byte
      rol   DH, 1                ; Position first bit to output

OutBit:
      mov   AL, DH               ; Move into AL
      and   AL, 02h              ; Leave only that bit
      or    AL, AH               ; Set speaker's other mystery bits
      out   61h, AL              ; Send to speaker

      mov   CX, ES               ; Wait
Blah: loop  Blah

      mov   CL, BL
      rol   DH, CL               ; Get next bit to output
      sub   DL, BL               ; All bits done in this byte?
      jnz   OutBit               ; no: Process next bit

      dec   DI                   ; All bytes done?
      jnz   OutByte              ; no: Process next byte

      jmp TalkDone               ; all done

NoByte:
      lodsb                      ; Get a byte
      mov   DH, AL               ; save it in DH
      mov   DL, 8                ; DL will hold number of bits left in byte
      rol   DH, 1                ; Position first bit to output

NoBit:
      mov   AL, DH               ; Move into AL
      and   AL, 02h              ; Leave only that bit
      or    AL, AH               ; Set speaker's other mystery bits
      in    AL, 61h              ; dummy input from speaker for timming

      mov   CX, ES               ; Wait
NoBlah: loop  NoBlah

      mov   CL, BL
      rol   DH, CL               ; Get next bit to output
      sub   DL, BL               ; All bits done in this byte?
      jnz   NoBit               ; no: Process next bit

      dec   DI                   ; All bytes done?
      jnz   NoByte              ; no: Process next byte



TalkDone:
      pop   AX                   ; Restore state of speaker
      out   61h, AL

      ret
endp  Talker

ends
end


