#include <api_mmsys.sbp> Declare Function waveOutOpen Lib "winmm" (phwo As *HWAVEOUT, uDeviceID As DWord, pwfx As *WAVEFORMATEX, dwCallback As DWord, dwInstance As DWord, fdwOpen As DWord) As MMRESULT Declare Function waveOutClose Lib "winmm" (hwo As HWAVEOUT) As MMRESULT Declare Function waveOutPrepareHeader Lib "winmm" (hwo As HWAVEOUT, pwh As *WAVEHDR, cbwh As DWord) As MMRESULT Declare Function waveOutUnprepareHeader Lib "winmm" (hwo As HWAVEOUT, pwh As *WAVEHDR, cbwh As DWord) As MMRESULT Declare Function waveOutWrite Lib "winmm" (hwo As HWAVEOUT, pwh As *WAVEHDR, cbwh As DWord) As MMRESULT Declare Function waveOutPause Lib "winmm" (hwo As HWAVEOUT) As MMRESULT Declare Function waveOutRestart Lib "winmm" (hwo As HWAVEOUT) As MMRESULT Declare Function waveOutReset Lib "winmm" (hwo As HWAVEOUT) As MMRESULT Declare Function waveOutGetPosition Lib "winmm" (hwo As HWAVEOUT, pmmt As *MMTIME, cbmmt As DWord) As MMRESULT Declare Function MulDiv Lib "kernel32" (nNumber As Long, nNumerator As Long, nDenominator As Long) As Long
TypeDef MMRESULT = DWord Typedef HWAVEOUT = VoidPtr Type WAVEHDR lpData As *Byte dwBufferLength As DWord dwBytesRecorded As DWord dwUser As DWord dwFlags As DWord dwLoops As DWord lpNext As *WAVEHDR reserved As *DWord End Type Type MMTIME wType As DWord u As DWord u2 As DWord End Type
Class WavePlayer Private buffer[2] As *Byte hwo As HWAVEOUT wfe As WAVEFORMATEX hF As HANDLE switch As Long
Function GetWavHeader() As Long Dim head[3] As Byte Dim r As DWord ReadFile(hF, head, 4, VarPtr(r), ByVal 0) If (memcmp(head, "RIFF", 4)) Then Exit Function ReadFile(hF, head, 4, VarPtr(r), ByVal 0)'ファイルサイズ ReadFile(hF, head, 4, VarPtr(r), ByVal 0) If (memcmp(head, "WAVE", 4)) Then Exit Function ReadFile(hF, head, 4, VarPtr(r), ByVal 0) If (memcmp(head, "fmt ", 4)) Then Exit Function ReadFile(hF, head, 4, VarPtr(r), ByVal 0) ReadFile(hF, VarPtr(wfe), Sizeof(WAVEFORMATEX), VarPtr(r), ByVal 0) If r <> SizeOf(WAVEFORMATEX) Then Exit Function ReadFile(hF, head, 2, VarPtr(r), ByVal 0)'"ta" ReadFile(hF, head, 4, VarPtr(r), ByVal 0)'データサイズ GetWavHeader = 1 End Function
Sub waveOutProc(hwo As HWAVEOUT, uMsg As DWord, dwInstance As *DWord, dwParam1 As DWord, dwParam2 As DWord) Dim x As *WavePlayer x = dwInstance Select Case uMsg Case WOM_CLOSE Case WOM_DONE x->wh[1].dwUser = x->wh[1].dwUser - 1 If x->wh[0].dwUser = 0 Then x->read(hwo) Case WOM_OPEN End Select End Sub
Public wh[2] As WAVEHDR Sub read(hwo As HWAVEOUT) Dim r As DWord
If hwo = NULL Or wh[0].dwUser = 1 Or wh[1].dwUser > 1 Then Exit Sub waveOutUnprepareHeader(hwo, VarPtr(wh[switch]), SizeOf(WAVEHDR)) ReadFile(hF, buffer[switch], wfe.nAvgBytesPerSec, VarPtr(r), ByVal 0) wh[switch].lpData = buffer[switch] wh[switch].dwBufferLength = r If r = 0 Then wh[0].dwUser = 1'これ以上再生しません waveOutPrepareHeader(hwo, VarPtr(wh[switch]), SizeOf(WAVEHDR)) waveOutWrite(hwo, VarPtr(wh[switch]), SizeOf(WAVEHDR)) wh[1].dwUser = wh[1].dwUser + 1 switch = switch + 1 If switch = 2 Then switch = 0 End Sub
Function play(infile As *Byte) As Long If hwo <> NULL Then Exit Function hF = CreateFile(infile, GENERIC_READ, 0, ByVal 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) If hF = INVALID_HANDLE_VALUE Then Exit Function If GetWavHeader() = 0 Then CloseHandle(hF) Exit Function End If buffer[0] = malloc(wfe.nAvgBytesPerSec) buffer[1] = malloc(wfe.nAvgBytesPerSec) waveOutOpen( VarPtr(hwo), WAVE_MAPPER, VarPtr(wfe), AddressOf(waveOutProc) ,VarPtr(this), CALLBACK_FUNCTION) read(hwo) Sleep(500) read(hwo) play = 1 End Function
Sub stop() As Long If hwo = NULL Then Exit Sub wh[0].dwUser = 1 waveOutReset(hwo) While wh[1].dwUser > 0 Sleep(1) Wend waveOutUnprepareHeader(hwo, VarPtr(wh[0]), SizeOf(WAVEHDR)) waveOutUnprepareHeader(hwo, VarPtr(wh[0]), SizeOf(WAVEHDR)) free(buffer[0]) free(buffer[1])
waveOutClose(hwo) CloseHandle(hF) hwo = NULL End Sub
Function state(t As *DWord) As Long state = wh[1].dwUser If t = NULL Then Exit Function Dim mmt As MMTIME mmt.wType = TIME_SAMPLES waveOutGetPosition(hwo, VarPtr(mmt), SizeOf(MMTIME)) SetDWord(t,MulDiv(mmt.u , 1000, wfe.nSamplesPerSec)) End Function End Class
#define SELFTEST #ifdef SELFTEST #N88BASIC Dim wp As WavePlayer Dim time As DWord Print "再生" wp.play("test.wav") While wp.state(VarPtr(time)) Locate 4,1 Print time\1000;"sec" Sleep(1000) Wend wp.stop() Print "停止" #endif