Help with audio recording latency in Vista (newbie)

DamoVB

New member
Joined
Jul 19, 2010
Messages
1
Programming Experience
Beginner
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:
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:
Back
Top