Hello. Actually, this example doesn't work and I'm looking for any help.
My purpose is reproducing a file wav through the speaker. The original information comes from Phil Inch in his Game Developers Magazine. As I think, the file wav only has bytes with amplitudes of the sound wave and, since the speaker takes 60 microseconds to attain its maximum distension, only we should use a maximum value of 72. The trick consists in to turn on and to turn off the speaker before its cone has reached its maximum possible extension in order to simulate different amplitudes to standard square wave. We have to reprogram PIT channel 0 to achieve it.
Phil's program doesn't work in my PC, simply it doesn't emit any sound. To begin with, Phil sends the code 90h to the PIT command register, i.e. produce an interruption ( 8h ) when finishing the count. It pretends halt the processor, with a HLT, until the interruption takes place (speaker cone is increasing meanwhile). After that, we repeat the same operation with another byte from the wav file. I need to put a 96h command to generate a square wave in order to emit a sound from the speaker. Besides, I don't like stopping system until generating an interruption, I prefer to use a variable to be changed in the Int 08h that I will intercept. In theory, the mechanism is the same.
I present a shortened version of my program in order to be simpler to revise and anderstand. I want to reproduce something like it should be. The duration of the notes could become regulated manually with the constant cOversamp. I believe that the main problem is in the "Sound" routine and how interpreting the byte that we will send to the speaker. In theory this byte should not surpass 72. I have tried several possibilities and no one emits a similar sound it should go out to.
Can anybody help me, please?
; ----------------------------------------------------------------------------
; - TITLE : Plays wav files through the speaker COM-NASM -
; ----- -----
; - AUTHOR : Alfonso Víctor Caballero Hurtado -
; - http://www.abreojosensamblador.net/ -
; ----- -----
; - VERSION : 1.0 -
; ----- -----
; - COMMENT : Based on Phil Inch, Game Developers Magazine -
; ----------------------------------------------------------------------------
cOversamp EQU 52000 ; Oversampling (perhaps we should modify it)
[org 100h]
[section .text]
CALL SaveValSPK
CALL OpenFile
CALL ReadHead
CALL PlayWav
CALL WrtMsg
; Salimos al DOS
MOV AX, 4C00h
INT 21h
SaveValSPK:
; Purpose : Save 61h port original value
; In : None
; Out : vbSpeaker
; Destroys : AX
IN AL, 61h
AND AL, 11111100b
MOV BYTE [vbSpeaker], AL
RET
OpenFile:
; Purpose : Open wav file
; In : None
; Out : HandleEntrada
; Destroys : AX, DX
MOV AX, 3D00h ; Open for reading
MOV DX, SourceFile ; DS:DX ASCIIZ filepathname
INT 21h
MOV WORD [Handle], AX ; We don't check fails
RET
ReadFile:
; Purpose : Extract bytes from file to DS:DX
; In : CX: number of bytes to read, DX: offset
; Out : Readed bytes in some buffer, AX number of bytes actually read
; Destroys : AX, BX
MOV AH, 3Fh ; Función leer fichero
MOV BX, WORD [Handle]
INT 21h ; We don't check fails
RET
ReadHead:
; Purpose : Extract wav head from file to MWavCab
; In : None
; Out : MWavCab
; Destroys : CX, DX
MOV CX, LTWavCab
MOV DX, MWavCab
CALL ReadFile
RET
SetCanal2:
; Purpose : Program channel 2 from PIT
; In : None
; Out : None
; Destroys : AX
; MOV AL, 90h ; 90h = 10010000b. 10-canal2,01-byte bajo (Phil)
; ; 000-Mode0 Int at the end
MOV AL, 96h ; 96h = 10010110b. 10-canal2,01-byte bajo (Mine)
; 011-Square wave
OUT 43h, AL
MOV AL, BYTE [vbSpeaker]
OR AL, 3 ; Conectamos el canal 2 al altavoz
OUT 61h, AL ; Lo hacemos
RET
SpkOn:
; Purpose : Turns on the speaker
; In : None
; Out : None
; Destroys : AX
MOV AL, BYTE [vbSpeaker]
OR AL, 3
OUT 61h, AL
RET
SpkOff:
; Purpose : Turns off the speaker
; In : None
; Out : None
; Destroys : AX
MOV AL, BYTE [vbSpeaker]
AND AL, 11111101b
OUT 61h, AL
RET
; Here resides the problem, I believe. That is, how treating the byte that we receive
; Sound:
; ; Purpose : Plays a note on the speaker using the PIT
; ; method1: we play it if positive, else turn off the speaker
; ; In : AL: byte from wav file
; ; Out : None
; ; Destroys : AX, CX
; OR AL, AL
; JL L_SD_Apagar
; CALL SpkOn
; JMP L_SD_Fin
; L_SD_Apagar:
; CALL SpkOff
; L_SD_Fin:
; MOV CX, cOversamp
; LOOP $
; RET
; Sound:
; ; Purpose : Plays a note on the speaker using the PIT
; ; method2: we play it if positive, else turn off the speaker (max 72)
; ; In : AL: byte from wav file
; ; Out : None
; ; Destroys : AX, CX
; OR AL, AL
; JL L_SD_Apagar
; CMP AL, 72
; JB L_SD_Next1
; MOV AL, 72
; L_SD_Next1:
; CALL SpkOn
; JMP L_SD_Fin
; L_SD_Apagar:
; NEG AL
; CMP AL, 72
; JB L_SD_Next2
; MOV AL, 72
; L_SD_Next2:
; CALL SpkOff
; L_SD_Fin:
; MOV CX, cOversamp
; LOOP $
; RET
Sound:
; Purpose : Plays a note on the speaker using the PIT
; method3: we play 72*AL/256 (max 72)
; In : AL: byte from wav file
; Out : None
; Destroys : AX, CX
MUL BYTE [SeventyTwo]
XCHG AL, AH
CALL SpkOn
MOV CX, cOversamp
LOOP $
CALL SpkOff
RET
PlayWav:
; Purpose : Plays wav file through the speaker
; In : None
; Out : MWavCab
; Destroys : CX, DX
; Calculate counter
MOV DX, 12h
MOV AX, 34DCh
DIV WORD [MWavCab+SampRat] ; Dividimos por la tasa de muestreo
MOV WORD [Contador], AX
CALL SetCanal2 ; Programamos el canal 2
L_PW_Bucle:
MOV CX, 1 ; One byte
MOV DX, vbTmp
CALL ReadFile
OR AX, AX
JZ L_PW_Fin
MOV AL, BYTE [vbTmp]
CALL Sound
MOV AH, 1
INT 16h
JZ L_PW_Bucle
MOV AH, 0
INT 16h
L_PW_Fin:
RET
WrtMsg:
; Purpose : Write final message onto the screen
; In : None
; Out : None
; Destroys : AX, DX
; Calculate counter
MOV DX, msg
MOV AH, 9
INT 21h
RET
[section .bss]
STRUC TWavCab
; Trozo Riff - 12 bytes
Riff: RESB 4 ; 0 - 3 "RIFF"
RLen: RESD 1 ; 4 - 7 total size
Wave: RESB 4 ; 8 - 11 "WAVE"
; Trozo Formato - 24 bytes
Fmt: RESB 4 ; 0 - 3 "fmt "
FLen: RESD 1 ; 4 - 7 Format chunk size
Uno: RESW 1 ; 8 - 9 Always 1
Canal: RESW 1 ; 10 - 11 Number of channels
SampRat: RESD 1 ; 12 - 15 Sample rate
BxSec: RESD 1 ; 16 - 19 Bytes per second
BxSamp: RESW 1 ; 20 - 21 Bytes per sample
BixSam: RESW 1 ; 22 - 23 Bits per sample
; Trozo de Datos - 8 bytes
Datos: RESB 4 ; 0 - 3 "data"
DLen: RESD 1 ; 4 - 7 Following data chunk size
ENDSTRUC
LTWavCab EQU TWavCab_size
[section .data]
SourceFile DB "zAryx2.wav", 0
msg DB "That's all folks!$"
SeventyTwo DB 72
MWavCab:
ISTRUC TWavCab
IEND
[section .bss]
Handle RESW 1
Contador RESW 1
vbSpeaker RESB 1
vbTmp RESB 1
vwCont RESW 1
You won't believe it, but I couldn't find the way to upload the entire zip...