home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
music
/
dousound.arc
/
DOUSOUND.ASM
next >
Wrap
Assembly Source File
|
1989-09-22
|
8KB
|
272 lines
Title DouSound - Two channel sound routine
; Written by Ori Berger
; Phone number 972-(0)3-540-1519
;
Comment @
This program simulates 2 channel sound using the regular PC speaker. This
program was written so that is will work on any speed, not depending on
the CPU. This is doneby re-vectoring and re-speeding interrupt 8 (IRQ0).
The tune here was taken from 'The great Gianna sisters', and was composed
by Chris Huelsback (somewhere in england). The data is given in half tones,
so
C = 1
C#= 2
D = 3
etc.
Try replacing SetC1 with SetC2 because the channels sound differently,
and which channel is better as the main channel (40h,40h,43h) is depending
on the tune.
Should be assembled under MASM 5.0 or TASM 1.0, and either LINK and EXE2BIN
or TLINK /T.
@
SetC1 Macro Rate
Mov Al,0b6h ; Set channel two speed!
Out 43h,Al ; Set mode
Mov Ax,Rate
Out 42h,Al
Mov Al,Ah
Out 42h,Al
Endm
SetC2 Macro Rate
Mov Al,036h
Out 43h,Al
Mov Ax,Rate
; This is a test - now we should try alternating frequencies!
Shl Ax,1
Shl Ax,1
Shl Ax,1
Shr Rate,1
Shr Rate,1
Shr Rate,1
Shr Rate,1
Add Ax,Rate
Shr Ax,1
Shr Ax,1
Shr Ax,1
; The following line should be removed if there's no need for timing.
Mov Cs:C2Rate,Ax
;
Out 40h,Al
Mov Al,Ah
Out 40h,Al
Endm
Speed Equ 4 ; speed in 1/18.2 of second per note.
Code Segment
Assume CS:Code,Ds:Code,Es:Code,Ss:Code
Org 100h
Start: Jmp Program
; This area holds timing parameters - count, rate, etc.
; C2 rate is the current rate for channel 2 - must be used to determine time.
; Tick18 is used both as a counter and as an indicator of the time to add to
; the bios ticker value.
; C2 roll is an accumulated value - an roll over means 1/18.2 of a second.
C2Rate Dw ?
C2Roll Dw ?
Ticks18 Dw ?
OldInt8 Dw ?,?
Int8 Proc Far
Push Ax
In Al,61h
Xor Al,2
Out 61h,Al
; These commands should be removed if timing is not dealt through clock 0
Mov Ax,Cs:C2Rate
Add Cs:C2Roll,Ax
Adc Cs:Ticks18,0
; This ends the commands to be removed
Mov Al,20h
Out 20h,Al
Pop Ax
Iret
Int8 Endp
; FreqTabl is the Frequency table (compiled!) for lowest octave.
FreqTabl Dw 4560,4304,4062,3834,3619,3416,3224,3043,2873,2711,2559,2416
; C C# D D# E F F# G G# A A# B
Sound Proc Near ; Sound CX on channel 1, DX on channel 2
Push Ax
SetC1 Dx
SetC2 Cx
Pop Ax
Ret
Sound Endp
AlterOct Db 0
MakeTAB Proc Near ; Builds a table of output values - from DS:SI and DS:DX into ES:DI, -1 is terminal!
Push Ax
Push Si
Push Dx
Push Bx
Push Di
Push Cx
Cld
Mov Ch,12 ; Length of octave - speed constant!
Loop001: Lodsb ; Get next note.
Inc Al ; is it a terminal?
Jz MkTABend ; if so, EXIT!
Dec Al ; Restore orig value.
Add Al,Ch ; I've discovered higher sounds better!
Cbw ; If not, we have to find the FREQUENCY!
Mov Cl,Ah ; AH is zero from the CBW.
Loop002: Cmp Al,Ch ; Now do octave shifting!
Jb NoAdj ; if in range 0-11 no need to do octave adjusting.
Sub Al,Ch ; Put it in range
Inc Cl ; And mark one shift.
Jmp Loop002 ; Repeat till in range
NoAdj: Shl Ax,1 ; It is a WORD table.
Mov Bx,Ax ; AX cannot address
Mov Ax,FreqTabl[Bx] ; Get the exact count for known octave
Or Cl,Cl ; Are we using octave 1? (NoAdjAg means No Adjust Again)
Jz NoAdjAg ; If so, no need to shift on 8086 (80286/Vx0 must not shift!)
Shr Ax,Cl ; Now the RIGHT count is in Ax
NoAdjAg: Stosw ; Put it in the output buffer.
Xor Ah,Ah ; Zero AH again.
Xchg Dx,Si ; Now, to the second channel....
Jmp Loop001 ; Redo this operation (channels alternate)
MkTABend:
Xor Ax,Ax ; Zero AX
Stosw ; Put two terminals in output
Stosw
Pop Cx
Pop Di
Pop Bx
Pop Dx
Pop Si
Pop Ax
Ret
MakeTAB Endp
Before Proc Near ; BEFORE action handler.
Push Ax ; 1. Steal INT8.
Push Bx
Push Es
Push Dx
Push Ds
Mov Ax,3508h ; Dos code for GetIntVec (8)
Int 21h
Mov OldInt8[0],Bx ; Offset
Mov OldInt8[2],Es ; Segment
Mov Dx,Offset Int8 ; Point DS:DX at int 8 routine
Mov Ax,Cs
Mov Ds,Ax
Mov Ax,2508h
Int 21h
In Al,61h ; Now we need to gate channel 2 to the speaker
Or Al,1 ; GATE value
Out 61h,Al ; We must not disturb other bits.
Mov Dx,3f2h
Mov Al,0ch
Out Dx,Al
Pop Ds
Pop Dx
Pop Es
Pop Bx
Pop Ax
Ret
Before Endp
After Proc Near
Push Ax
Push Dx
Push Ds
Mov Ax,2508h
Lds Dx,Dword Ptr OldInt8
Int 21h
Mov Al,36h
Out 43h,Al
Sub Al,Al
Out 40h,Al
Out 40h,Al
In Al,61h
And Al,Not 3
Out 61h,Al
Pop Ds
Pop Dx
Pop Ax
Ret
After Endp
Play Proc Near ; Actually plays the buffer. (DS:SI)
Loop003: Lodsw
Or Ax,Ax
Jz Terminal
Mov Cx,Ax
Lodsw
Or Ax,Ax
Jz Terminal
Mov Dx,Ax
Call Sound
Mov Ticks18,0
Loop004: Cmp Ticks18,Speed
Jb Loop004
Jmp Loop003
Terminal:
Ret
Play Endp
Program Proc Near
Call Before
Mov Si,Offset Channel1
Mov Dx,Offset Channel2
Mov Di,Offset WorkSpace
Call MakeTAB
Mov Si,Offset WorkSpace
Call Play
Call After
Mov Ax,4c00h
Int 21h
Program Endp
Channel1 Db 22,17,24,17,25,17,24,17,22,17,27,17,25,17,24,17,22,17,24,17,25,17
Db 27,17,29,17,27,17,25,17,24,17
Db 22,17,24,17,25,17,24,17,22,17,27,17,25,17,24,17,21,17,22,17,24,17,25,17
Db 27,17,29,17,25,17,24,17
Db 22,22,24,24,25,25,24,24,22,22,27,27,25,25,24,24,22,22,24,24,25,25
Db 27,27,29,29,27,27,25,25,24,24
Db 22,22,24,24,25,25,24,24,22,22,27,27,25,25,24,24,21,21,22,22,24,24,25,25
Db 27,27,29,29,25,25,24,24
Db 24,19,26,19,27,19,26,19,24,19,29,19,27,19,26,19,24,19,26,19,27,19
Db 29,19,31,19,29,19,27,19,26,19
Db 24,19,26,19,27,19,26,19,24,19,29,19,27,19,26,19,23,19,24,19,26,19,27,19
Db 29,19,31,19,27,19,26,19,-1
Channel2 Db 16 dup (10),16 dup(8),16 dup(6),16 dup (5),
Db 8 dup (10,17),8 dup (8,15),8 dup (6,13), 8 dup (5,12)
Db 8 dup (12,19),8 dup (10,17),8 dup (8,15), 8 dup (7,14),-1
WorkSpace Db 'WorkSpace'
Code Ends
End Start