I have written a console app in vb.net to capture audio data. This works well in XP, no issues and little (or no observable) latency. However, when I run the .exe on a Vista, the recording latency is horrible (0.5 - 1 seconds).
Is this the code (using calls to winmm) or is it, as I have read, just the way Vista handles audio. If it is the latter, is it possible to get over this with code or should I focus on the hardware / drivers etc on Vista to get it working as well as it does in XP.
Any help appreciated.
Damo.
The audio portion of the code is here:
Is this the code (using calls to winmm) or is it, as I have read, just the way Vista handles audio. If it is the latter, is it possible to get over this with code or should I focus on the hardware / drivers etc on Vista to get it working as well as it does in XP.
Any help appreciated.
Damo.
The audio portion of the code is here:
VB.NET:
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Drawing.Drawing2D
Public Class Form1
Inherits System.Windows.Forms.Form
#Region "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 WAVEHDR
Dim lpData As IntPtr
Dim dwBufferLength As Int32
Dim dwBytesRecorded As Int32
Dim dwUser As Int32
Dim dwFlags As Int32
Dim dwLoops As Int32
Dim lpNext As Int32
Dim reserved As Int32
End Structure
#End Region
#Region "API declarations"
Private Declare Function waveInOpen Lib "winmm.dll" Alias "waveInOpen" (ByRef lphWaveIn As IntPtr, ByVal uDeviceID As Int32, ByRef lpFormat As WAVEFORMATEX, ByVal dwCallback As WaveCallBackProcedure, ByVal dwInstance As Int32, ByVal dwFlags As Int32) As Int32
Private Declare Function waveInClose Lib "winmm.dll" Alias "waveInClose" (ByVal hWaveIn As IntPtr) As Int32
Private Declare Function waveInReset Lib "winmm.dll" Alias "waveInReset" (ByVal hWaveIn As IntPtr) As Int32
Private Declare Function waveInStart Lib "winmm.dll" Alias "waveInStart" (ByVal hWaveIn As IntPtr) As Int32
Private Declare Function waveInStop Lib "winmm.dll" Alias "waveInStop" (ByVal hWaveIn As IntPtr) As Int32
Private Declare Function waveInAddBuffer Lib "winmm.dll" Alias "waveInAddBuffer" (ByVal hWaveIn As IntPtr, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As Int32) As Int32
Private Declare Function waveInPrepareHeader Lib "winmm.dll" Alias "waveInPrepareHeader" (ByVal hWaveIn As IntPtr, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As Int32) As Int32
Private Declare Function waveInUnprepareHeader Lib "winmm.dll" Alias "waveInUnprepareHeader" (ByVal hWaveIn As IntPtr, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As Int32) As Int32
Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As IntPtr, ByVal dwFlags As Int32, ByVal dwBytes As Int32) As Int32
Private Declare Function HeapCreate Lib "kernel32" (ByVal flOptions As Int32, ByVal dwInitialSize As Int32, ByVal dwMaximumSize As Int32) As IntPtr
Private Declare Function HeapDestroy Lib "kernel32" (ByVal hHeap As IntPtr) As Int32
#End Region
#Region "API Constants"
Private Const WAVE_FORMAT_PCM As Int32 = 1
Private Const WAVE_MAPPER As Int32 = -1
Private Const CALLBACK_FUNCTION As Int32 = &H30000
Private Const MM_WIM_DATA As Int32 = &H3C0
Private Const BUFFER_SIZE As Int32 = 512
Private Const NUMBER_OF_BUFFERS As Int32 = 16
Private Const HEAP_ZERO_MEMORY As Int32 = &H8
Private Const HEAP_GENERATE_EXCEPTIONS As Int32 = &H4
Private Const SAMPLE_RATE As Integer = 8000
Private Const BITS_PER_SAMPLE As Integer = 8
#End Region
Private Sub myWaveHandler_ProcessWave()
Try
If StopAddingBuffers = False Then
'add another buffer to the end of the queue
WaveBufferHeaders(BufferCount).dwFlags = 0
i = waveInPrepareHeader(WaveInHandle, WaveBufferHeaders(BufferCount), Marshal.SizeOf(WaveBufferHeaders(BufferCount)))
If i <> 0 Then
MsgBox("myWaveHandler_ProcessWave / waveInPrepareHeader Error", MsgBoxStyle.Exclamation)
End
End If
i = waveInAddBuffer(WaveInHandle, WaveBufferHeaders(BufferCount), Marshal.SizeOf(WaveBufferHeaders(BufferCount)))
If i <> 0 Then
MsgBox("myWaveHandler_ProcessWave / waveInAddBuffer Error", MsgBoxStyle.Exclamation)
End
End If
BufferCount = BufferCount + 1
If BufferCount > NUMBER_OF_BUFFERS - 1 Then BufferCount = 0
'SignalWindow.Clear(Color.Black)
SignalWindow.DrawLine(myBlackSignalPen, 0, 0, 0, PicSignalHeight)
For j = 0 To (BUFFER_SIZE - 1)
'//Do Other Signal Processing Here
Next
End If
Catch e As Exception
MsgBox("myWaveHandler_ProcessWave Error: " & e.ToString, MsgBoxStyle.Exclamation)
End
End Try
End Sub
Private Function MyWaveCallBackProcedure(ByVal hwi As IntPtr, ByVal uMsg As Int32, ByVal dwInstance As Int32, ByVal dwParam1 As Int32, ByVal dwParam2 As Int32) As Integer
Try
InCallBackProcedure = True
If uMsg = MM_WIM_DATA And WaveBufferHeaders(BufferCount).dwBytesRecorded = BUFFER_SIZE Then
Marshal.Copy(WaveBufferHeaders(BufferCount).lpData, RawWaveData, 0, _
WaveBufferHeaders(BufferCount).dwBytesRecorded) 'get the data
myWaveHandler_ProcessWave()
End If
InCallBackProcedure = False
Catch e As Exception
MsgBox("MyWaveCallBackProcedure Error: " & e.ToString, MsgBoxStyle.Exclamation)
End
End Try
End Function
Private Sub InitializeWaveInput()
Try
StopAddingBuffers = False
Dim waveFormat As WAVEFORMATEX
myCallBackFunction = New WaveCallBackProcedure(AddressOf MyWaveCallBackProcedure) 'use with callback
With waveFormat
.wFormatTag = WAVE_FORMAT_PCM 'uncompressed Pulse Code Modulation
.nchannels = 1 'mono 2 for stereo
.nSamplesPerSec = SAMPLE_RATE '44100 is CD quality
.wBitsPerSample = BITS_PER_SAMPLE 'CD quality is 16
.nBlockAlign = .nchannels * (.wBitsPerSample / 8)
.nAvgBytesPerSec = .nSamplesPerSec * .nBlockAlign
.cbSize = 0
End With
For j = 0 To NUMBER_OF_BUFFERS - 1
With WaveBufferHeaders(j)
.dwBufferLength = BUFFER_SIZE
.dwFlags = 0
.dwLoops = 0
.dwUser = 0
hHeap(j) = HeapCreate(HEAP_GENERATE_EXCEPTIONS, BUFFER_SIZE, 0)
.lpData = New IntPtr(HeapAlloc(hHeap(j), HEAP_ZERO_MEMORY, BUFFER_SIZE))
End With
Next
i = waveInOpen(WaveInHandle, WAVE_MAPPER, waveFormat, myCallBackFunction, 0, CALLBACK_FUNCTION)
If i <> 0 Then
MsgBox("InitializeWaveInput / WaveInOpen Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
For j = 0 To NUMBER_OF_BUFFERS - 1
i = waveInPrepareHeader(WaveInHandle, WaveBufferHeaders(j), Marshal.SizeOf(WaveBufferHeaders(j)))
If i <> 0 Then
MsgBox("InitializeWaveInput / waveInPrepareHeader Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
i = waveInAddBuffer(WaveInHandle, WaveBufferHeaders(j), Marshal.SizeOf(WaveBufferHeaders(j)))
If i <> 0 Then
MsgBox("InitializeWaveInput / waveInAddBuffer Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
Next
i = waveInStart(WaveInHandle)
If i <> 0 Then
MsgBox("InitializeWaveInput / waveInStart Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
Else
End If
Catch e As Exception
MsgBox("InitializeWaveInput Error: " & e.ToString, MsgBoxStyle.Exclamation)
End
End Try
End Sub
Private Sub ShutDownWaves()
Try
Dim temp As Integer, t As Integer
StopAddingBuffers = True
Do
Application.DoEvents()
Loop Until Not InCallBackProcedure
i = waveInReset(WaveInHandle)
If i <> 0 Then
MsgBox("ShutDownWaves / waveInReset Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
For j = 0 To NUMBER_OF_BUFFERS - 1
i = waveInUnprepareHeader(WaveInHandle, WaveBufferHeaders(j), Marshal.SizeOf(WaveBufferHeaders(j)))
If i <> 0 Then
MsgBox("ShutDownWaves / waveInUnprepareHeader Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
HeapDestroy(hHeap(j))
Next
i = waveInClose(WaveInHandle)
If i <> 0 Then
MsgBox("ShutDownWaves / waveInClose Error - (i) returned " & i, MsgBoxStyle.Exclamation)
End
End If
BufferCount = 0
Catch e As Exception
MsgBox("ShutDownWaves Error: " & e.ToString, MsgBoxStyle.Exclamation)
End
End Try
End Sub
End Class
Last edited by a moderator: