Converting VB to PB (SPC Player)

Just starting out? Need help? Post your questions and find answers here.
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Converting VB to PB (SPC Player)

Post by moogle »

Alright all I need is someone who can help me convert this VB code to PB. Can anyone help? or say something i can understand?

Code: Select all

'===================================================================================================
' Wave Device Output                                         Copyright (C)2004 Alpha-II Productions
'===================================================================================================

'---------------------------------------------------------------------------------------------------
'MMSYSTEM.H Imports
'
'Visit MSDN for information on the Windows multi-media library:
'
'http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveform_audio_reference.asp

Const WAVE_FORMAT_PCM As Long = 1&
Const WAVE_MAPPER As Long = -1&
Const WAVE_ALLOWSYNC As Long = &H2
Const WOM_DONE As Long = &H3BD

Const MMSYSERR_NOERROR = 0

Const CALLBACK_FUNCTION = &H30000


Type WAVEFORMATEX                               'Wave format chunk
        wFormatTag As Integer                   'http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveformatex_str.asp
        nChannels As Integer
        nSamplesPerSec As Long
        nAvgBytesPerSec As Long
        nBlockAlign As Integer
        wBitsPerSample As Integer
        cbSize As Integer
End Type

Type WAVEHDR                                    'Output buffer header
        lpData As Long                          'http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_wavehdr_str.asp
        dwBufferLength As Long
        dwBytesRecorded As Long
        dwUser As Long
        dwFlags As Long
        dwLoops As Long
        lpNext As Long
        reserved As Long
End Type

Declare Function waveOutOpen Lib "winmm.dll" (lphWaveOut As Long, ByVal uDeviceID As Long, lpFormat As WAVEFORMATEX, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Declare Function waveOutReset Lib "winmm.dll" (ByVal hWaveOut As Long) As Long
Declare Function waveOutClose Lib "winmm.dll" (ByVal hWaveOut As Long) As Long
Declare Function waveOutWrite Lib "winmm.dll" (ByVal hWaveOut As Long, lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long
Declare Function waveOutPrepareHeader Lib "winmm.dll" (ByVal hWaveOut As Long, lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long
Declare Function waveOutUnprepareHeader Lib "winmm.dll" (ByVal hWaveOut As Long, lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long


'===================================================================================================
' Global Data

Private Const SAMPLE_RATE As Long = 32000       'Output sample rate is 32kHz (SNESAPU default)
Private Const BUFSIZE As Long = 3200            '((100 * SAMPLE_RATE) / 1000) = 100ms at 32kHz

Private Handle As Long                          'Handle to output device
Private Ready As Boolean                        'Output device is ready for data
Private Fmt As WAVEFORMATEX                     'Output format
Private Hdr(1) As WAVEHDR                       'Headers for output buffers
Private Buffer(BUFSIZE - 1, 1) As Long          'Raw PCM output buffers (16-bit stereo)

'Wave Out Callback
'
'Event handler called by Windows when the output device needs attention
'
'In:
'   hwo        = Handle to output device
'   uMsg       = Message being sent
'   dwInstance = User defined data (not used in here)
'   pWHdr     -> Current wave header (if applicable)
'   dwParam2   = not used

Private Sub WaveOutDone(ByVal hwo As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef pWHdr As WAVEHDR, ByVal dwParam2 As Long)
    If (uMsg = WOM_DONE) And (Ready = True) Then            'We only care if a buffer is through playing and we're ready for data
        EmuAPU pWHdr.lpData, pWHdr.dwBufferLength / 4, True 'Emulate SNES APU
        waveOutWrite hwo&, pWHdr, Len(pWHdr)                'Send PCM data to output device
    End If
End Sub

'Initialize format chunk for sending audio data to the output device

Public Sub WavInit()
    Fmt.wFormatTag = WAVE_FORMAT_PCM
    Fmt.nChannels = 2
    Fmt.nSamplesPerSec = SAMPLE_RATE
    Fmt.nAvgBytesPerSec = 2 * (16 / 8) * SAMPLE_RATE
    Fmt.nBlockAlign = 2 * (16 / 8)
    Fmt.wBitsPerSample = 16
    Fmt.cbSize = 0
End Sub

'Close the output device if it's still open

Public Sub WavQuit()
    WavClose
End Sub

'Open the output device, prepare the buffers, load the .spc file, and begin sending audio

Public Function WavOpen(file() As Byte) As Boolean
Dim error As Long

    If Ready Then
        WavOpen = True
        Exit Function
    End If
    
    'Open audio device
    error = waveOutOpen(Handle, -1, Fmt, AddressOf WaveOutDone, 0, WAVE_ALLOWSYNC Or CALLBACK_FUNCTION)

    If error = MMSYSERR_NOERROR Then
        Ready = True

        'Initialize buffers
        Hdr(0).dwBufferLength = BUFSIZE * 4
        Hdr(0).lpData = VarPtr(Buffer(0, 0))
        waveOutPrepareHeader Handle, Hdr(0), Len(Hdr(0))

        Hdr(1).dwBufferLength = BUFSIZE * 4
        Hdr(1).lpData = VarPtr(Buffer(0, 1))
        waveOutPrepareHeader Handle, Hdr(1), Len(Hdr(1))

        'Load .spc file into emulator
        LoadSPCFile file(0)
        
        'Manually send empty buffer messages to begin output
        WaveOutDone Handle, WOM_DONE, 0, Hdr(0), 0
        WaveOutDone Handle, WOM_DONE, 0, Hdr(1), 0
    Else
        Ready = False
        MsgBox "Error opening audio device"
    End If
    
    WavOpen = Ready
End Function

'Close the output device and release the buffer headers

Public Sub WavClose()
    If Ready Then
        Ready = False
        
        waveOutReset Handle                 'Tell Windows to reset the output device
        waveOutUnprepareHeader Handle, Hdr(0), Len(Hdr(0))
        waveOutUnprepareHeader Handle, Hdr(1), Len(Hdr(1))
        waveOutClose Handle                 'Close output device
        
        Handle = 0
    End If
End Sub

Last edited by moogle on Sat Mar 04, 2006 8:01 pm, edited 2 times in total.
Image
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

structure or interface already declared:waveHdr
As the compiler said, this structure is a builtin structure so it's already defined.
Simply delete those lines (wavehdr lines) and it'll work :wink:
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Post by moogle »

really? yippeeeee! but what about the procedures. i put the some of the parameters as types. will it work?

heres the procedures

Code: Select all

; ProcedureDLL.l waveOutClose(hWaveOut.l)
;   ProcedureReturn CallFunctionFast(waveOutClose,hWaveOut)
; EndProcedure
;
; ProcedureDLL.l waveOutOpen(lphWaveOut.l,uDeviceID.l,lpFormat\WAVEFORMATEX,dwCallback.l,dwInstance.l,dwFlags.l)
;   ProcedureReturn CallFunctionFast(waveOutOpen,lphWaveOut,uDeviceID,lpFormat,dwCallback,dwInstance,dwFlags)
; EndProcedure
;
; ProcedureDLL.l waveOutPrepareHeader(hWaveOut.l,lpWaveOutHdr\WAVEHDR,uSize.l)
;   ProcedureReturn CallFunctionFast(waveOutPrepareHeader,hWaveOut,lpWaveOutHdr,uSize)
; EndProcedure
;
; ProcedureDLL.l waveOutReset(hWaveOut.l)
;   ProcedureReturn CallFunctionFast(waveOutReset,hWaveOut)
; EndProcedure
;
; ProcedureDLL.l waveOutUnprepareHeader(hWaveOut.l,lpWaveOutHdr\WAVEHDR,uSize.l)
;   ProcedureReturn CallFunctionFast(waveOutUnprepareHeader,hWaveOut,lpWaveOutHdr,uSize)
; EndProcedure
;
; ProcedureDLL.l waveOutWrite(hWaveOut.l,lpWaveOutHdr\WAVEHDR,uSize.l)
;   ProcedureReturn CallFunctionFast(waveOutWrite,hWaveOut,lpWaveOutHdr,uSize)
; EndProcedure
;
But thanks alot for help!

EDIT: Ie this procedure.

Code: Select all

ProcedureDLL.l waveOutOpen(lphWaveOut.l,uDeviceID.l,lpFormat\WAVEFORMATEX,dwCallback.l,dwInstance.l,dwFlags.l)
  ProcedureReturn CallFunctionFast(waveOutOpen,lphWaveOut,uDeviceID,lpFormat,dwCallback,dwInstance,dwFlags)
EndProcedure
Gives me the error: This variable doesn't have a 'Structure'
What is causing this and how to fix this.
Image
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post by Flype »

ProcedureDLL.l waveOutOpen(lphWaveOut.l,uDeviceID.l,lpFormat\WAVEFORMATEX,dwCallback.l,dwInstance.l,dwFlags.l)
ProcedureReturn CallFunctionFast(waveOutOpen,lphWaveOut,uDeviceID,lpFormat,dwCallback,dwInstance,dwFlags)
EndProcedure
with PB4:

Code: Select all

ImportC "winmm.lib"
  waveOutOpen(*phwo,uDeviceID.l,*pwfx,*dwCallback,dwCallbackInstance.l,fdwOpen.l)
EndImport
http://msdn.microsoft.com/library/defau ... utopen.asp
lpFormat\WAVEFORMATEX
here the function need a pointer to the structure, so you have to specify *pwfx.WAVEFORMATEX,
but as pointer is pointer ( always a LONG value ) let it to *pwfx.

And then when calling the function you have to pass the structure this way:

Code: Select all

Procedure waveOutProc(hwo,uMsg,dwInstance,dwParam1,dwParam2)
EndProcedure

pwfx.WAVEFORMATEX

waveOutOpen(phwo,1,@pwfx,@waveOutProc(),0,0)
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Post by moogle »

Im sorry im a newbie to PB but im learning :oops:
Im unsure how to implement this. DId you download the file i put in my post and look at wave.bas file in the visual basic examples folder?

How would i start converting? and which part of my code is right?

EDIT: BTw im using pb 3.94.
Image
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Post by inc. »

Imho all the Winmm.lib commands are natively integrated in PB as supported API calls and IIRC the WAVEFORMATEX structure also,

From the API functions listing in the PB compilers directory:
...
...
waveOutBreakLoop (hwo)
waveOutClose (hwo)
waveOutGetDevCaps (uDeviceID, pwoc, cbwoc)
waveOutGetErrorText (mmrError, pszText, cchText)
waveOutGetID (hwo, puDeviceID)
waveOutGetNumDevs ()
waveOutGetPitch (hwo, pdwPitch)
waveOutGetPlaybackRate (hwo, pdwRate)
waveOutGetPosition (hwo, pmmt, cbmmt)
waveOutGetVolume (hwo, pdwVolume)
waveOutMessage (hwo, uMsg, dw1, dw2)
waveOutOpen (phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen)
waveOutPause (hwo)
waveOutPrepareHeader (hwo, pwh, cbwh)
waveOutReset (hwo)
waveOutRestart (hwo)
waveOutSetPitch (hwo, dwPitch)
waveOutSetPlaybackRate (hwo, dwRate)
waveOutSetVolume (hwo, dwVolume)
waveOutUnprepareHeader (hwo, pwh, cbwh)
waveOutWrite (hwo, pwh, cbwh)
...
...
Also if playing back audio from larger files (or even in general) you shouldn't use an "all in one" playback buffersize of the whole given audiodatasize. The goal is to use several buffers where these will be refilled continously during audio data playback. Do use i.e. 4 Buffers using a size of i.e. 4096bytes each IIRC.

So like Flype mentioned but adding a condition where it will recognised IF the buffer(x) has been played back ...

Code: Select all

waveOutOpen(phwo,1,@pwfx,@waveOutProc(),0,0)



Procedure waveOutProc(hwo,uMsg,dwInstance,dwParam1,dwParam2)
...
..
.
If uMsg = #WOM_DONE ; <-- The buffer(x) has been processed
  RefillBuffersProcedure() 
Endif
.
..
...
EndProcedure
My recommendation: Do look in the MSDN SDK for the "AviEdit" example in the SDK codesamples. Its C but you will se how the approach works.

I used that piece of code for my AviFil_ext Userlibrary for Avi Audioplayback support. Do look in the forum in here IIRC I also did include the source in the package.
moogle
Enthusiast
Enthusiast
Posts: 372
Joined: Tue Feb 14, 2006 9:27 pm
Location: London, UK

Post by moogle »

all i want to do is convert the code from the vb to pb, just to not complicate things. using 4 buffers might be a good idea for larger files. but since this an spc which is only and always 64.5kb ill not bother for now. i just want to get it working. i am a newbie after all so all this language is confusing to me. :oops:
Image
Post Reply