Callback Functions in VB.NET

mikepayne

Member
Joined
Dec 22, 2005
Messages
6
Programming Experience
5-10
Hello everyone. I'm trying to implement a callback function for processing digital audio input in VB.NET. Here is my code:

VB.NET:
Imports System.Runtime.InteropServices 

Module modWave 

    'Constants... 
    Const WAVE_FORMAT_PCM As Integer = 1 
    Const WAVE_MAPPER As Integer = -1 
    Const CALLBACK_FUNCTION As Integer = 0 
    Const CALLBACK_THREAD As Integer = 2097153 
    Const MEM_COMMIT As Integer = 4096 
    Const PAGE_READWRITE As Integer = 4 

    'API Declarations... 
    Declare Function waveInOpen Lib "winmm.dll" Alias "waveInOpen" (ByRef lphWaveIn As Int32, ByVal uDeviceID As Int32, ByRef lpFormat As WAVEFORMATEX, ByVal dwCallback As waveCallbackProc, ByVal dwInstance As UInt32, ByVal dwFlags As Int32) As Int32 
    Declare Function waveInStart Lib "winmm.dll" Alias "waveInStart" (ByVal hWaveIn As Int32) As Int32 
    Declare Function waveInStop Lib "winmm.dll" Alias "waveInStop" (ByVal hWaveIn As Int32) As Int32 
    Declare Function waveInAddBuffer Lib "winmm.dll" Alias "waveInAddBuffer" (ByVal hWaveIn As Int32, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As UInt32) As Int32 
    Declare Function waveInGetNumDevs Lib "winmm.dll" Alias "waveInGetNumDevs" () As Integer 
    Declare Function waveInGetDevCaps Lib "winmm.dll" Alias "waveInGetDevCapsA" (ByVal uDeviceID As Integer, ByRef lpCaps As WAVEINCAPS, ByVal uSize As Integer) As Integer 
    Declare Function waveInPrepareHeader Lib "winmm.dll" Alias "waveInPrepareHeader" (ByVal hWaveIn As Int32, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As UInt32) As Int32 
    Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Int32, ByVal dwSize As Int32, ByVal flAllocationType As Int32, ByVal flProtect As Int32) As Int32 

    'Define the signature of our callback procedure... 
    Public Delegate Sub waveCallbackProc(ByVal hwi As Int32, ByVal uMsg As UInt32, ByVal dwInstance As Int32, ByVal dwParam1 As Int32, ByVal dwparam2 As Int32) 

    'API Structures... 
    Structure WAVEFORMATEX 
        Dim wFormatTag As Int16 
        Dim nChannels As Int16 
        Dim nSamplesPerSec As Int32 
        Dim nAvgBytesPerSec As Int32 
        Dim nBlockAlign As Int16 
        Dim wBitsPerSample As Int16 
        Dim cbSize As Int16 
    End Structure 
    Structure WAVEINCAPS 
        Dim wMid As Int16 
        Dim wPid As Int16 
        Dim vDriverVersion As Int64 
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)> Dim szpName() As Char 'String of length 32 
        Dim dwFormats As Int32 
        Dim wChannels As Int16 
        Dim wReserved1 As Int16 
    End Structure 
    Structure WAVEHDR 
        Dim lpData As Int32 
        Dim dwBufferLength As Int32 
        Dim dwBytesRecorded As Int32 
        Dim dwUser As Int32 
        Dim dwFlags As Int32 
        Dim dwLoops As Int32 
        Dim reserved As Int32 
        Dim lpNext As Int32 
    End Structure 

    'Create two WAVEHDRs for double buffering... 
    'One will be processed while the other is being filled. 
    Dim bufferHeader(2) As WAVEHDR 

    'Store the handle to the waveIn device we are using... 
    Dim waveInHandle As Integer 

    'This procedure opens the given wave device and starts waveIn on it... 
    Public Sub openWaveDevice(ByVal devName As Integer) 

        'result of MM operations... 
        Dim result As UInt32 

        'Create a wave format object and set it up for 16bit 44khz stereo... 
        Dim waveFormat As WAVEFORMATEX 
        waveFormat.wFormatTag = WAVE_FORMAT_PCM 
        waveFormat.nChannels = 2 
        waveFormat.nSamplesPerSec = 44100 
        waveFormat.wBitsPerSample = 16 
        waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8) 
        waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign 
        waveFormat.cbSize = 0 
        
        'The lpData, dwBufferLength, and dwFlags members of the WAVEHDR structure 
        'must be set before calling this function (dwFlags must be zero).... 

        'Set up the first buffer... 
        bufferHeader(0).dwBufferLength = 1024 
        bufferHeader(0).dwFlags = 0 
        'Allocate the memory for both buffers... 
        bufferHeader(0).lpData = VirtualAlloc(0, bufferHeader(0).dwBufferLength * 2, MEM_COMMIT, PAGE_READWRITE) 

        'Set up the second buffer... 
        bufferHeader(1).dwBufferLength = 1024 
        bufferHeader(1).dwFlags = 0 
        'Point the second buffer to the pre-allocated memory (second half of that allocated above...) 
        bufferHeader(1).lpData = bufferHeader(0).lpData + bufferHeader(0).dwBufferLength 

        'Try to open the preferred device... 
        result = waveInOpen(waveInHandle, WAVE_MAPPER, waveFormat, AddressOf waveInProc, 0, CALLBACK_FUNCTION) 
        If (result) Then MsgBox("There was an error opening the device: " & result) 

        'Try to prepare the wave headers... 
        result = waveInPrepareHeader(waveInHandle, bufferHeader(0), Marshal.SizeOf(bufferHeader(0))) 
        If (result) Then MsgBox("There was an error preparing the buffer " & result) 

        result = waveInPrepareHeader(waveInHandle, bufferHeader(1), Marshal.SizeOf(bufferHeader(1))) 
        If (result) Then MsgBox("There was an error preparing the buffer " & result) 

        'Try to add the buffers... 
        result = waveInAddBuffer(waveInHandle, bufferHeader(0), 1024) 
        If (result) Then MsgBox("There was an error adding the buffer " & result) 

        result = waveInAddBuffer(waveInHandle, bufferHeader(1), 1024) 
        If (result) Then MsgBox("There was an error adding the buffer " & result) 

        'Try to start waveIn... 
        result = waveInStart(waveInHandle) 
        If (result) Then MsgBox("There was an error starting wav input " & result) 

    End Sub 

    'This procedure just stops waveIn... 
    Public Sub stopWave() 
        'Try to stop the waveIn... 
        Dim result As Integer = waveInStop(waveInHandle) 
        If (result) Then MsgBox("There was an error stopping wav input " & result) 
    End Sub 

    'Here's the callback. If it were being called, we'd get a messagebox. but we dont. 
    Public Sub waveInProc(ByVal hwi As Int32, ByVal uMsg As UInt32, ByVal dwInstance As Int32, ByVal dwParam1 As Int32, ByVal dwparam2 As Int32) 
        MsgBox("I've been called") 
    End Sub




For some reason, the callback procedure is not called. There are no errors presented by the compiler, so i'm quite sure that all the APIs and structures are correct. Can anyone see why the callback isn't called? Also, I hear that it is wiser to use callback threads instead. Can anyone help with this?

Any kind of help would be greatly appreciated. Thanks in advance.

Mike Payne
 
Const CALLBACK_FUNCTION As Integer = &H30000
- see if this helps
 
Done

That's done it! Thanks John. It's weird, i got the value for that constant directly from Winmm.h. Ah well.

Thanks again!
Mike
 
Back
Top