' Wav Player by: Tom Ford (TF Software) ' Email: TFSoft@aol.com ' ' Note: The original DMA functions were written by Mike Huff ' ' I have just modified his work to now play .WAV files of any length. ' This may also be able to play .VOC's or any other sound file, but ' I have not tried it so don't get mad if it doesn't. ' ' DO NOT RUN THIS PROGRAM YET!!! ' First scroll down and type in the path of the .WAV you want to play. ' You may listen to the sample .WAV I have included or you can listen to ' a different one, but it has to be Mono, 8bit. ' ' Another note: Some sound cards can't play .WAV's over 22050 with ' these functions. (Including mine) ' ' DECLARE SUB PlayLngFile (WavFileName$, WavFreq&) DECLARE SUB PlayFile (WavFileName$, WavFreq&) DECLARE FUNCTION FileLength& (WavFileName$) DECLARE FUNCTION DMADone% () DECLARE FUNCTION ResetDSP% () DECLARE SUB MasterVolume (Right%, Left%, Getvol%) DECLARE SUB WriteDSP (byte%) DECLARE FUNCTION ReadDSP% () DECLARE SUB SpeakerState (OnOff%) DECLARE SUB DMAPlay (Segment&, Offset&, Length&, Freq&) DECLARE FUNCTION GetBLASTER% (DMA%, BasePort%, IRQ%) DECLARE FUNCTION DSPVersion! () '-----COMMONs----- COMMON SHARED PlaySndFlag%, WavFlag% COMMON SHARED BasePort%, LenPort%, Channel%, IRQ%, HaveBlast%, WavRep%, TheWavLen& COMMON SHARED TFWav() AS STRING * 32767 '-----End COMMONs----- ON ERROR GOTO EHandler CLS '$DYNAMIC DIM SHARED TFWav(1) AS STRING * 32767 'This detects the SB and does some other initializations: HaveBlast% = GetBLASTER(Channel%, BasePort%, IRQ%)' Parses BLASTER environment IF HaveBlast% THEN PlaySndFlag% = 1 ELSE PlaySndFlag% = 0 ResetIt% = ResetDSP% SpeakerState 1 'turn the speaker on MasterVolume 15, 15, 0 'this cranks the master volume all the way up. 'End initialization stuff here WavName$ = "d:\mp1\bomb.wav" '<-- Type in the path of the wav here Freq& = 11025 '<-- Type in the frequency here WavFlag% = 2 '<-- Set WavFlag to 2 when playing .WAV's over 32K '**Idea: If you don't want to set the .WAV flag ' everytime just make a sub routine that will ' do it.** PlayLngFile WavName$, Freq& 'Play the file! (This just starts it, the loop 'below is what finishes it) 'PlayFile WavName$, Freq& 'You can do this to play 32K (good for small wavs) ' Another Idea: If you don't want to check for DMADone, and WavFlag ' everytime, then make a function that will! This is ' just how I like to do it. DO IF DMADone% <> 0 AND WavFlag% < 5 THEN PlayLngFile WavName$, Freq& COLOR INT(RND * 16) PRINT "Playing sound in background! Yeehaw!" LOOP UNTIL DMADone% <> 0 AND WavFlag% >= 5 COLOR 15 PRINT "Finished!" END EHandler: COLOR 15 Er% = ERR PRINT "Something bad happened!" PRINT "Error code: "; Er% END RESUME REM $STATIC FUNCTION DMADone% Count% = INP(LenPort%) Count2% = INP(LenPort%) Count& = CLNG(Count% + 1) * CLNG(Count2% + 1) IF (Count& - 1) >= &HFFFF& THEN junk% = INP(DSPDataAvail%): DMADone% = -1 END FUNCTION SUB DMAPlay (Segment&, Offset&, Length&, Freq&) ' Transfers and plays the contents of the buffer. IF PlaySndFlag% = 0 THEN EXIT SUB Length& = Length& - 1 Page% = 0 MemLoc& = Segment& * 16 + Offset& SELECT CASE Channel% CASE 0 PgPort% = &H87 AddPort% = &H0 LenPort% = &H1 ModeReg% = &H48 CASE 1 PgPort% = &H83 AddPort% = &H2 LenPort% = &H3 ModeReg% = &H49 CASE 2 PgPort% = &H81 AddPort% = &H4 LenPort% = &H5 ModeReg% = &H4A CASE 3 PgPort% = &H82 AddPort% = &H6 LenPort% = &H7 ModeReg% = &H4B CASE ELSE EXIT SUB END SELECT OUT &HA, &H4 + Channel% OUT &HC, &H0 OUT &HB, ModeReg% OUT AddPort%, MemLoc& AND &HFF OUT AddPort%, (MemLoc& AND &HFFFF&) \ &H100 IF (MemLoc& AND 65536) THEN Page% = Page% + 1 IF (MemLoc& AND 131072) THEN Page% = Page% + 2 IF (MemLoc& AND 262144) THEN Page% = Page% + 4 IF (MemLoc& AND 524288) THEN Page% = Page% + 8 OUT PgPort%, Page% OUT LenPort%, Length& AND &HFF OUT LenPort%, (Length& AND &HFFFF&) \ &H100 OUT &HA, Channel% IF Freq& < 23000 THEN TimeConst% = 256 - 1000000 \ Freq& WriteDSP &H40 WriteDSP TimeConst% WriteDSP &H14 WriteDSP (Length& AND &HFF) WriteDSP ((Length& AND &HFFFF&) \ &H100) ELSE IF DSPVersion! >= 3 THEN TimeConst% = ((65536 - 256000000 \ Freq&) AND &HFFFF&) \ &H100 WriteDSP &H40 WriteDSP TimeConst% WriteDSP (Length& AND &HFF) WriteDSP ((Length& AND &HFFFF&) \ &H100) WriteDSP &H91 ELSE PRINT "You need a Sound Blaster with a DSP v3.x+ to play at high speed." EXIT SUB END IF END IF END SUB SUB DoSNDEvent (SNDNum%) SELECT CASE SNDNum% CASE 1 END SELECT END SUB FUNCTION DSPVersion! ' Gets the DSP version. WriteDSP &HE1 Temp% = ReadDSP% Temp2% = ReadDSP% DSPVersion! = VAL(STR$(Temp%) + "." + STR$(Temp2%)) END FUNCTION FUNCTION FileLength& (WavFileName$) OPEN WavFileName$ FOR BINARY AS #1 TotWavLength& = LOF(1) - 44 ResWavLength& = TotWavLength& - (32767& * WavRep%) - 44 IF ResWavLength& > 32767& THEN ResWavLength& = 32767& CLOSE #1 IF ResWavLength& = 0 THEN KILL ResWavFileName$ FileLength& = ResWavLength& END FUNCTION FUNCTION GetBLASTER% (DMA%, BasePort%, IRQ%) ' This subroutine parses the BLASTER environment string and returns settings. IF LEN(ENVIRON$("BLASTER")) = 0 THEN GetBLASTER% = 0: EXIT FUNCTION FOR Length% = 1 TO LEN(ENVIRON$("BLASTER")) SELECT CASE MID$(ENVIRON$("BLASTER"), Length%, 1) CASE "A" BasePort% = VAL("&H" + MID$(ENVIRON$("BLASTER"), Length% + 1, 3)) CASE "I" IRQ% = VAL(MID$(ENVIRON$("BLASTER"), Length% + 1, 1)) CASE "D" DMA% = VAL(MID$(ENVIRON$("BLASTER"), Length% + 1, 1)) END SELECT NEXT GetBLASTER% = 1 END FUNCTION SUB MakeWav WavLen1& = FileLength("tfwav1.wav") WavLen1& = WavLen1& + 44 OPEN "tfwav1.wav" FOR BINARY AS #1 GET #1, 0, TFWav(1) 'Get 32k from file (skip header on WAV) CLOSE #1 OPEN "tfall.wav" FOR BINARY AS #1 PUT #1, 0, TFWav(1) CLOSE #1 END SUB SUB MasterVolume (Right%, Left%, Getvol%) OUT BasePort% + 4, &H22 'PRINT BasePort% IF Getvol% THEN Left% = INP(BasePort% + 5) \ 16 Right% = INP(BasePort% + 5) AND &HF EXIT SUB ELSE OUT BasePort% + 5, (Right% + Left% * 16) AND &HFF END IF END SUB SUB PlayFile (WavFileName$, WavFreq&) WavRep% = 0 WavFlag% = 1 TheWavLen& = FileLength(WavFileName$) OPEN WavFileName$ FOR BINARY AS #1 GET #1, 44, TFWav(1) 'Get 32k from file (skip header on WAV) CLOSE #1 'TheWavLen& = TheWavLen& - 44 DMAPlay VARSEG(TFWav(1)), VARPTR(TFWav(1)), TheWavLen&, WavFreq& END SUB SUB PlayLngFile (WavFileName$, WavFreq&) IF WavRep% > 0 THEN DMAPlay VARSEG(TFWav(1)), VARPTR(TFWav(1)), TheWavLen&, WavFreq& IF WavFlag% = 2 THEN WavRep% = 0: WavFlag% = 3 TheWavLen& = FileLength(WavFileName$) OPEN WavFileName$ FOR BINARY AS #1 IF WavRep% = 0 THEN GET #1, 44, TFWav(1) DMAPlay VARSEG(TFWav(1)), VARPTR(TFWav(1)), TheWavLen&, WavFreq& WavRep% = WavRep% + 1 END IF GET #1, (32767& * WavRep%), TFWav(1) IF WavFlag% = 4 THEN WavFlag% = 5: CLOSE #1: EXIT SUB WavRep% = WavRep% + 1 IF TheWavLen& < (32766&) THEN WavFlag% = 4 CLOSE #1 END SUB FUNCTION ReadDSP% ' Reads a byte from the DSP DO LOOP UNTIL INP(BasePort% + 14) AND &H80 ReadDSP% = INP(BasePort% + 10) END FUNCTION FUNCTION ResetDSP% ' Resets the DSP OUT BasePort% + 6, 1 FOR Count% = 1 TO 4 junk% = INP(BasePort% + 6) NEXT OUT BasePort% + 6, 0 IF INP(BasePort% + 14) AND &H80 = &H80 AND INP(BasePort% + 10) = &HAA THEN ResetDSP% = -1 ELSE ResetDSP% = 0 END IF END FUNCTION SUB SpeakerState (OnOff%) ' Turns speaker on or off. IF OnOff% THEN WriteDSP &HD1 ELSE WriteDSP &HD3 END SUB SUB WriteDSP (byte%) ' Writes a byte to the DSP DO LOOP WHILE INP(BasePort% + 12) AND &H80 OUT BasePort% + 12, byte% END SUB