Hello everyone. I'm trying to implement a callback function for processing digital audio input in VB.NET. Here is my code:
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
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