Click here to Skip to main content
12,697,076 members (26,722 online)
Click here to Skip to main content

Stats

80K views
2.8K downloads
30 bookmarked
Posted

VB.NET Wav file graphical viewer control

, 22 Mar 2005
A control to produce a graphical display of any 16bit PCM Wav file.
vbnetWaveRender_02
vbnetWaveRenderTestApp_02
bin
vbnetWaveRenderTestApp_02.exe
vbnetWaveRenderTestApp_02.exe.manifest
vbnetWaveRender_02.dll
vbnetWaveRenderTestApp_02.vbproj.user
vbnetWaveRender_02
bin
vbnetWaveRender_02.dll
vbnetWaveRender_02.vbproj.user
Option Strict
Option Explicit

'
'   WaveFile class
'     written in VB.NET                          Version: 1.0
'     by The KPD-Team                            Date: 2002/01/16
'     Copyright � 2002                           Comments to: KPDTeam@allapi.net
'                                                URL: http://www.allapi.net/
'
'
'  You are free to use this class file in your own applications,
'  but you are expressly forbidden from selling or otherwise
'  distributing this code as source without prior written consent.
'  This includes both posting samples on a web site or otherwise
'  reproducing it in text or html format.
'
'  Although much care has gone into the programming of this class
'  file, The KPD-Team does not accept any responsibility for damage
'  caused by possible errors in this class and/or by misuse of this
'  class.
'
'  Many thanks to Mark Hurd for removing a serious bug from this
'  class file.
'

Imports System.Runtime.InteropServices
Imports System.Text
Imports System.IO
Imports Microsoft.VisualBasic
Imports System

'/// <summary>This is an abstract representation of a WAVE file.</summary>
Friend Class WaveFile
    '<API-DECLARES>
    Private Const CALLBACK_WINDOW As Integer = &H10000
    Private Const CALLBACK_FUNCTION As Integer = &H30000
    Private Const MMIO_READ As Integer = &H0
    Private Const MMIO_FINDCHUNK As Integer = &H10
    Private Const MMIO_FINDRIFF As Integer = &H20
    Private Const MM_WOM_DONE As Integer = &H3BD
    Private Const MMSYSERR_NOERROR As Integer = 0
    Private Const SEEK_CUR As Integer = 1
    Private Const SEEK_END As Integer = 2
    Private Const SEEK_SET As Integer = 0
    Private Const TIME_BYTES As Integer = &H4
    Private Const WHDR_DONE As Integer = &H1
    Private Const NUM_BUFFERS As Integer = 5
    Private Const BUFFER_SECONDS As Single = 0.1

    <StructLayout(LayoutKind.Sequential)> _
Private Structure MMIOINFO
        Public dwFlags As Integer
        Public fccIOProc As Integer
        Public pIOProc As Integer
        Public wErrorRet As Integer
        Public htask As Integer
        Public cchBuffer As Integer
        Public pchBuffer As String
        Public pchNext As String
        Public pchEndRead As String
        Public pchEndWrite As String
        Public lBufOffset As Integer
        Public lDiskOffset As Integer
        Public adwInfo1 As Integer
        Public adwInfo2 As Integer
        Public adwInfo3 As Integer
        Public adwInfo4 As Integer
        Public dwReserved1 As Integer
        Public dwReserved2 As Integer
        Public hmmio As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Private Structure WAVEHDR
        Public lpData As Integer
        Public dwBufferLength As Integer
        Public dwBytesRecorded As Integer
        Public dwUser As Integer
        Public dwFlags As Integer
        Public dwLoops As Integer
        Public lpNext As Integer
        Public Reserved As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Private Structure WAVEINCAPS
        Public wMid As Short
        Public wPid As Short
        Public vDriverVersion As Integer
        Public szPname As String
        Public dwFormats As Integer
        Public wChannels As Short
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Private Structure WAVEFORMAT
        Public wFormatTag As Short
        Public nChannels As Short
        Public nSamplesPerSec As Integer
        Public nAvgBytesPerSec As Integer
        Public nBlockAlign As Short
        Public wBitsPerSample As Short
        Public cbSize As Short
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Private Structure MMCKINFO
        Public ckid As Integer
        Public ckSize As Integer
        Public fccType As Integer
        Public dwDataOffset As Integer
        Public dwFlags As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Private Structure MMTIME
        Public wType As Integer
        Public u As Integer
        Public x As Integer
    End Structure
    Private Declare Function waveOutGetPosition Lib "winmm.dll" (ByVal hWaveOut As IntPtr, ByRef lpInfo As MMTIME, ByVal uSize As Integer) As Integer
    Private Declare Ansi Function waveOutOpen Lib "winmm.dll" (ByRef hWaveOut As IntPtr, ByVal uDeviceID As Integer, ByVal format() As Byte, ByVal dwCallback As WaveDelegate, ByRef fPlaying As Integer, ByVal dwFlags As Integer) As Integer
    Private Declare Function waveOutPrepareHeader Lib "winmm.dll" (ByVal hWaveIn As IntPtr, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As Integer) As Integer
    Private Declare Function waveOutPrepareHeaderPtr Lib "winmm.dll" (ByVal hWaveIn As IntPtr, ByVal lpWaveInHdr As Integer, ByVal uSize As Integer) As Integer
    Private Declare Function waveOutReset Lib "winmm.dll" (ByVal hWaveIn As IntPtr) As Integer
    Private Declare Function waveOutUnprepareHeader Lib "winmm.dll" (ByVal hWaveIn As IntPtr, ByRef lpWaveInHdr As WAVEHDR, ByVal uSize As Integer) As Integer
    Private Declare Function waveOutClose Lib "winmm.dll" (ByVal hWaveIn As IntPtr) As Integer
    Private Declare Function waveOutWrite Lib "winmm.dll" (ByVal hWaveOut As IntPtr, ByRef lpWaveOutHdr As WAVEHDR, ByVal uSize As Integer) As Integer
    Private Declare Function waveOutPause Lib "winmm.dll" (ByVal hWaveOut As IntPtr) As Integer
    Private Declare Function waveOutRestart Lib "winmm.dll" (ByVal hWaveOut As IntPtr) As Integer
    Private Declare Function waveOutSetVolume Lib "winmm.dll" (ByVal uDeviceID As IntPtr, ByVal dwVolume As UInt32) As Integer
    Private Declare Function waveOutGetVolume Lib "winmm.dll" (ByVal uDeviceID As IntPtr, ByRef lpdwVolume As Integer) As Integer
    Private Declare Function mmioClose Lib "winmm.dll" (ByVal hmmio As IntPtr, ByVal uFlags As Integer) As Integer
    Private Declare Function mmioDescend Lib "winmm.dll" (ByVal hmmio As IntPtr, ByRef lpck As MMCKINFO, ByRef lpckParent As MMCKINFO, ByVal uFlags As Integer) As Integer
    Private Declare Function mmioDescendParent Lib "winmm.dll" Alias "mmioDescend" (ByVal hmmio As IntPtr, ByRef lpck As MMCKINFO, ByVal x As Integer, ByVal uFlags As Integer) As Integer
    Private Declare Ansi Function mmioOpen Lib "winmm.dll" Alias "mmioOpenA" (ByVal szFileName As String, ByRef lpmmioinfo As MMIOINFO, ByVal dwOpenFlags As Integer) As IntPtr
    Private Declare Function mmioRead Lib "winmm.dll" (ByVal hmmio As IntPtr, ByVal pch As Integer, ByVal cch As Integer) As Integer
    Private Declare Function mmioReadString Lib "winmm.dll" Alias "mmioRead" (ByVal hmmio As IntPtr, ByVal pch() As Byte, ByVal cch As Integer) As Integer
    Private Declare Function mmioSeek Lib "winmm.dll" (ByVal hmmio As IntPtr, ByVal lOffset As Integer, ByVal iOrigin As Integer) As Integer
    Private Declare Ansi Function mmioStringToFOURCC Lib "winmm.dll" Alias "mmioStringToFOURCCA" (ByVal sz As String, ByVal uFlags As Integer) As Integer
    Private Declare Function mmioAscend Lib "winmm.dll" (ByVal hmmio As IntPtr, ByRef lpck As MMCKINFO, ByVal uFlags As Integer) As Integer
    Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Integer, ByVal dwBytes As Integer) As IntPtr
    Private Declare Function GlobalLock Lib "kernel32" (ByVal hmem As IntPtr) As IntPtr
    Private Declare Function GlobalFree Lib "kernel32" (ByVal hmem As IntPtr) As Integer
    Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hmem As IntPtr) As Integer
    Private Declare Sub CopyWaveFormatFromBytes Lib "kernel32" Alias "RtlMoveMemory" (ByRef dest As WAVEFORMAT, ByVal source() As Byte, ByVal cb As Integer)
    Private Declare Sub CopyWaveHeaderFromPointer Lib "kernel32" Alias "RtlMoveMemory" (ByRef dest As WAVEHDR, ByVal source As Integer, ByVal cb As Integer)
    Private Declare Function IsBadWritePtr Lib "kernel32" (ByVal lp As Integer, ByVal ucb As Integer) As Integer
    '</API-DECLARES>
    Private Delegate Sub WaveDelegate(ByVal hwo As IntPtr, ByVal uMsg As Integer, ByVal dwInstance As Integer, ByRef wavhdr As WAVEHDR, ByVal dwParam2 As Integer)

    '---------------------------------------------------------------------------------------------
    'Added 05/03/05
    '---------------------------------------------------------------------------------------------

    Private m_lBufferSize As Integer
    Private m_FileOpen As Boolean
    Private m_lPtrBuffer As IntPtr = IntPtr.Zero
    Private m_lCurrentReadSize As Integer
    Private m_hMemBuffer As IntPtr = IntPtr.Zero
    Private m_hPtrBuffer As IntPtr = IntPtr.Zero


    Public Sub New()
        MyBase.New()
        Initialize()
    End Sub

    Private Sub Initialize()
        m_lBufferSize = 131072
        m_FileOpen = False
    End Sub

    '---------------------------------------------------------------------------------------------
    'Not required as already present in class
    '---------------------------------------------------------------------------------------------
    'Private Sub Terminate()
    '    CloseFile()
    'End Sub

    'Protected Overrides Sub Finalize()
    '    Terminate()
    '    MyBase.Finalize()
    'End Sub
    '---------------------------------------------------------------------------------------------

    Public Sub SeekRelative(ByVal lSampleOffset As Integer)
        Dim lSample As Integer
        lSample = mmioSeek(m_MmioIn, SEEK_CUR, 0) - m_DataOffset
        If (lSample + lSampleOffset * 4) > m_AudioLength Then
            Throw New MediaException("Position out of range")
        ElseIf (lSample - lSampleOffset * 4) < 0 Then
            Throw New MediaException("Position out of range")
        Else
            mmioSeek(m_MmioIn, lSampleOffset * 4, SEEK_CUR)
        End If
    End Sub

    Public Sub SeekAbsolute(ByVal lSample As Integer)
        If ((lSample * 4) > m_AudioLength) Or (lSample < 0) Then
            Throw New MediaException("Position out of range")
        Else
            mmioSeek(m_MmioIn, (lSample * 4) + m_DataOffset, SEEK_SET)
        End If
    End Sub

    Public Function Read() As Boolean
        Dim dataRemaining As Integer
        Dim lR As Integer

        If (m_MmioIn.Equals(IntPtr.Zero)) Then
            Throw New MediaException("No Wave File Open")
            Exit Function
        End If

        dataRemaining = (m_DataOffset + m_AudioLength - mmioSeek(m_MmioIn, 0, SEEK_CUR))
        If (m_lBufferSize < dataRemaining) Then
            lR = mmioRead(m_MmioIn, m_hPtrBuffer.ToInt32, m_lBufferSize)
            m_lCurrentReadSize = m_lBufferSize
            Read = True
        ElseIf (dataRemaining > 0) Then
            lR = mmioRead(m_MmioIn, m_hPtrBuffer.ToInt32, dataRemaining)
            m_lCurrentReadSize = dataRemaining
            Read = False
        Else
            Read = False
        End If
    End Function

    Public Property Filename() As String
        Get
            Filename = m_Filename
        End Get
        Set(ByVal Value As String)
            If OpenFile(Value) Then
                m_Filename = Value
            End If
        End Set
    End Property

    Public ReadOnly Property FileOpen() As Boolean
        Get
            FileOpen = m_FileOpen
        End Get
    End Property

    Public ReadOnly Property BufferStartPosition() As Integer
        Get
            BufferStartPosition = mmioSeek(m_MmioIn, 0, SEEK_CUR) - m_DataOffset
        End Get
    End Property

    Public ReadOnly Property AudioLength() As Integer
        Get
            AudioLength = m_AudioLength \ 4
        End Get
    End Property

    Public ReadOnly Property ReadbufferSize() As Integer
        Get
            ReadbufferSize = m_lBufferSize \ 4
        End Get
    End Property

    Public ReadOnly Property ReadSize() As Integer
        Get
            ReadSize = m_lCurrentReadSize \ 4
        End Get
    End Property

    Public ReadOnly Property ReadBufferPtr() As IntPtr
        Get
            ReadBufferPtr = m_hPtrBuffer
        End Get
    End Property

    Private Function AllocateBuffer() As Boolean
        FreeBuffer()
        m_hMemBuffer = GlobalAlloc(0, m_lBufferSize * 4)
        If Not (m_hMemBuffer.Equals(IntPtr.Zero)) Then
            m_hPtrBuffer = GlobalLock(m_hMemBuffer)
            AllocateBuffer = Not (m_hPtrBuffer.Equals(IntPtr.Zero))
        End If
    End Function

    Private Sub FreeBuffer()
        If Not (m_hPtrBuffer.Equals(IntPtr.Zero)) Then
            GlobalUnlock(m_hMemBuffer)
            m_hPtrBuffer = IntPtr.Zero
        End If
        If Not (m_hMemBuffer.Equals(IntPtr.Zero)) Then
            GlobalFree(m_hMemBuffer)
            m_hMemBuffer = IntPtr.Zero
        End If
    End Sub

    Public Sub CloseFile()
        If Not m_MmioIn.Equals(IntPtr.Zero) Then
            mmioClose(m_MmioIn, 0)
            m_MmioIn = IntPtr.Zero
            FreeBuffer()
            m_lCurrentReadSize = 0
            m_DataOffset = 0
            m_AudioLength = 0
        End If
    End Sub

    Public Function OpenFile(ByVal sSoundFile As String) As Boolean
        '    'Make sure the file exists
        If (sSoundFile = "") Then
            Exit Function
        End If
        If Not File.Exists(sSoundFile) Then
            Throw New FileNotFoundException
            Exit Function
        End If
        Dim mmckinfoParentIn As MMCKINFO
        Dim mmckinfoSubchunkIn As MMCKINFO
        Dim mmioinf As MMIOINFO

        Dim bFailed As Boolean
        Dim iBuffer As Integer
        Dim lRem As Integer
        Dim rc As Integer

        CloseFile()



        'Open the input file
        m_MmioIn = mmioOpen(sSoundFile, mmioinf, MMIO_READ)
        If (InputHandle.ToInt64 = 0) Then
            Throw New MediaException("Error while opening the input file.")
            Exit Function
        End If

        'Check if this is a wave file
        mmckinfoParentIn.fccType = mmioStringToFOURCC("WAVE", 0)
        rc = mmioDescendParent(InputHandle, mmckinfoParentIn, 0, MMIO_FINDRIFF)
        If (rc <> MMSYSERR_NOERROR) Then
            CloseFile()
            Throw New MediaException("Invalid file type.")
        End If

        'Get format info
        mmckinfoSubchunkIn.ckid = mmioStringToFOURCC("fmt", 0)
        rc = mmioDescend(InputHandle, mmckinfoSubchunkIn, mmckinfoParentIn, MMIO_FINDCHUNK)
        If (rc <> MMSYSERR_NOERROR) Then
            CloseFile()
            Throw New MediaException("Couldn't find format chunk.")
        End If

        rc = mmioReadString(InputHandle, m_FormatBuffer, mmckinfoSubchunkIn.ckSize)
        If (rc = -1) Then
            CloseFile()
            Throw New MediaException("Couldn't read from WAVE file.")
        End If

        rc = mmioAscend(InputHandle, mmckinfoSubchunkIn, 0)
        CopyWaveFormatFromBytes(m_Format, m_FormatBuffer, Len(m_Format))

        If Not (m_Format.wBitsPerSample = 16) Or Not (m_Format.nChannels = 2) Then
            CloseFile()
            Throw New MediaException("Only stereo 16bit wave files supported")
            Exit Function
        End If

        'Find the data subchunk
        mmckinfoSubchunkIn.ckid = mmioStringToFOURCC("data", 0)
        rc = mmioDescend(InputHandle, mmckinfoSubchunkIn, mmckinfoParentIn, MMIO_FINDCHUNK)
        If (rc <> MMSYSERR_NOERROR) Then
            CloseFile()
            Throw New MediaException("Unable to find the data chunk.")
        End If
        m_DataOffset = mmioSeek(InputHandle, 0, SEEK_CUR)

        'Get the length of the audio
        m_AudioLength = mmckinfoSubchunkIn.ckSize

        If Not AllocateBuffer() Then
            CloseFile()
            Throw New MediaException("Unable to Allocate Buffer")
            Exit Function
        End If

        '    'Allocate audio buffers
        '    m_BufferSize = CType(m_Format.nSamplesPerSec * m_Format.nBlockAlign * m_Format.nChannels * BUFFER_SECONDS, Integer)
        '    m_BufferSize = m_BufferSize - (m_BufferSize Mod m_Format.nBlockAlign)
        '    For i = 0 To NUM_BUFFERS - 1
        '        GlobalFree(hmem(i))
        '        hmem(i) = GlobalAlloc(0, m_BufferSize)
        '        pmem(i) = GlobalLock(hmem(i))
        '    Next


        '    'The class in successfully initialized
        '    m_Initialized = True

        OpenFile = True
        m_FileOpen = True
    End Function



    '---------------------------------------------------------------------------------------------
    '---------------------------------------------------------------------------------------------


    'Public Sub New(Filename as String)
    '	If Filename Is Nothing Then Throw New ArgumentException()
    '	m_Filename = Filename
    '	OpenFile()
    'End Sub


    '---------------------------------------------------------------------------------------------
    'Added
    '---------------------------------------------------------------------------------------------

    Public ReadOnly Property Channels() As Int16
        Get
            Return m_Format.nChannels
        End Get
    End Property

    ''' <summary>
    ''' Gets the sample frequency of the file.
    ''' </summary>
    Public ReadOnly Property SamplingFrequency() As Integer
        Get
            Return m_Format.nSamplesPerSec
        End Get
    End Property

    ''' <summary>
    ''' Gets the number of bits per sample in the wave file.
    ''' </summary>
    Public ReadOnly Property BitsPerSample() As Int16
        Get
            Return m_Format.wBitsPerSample
        End Get
    End Property

    '---------------------------------------------------------------------------------------------

    '/// <summary>Starts playing the wave file.</summary>
    '/// <exceptions cref="MediaException">Thrown when an error occured while reading from the file.</exceptions>
    'Public Sub Play()
    '    If InputHandle.Equals(IntPtr.Zero) Then Exit Sub
    '    If m_Playing Then Exit Sub
    '    Dim rc, i As Integer
    '    m_Callback = AddressOf WaveCallBack
    '    rc = waveOutOpen(m_WaveOut, 0, m_FormatBuffer, m_Callback, Nothing, CALLBACK_FUNCTION)
    '    If (rc <> MMSYSERR_NOERROR) Then
    '        Throw New MediaException("Unable to open the WAVE file.")
    '    End If
    '    hHdr = GCHandle.Alloc(hdr, GCHandleType.Pinned)
    '    For i = 0 To NUM_BUFFERS - 1
    '        hdr(i).lpData = pmem(i).ToInt32
    '        hdr(i).dwBufferLength = m_BufferSize
    '        hdr(i).dwFlags = 0
    '        hdr(i).dwLoops = 0
    '        rc = waveOutPrepareHeader(WaveOutHandle, hdr(i), Len(hdr(i)))
    '        If (rc <> MMSYSERR_NOERROR) Then
    '            Throw New MediaException("Unable to prepare the WAVE buffers.")
    '        End If
    '    Next
    '    m_Playing = True
    '    m_Paused = False
    '    m_StartPos = mmioSeek(InputHandle, 0, SEEK_CUR) - m_DataOffset
    '    For i = 0 To NUM_BUFFERS - 1
    '        WaveCallBack(InputHandle, MM_WOM_DONE, 0, hdr(i), 0)
    '    Next i
    'End Sub
    ''/// <summary>Stops the playback of the wave file.</summary>
    'Public Sub StopPlay()
    '    Dim i As Integer
    '    m_Playing = False
    '    waveOutReset(WaveOutHandle)
    '    For i = 0 To NUM_BUFFERS - 1
    '        waveOutUnprepareHeader(WaveOutHandle, hdr(i), Len(hdr(i)))
    '    Next
    '    waveOutClose(WaveOutHandle)
    '    Position = 0
    'End Sub
    '/// <summary>Specifies whether the WAVE file is currently paused or not.</summary>
    '/// <value>True when the file is paused, False otherwise.</value>
    'Public Property Paused() As Boolean
    '    Get
    '        Return m_Paused
    '    End Get
    '    Set(ByVal Value As Boolean)
    '        m_Paused = Value
    '        If m_Paused Then
    '            waveOutPause(WaveOutHandle)
    '        Else
    '            waveOutRestart(WaveOutHandle)
    '        End If
    '    End Set
    'End Property
    '/// <summary>Gets the name of the WAVE file.</summary>
    '/// <value>The name of the WAVE file.</value>

    'Public ReadOnly Property Filename() As String
    '    Get
    '        Return m_Filename
    '    End Get
    'End Property

    '/// <summary>Gets the length of the WAVE file.</summary>
    '/// <value>The length of the WAVE file.</value>
    Public ReadOnly Property Length() As Integer
        Get
            Return m_AudioLength \ m_Format.nBlockAlign
        End Get
    End Property
    '/// <summary>Specifies whether the WAVE file is currently playing.</summary>
    '/// <remarks>This property is only influenced by the methods 'Play' and 'StopPlay'. If you pause a file, Playing will still be True.</remarks>
    '/// <value>True if the WAVE file is currently playing, False otherwise.</value>
    'Public ReadOnly Property Playing() As Boolean
    '    Get
    '        Dim tm As MMTIME
    '        Dim lr As Integer
    '        tm.wType = TIME_BYTES
    '        lr = waveOutGetPosition(WaveOutHandle, tm, Len(tm))
    '        If lr = MMSYSERR_NOERROR Then
    '            Return True
    '        Else
    '            Return False
    '        End If

    '    End Get
    'End Property
    '/// <summary>Specifies the output volume.</summary>
    '/// <remarks>This value must be between 0 and 65535.</remarks>
    '/// <value>The output volume.</value>
    'Public Property Volume() As Integer
    '    Get
    '        waveOutGetVolume(WaveOutHandle, Volume)
    '        Volume = CType(Volume And &HFFFF&, Integer)
    '    End Get
    '    Set(ByVal Value As Integer)
    '        If Value < &H0 OrElse Value > &HFFFF Then Throw New ArgumentException
    '        waveOutSetVolume(WaveOutHandle, UInt32.Parse((Value + 2 ^ 16 * Value).ToString))
    '    End Set
    'End Property
    '/// <summary>Specifies the position in the WAVE file.</summary>
    '/// <value>The position in the WAVE file.</value>
    'Public Property Position() As Integer
    '    Get
    '        Dim tm As MMTIME
    '        tm.wType = TIME_BYTES
    '        If (waveOutGetPosition(WaveOutHandle, tm, Len(tm)) = MMSYSERR_NOERROR) Then
    '            Position = (m_StartPos + tm.u) \ m_Format.nBlockAlign
    '        Else
    '            Position = (mmioSeek(InputHandle, 0, SEEK_CUR) - m_DataOffset + m_BufferSize * NUM_BUFFERS) \ m_Format.nBlockAlign
    '        End If
    '    End Get
    '    Set(ByVal Value As Integer)
    '        If Not m_Initialized Then Exit Property
    '        Dim bytepos As Integer = Value * m_Format.nBlockAlign
    '        mmioSeek(InputHandle, bytepos + m_DataOffset, SEEK_SET)
    '    End Set
    'End Property
    '/// <summary>Returns the handle of the input device.</summary>
    '/// <value>The handle of the input device.</value>
    Private ReadOnly Property InputHandle() As IntPtr
        Get
            Return m_MmioIn
        End Get
    End Property
    ''/// <summary>Returns the handle of the output device.</summary>
    ''/// <value>The handle of the output device.</value>
    'Private ReadOnly Property WaveOutHandle() As IntPtr
    '    Get
    '        Return m_WaveOut
    '    End Get
    'End Property
    '/// <summary>Called when the class gets GCed.</summary>
    Protected Overrides Sub Finalize()
        CloseFile()
        MyBase.Finalize()
    End Sub
    '/// <summary>Used internally to open a wave file and initializing the required memory.</summary>
    '/// <exceptions cref="MediaException">Thrown when there was an error opening the file or allocating the necessary buffers.</exceptions>
    '/// <exceptions cref="FileNotFoundException">Thrown when the specified file could not be found.</exceptions>
    'Protected Sub OpenFile()
    '    'Make sure the file exists
    '    If Not File.Exists(Filename) Then
    '        Throw New FileNotFoundException
    '        Exit Sub
    '    End If
    '    Dim mmckinfoParentIn As MMCKINFO
    '    Dim mmckinfoSubchunkIn As MMCKINFO
    '    Dim mmioinf As MMIOINFO
    '    Dim rc, i As Integer
    '    'Open the input file
    '    m_MmioIn = mmioOpen(Filename, mmioinf, MMIO_READ)
    '    If (InputHandle.ToInt64 = 0) Then
    '        Throw New MediaException("Error while opening the input file.")
    '    End If
    '    'Check if this is a wave file
    '    mmckinfoParentIn.fccType = mmioStringToFOURCC("WAVE", 0)
    '    rc = mmioDescendParent(InputHandle, mmckinfoParentIn, 0, MMIO_FINDRIFF)
    '    If (rc <> MMSYSERR_NOERROR) Then
    '        CloseFile()
    '        Throw New MediaException("Invalid file type.")
    '    End If
    '    'Get format info
    '    mmckinfoSubchunkIn.ckid = mmioStringToFOURCC("fmt", 0)
    '    rc = mmioDescend(InputHandle, mmckinfoSubchunkIn, mmckinfoParentIn, MMIO_FINDCHUNK)
    '    If (rc <> MMSYSERR_NOERROR) Then
    '        CloseFile()
    '        Throw New MediaException("Couldn't find format chunk.")
    '    End If
    '    rc = mmioReadString(InputHandle, m_FormatBuffer, mmckinfoSubchunkIn.ckSize)
    '    If (rc = -1) Then
    '        CloseFile()
    '        Throw New MediaException("Couldn't read from WAVE file.")
    '    End If
    '    rc = mmioAscend(InputHandle, mmckinfoSubchunkIn, 0)
    '    CopyWaveFormatFromBytes(m_Format, m_FormatBuffer, Len(m_Format))
    '    'Find the data subchunk
    '    mmckinfoSubchunkIn.ckid = mmioStringToFOURCC("data", 0)
    '    rc = mmioDescend(InputHandle, mmckinfoSubchunkIn, mmckinfoParentIn, MMIO_FINDCHUNK)
    '    If (rc <> MMSYSERR_NOERROR) Then
    '        CloseFile()
    '        Throw New MediaException("Unable to find the data chunk.")
    '    End If
    '    m_DataOffset = mmioSeek(InputHandle, 0, SEEK_CUR)
    '    'Get the length of the audio
    '    m_AudioLength = mmckinfoSubchunkIn.ckSize
    '    'Allocate audio buffers
    '    m_BufferSize = CType(m_Format.nSamplesPerSec * m_Format.nBlockAlign * m_Format.nChannels * BUFFER_SECONDS, Integer)
    '    m_BufferSize = m_BufferSize - (m_BufferSize Mod m_Format.nBlockAlign)
    '    For i = 0 To NUM_BUFFERS - 1
    '        GlobalFree(hmem(i))
    '        hmem(i) = GlobalAlloc(0, m_BufferSize)
    '        pmem(i) = GlobalLock(hmem(i))
    '    Next
    '    'The class in successfully initialized
    '    m_Initialized = True
    'End Sub
    ''/// <summary>Used internally to close a wave file and free the used memory.</summary>
    'Protected Sub CloseFile()
    '    Dim i As Integer
    '    If Playing Then waveOutReset(WaveOutHandle)
    '    mmioClose(InputHandle, 0)
    '    For i = 0 To NUM_BUFFERS - 1
    '        GlobalFree(hmem(i))
    '    Next i
    '    If hHdr.IsAllocated Then hHdr.Free()
    'End Sub
    ''/// <summary>The callback function.</summary>
    'Private Sub WaveCallBack(ByVal hwo As IntPtr, ByVal uMsg As Integer, ByVal dwInstance As Integer, ByRef wavhdr As WAVEHDR, ByVal dwParam2 As Integer)
    '    If uMsg = MM_WOM_DONE AndAlso m_Playing Then
    '        Dim rc As Integer
    '        m_DataRemaining = (m_DataOffset + m_AudioLength - mmioSeek(InputHandle, 0, SEEK_CUR))
    '        If (m_BufferSize < m_DataRemaining) Then
    '            rc = mmioRead(InputHandle, wavhdr.lpData, m_BufferSize)
    '        Else
    '            rc = mmioRead(InputHandle, wavhdr.lpData, m_DataRemaining)
    '            m_Playing = False
    '        End If
    '        If rc <> -1 Then
    '            wavhdr.dwBufferLength = rc
    '            rc = waveOutWrite(WaveOutHandle, wavhdr, Len(wavhdr))
    '        End If
    '    End If
    'End Sub
    'Private variables
    Private m_Tel As Integer
    Private m_Filename As String
    Private m_Initialized As Boolean = False
    Private m_MmioIn As IntPtr = IntPtr.Zero
    Private m_DataOffset As Integer = 0
    Private m_AudioLength As Integer = 0
    Private m_BufferSize As Integer = 0
    Private hmem(NUM_BUFFERS - 1) As IntPtr  ' memory handles
    Private pmem(NUM_BUFFERS - 1) As IntPtr  ' memory pointers
    Private hdr(NUM_BUFFERS - 1) As WAVEHDR  ' wave headers
    Private m_Format As WAVEFORMAT   ' waveformat structure
    Private m_WaveOut As IntPtr = IntPtr.Zero
    Private m_Playing As Boolean = False
    Private m_StartPos As Integer = 0
    Private m_DataRemaining As Integer = 0
    Private m_FormatBuffer(49) As Byte
    Private m_Callback As WaveDelegate
    Private m_Paused As Boolean
    Private hHdr As GCHandle
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Quenchmaster
Web Developer
United Kingdom United Kingdom
Having done a four year Electronic Engineering Undergraduate course at the University of Warwick, I have now moved on to doing a PhD at the same place.

I am currently envolved in the use of signal processing in watermarking for copyright control.

I have always had a knack of picking up different programming languages quite easily but have not done much serious programming untill now.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170118.1 | Last Updated 22 Mar 2005
Article Copyright 2005 by Quenchmaster
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid