Click here to Skip to main content
15,892,674 members
Articles / Desktop Programming / Windows Forms

VB.NET Wav file graphical viewer control

Rate me:
Please Sign up or sign in to vote.
4.64/5 (13 votes)
22 Mar 20053 min read 107.3K   4K   32  
A control to produce a graphical display of any 16bit PCM Wav file.
Imports System
Imports System.Drawing.Graphics
Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class vbnetWaveRender
    Inherits System.Windows.Forms.UserControl

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        UserControl_Initialize()

    End Sub

    'UserControl1 overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            UserControl_Terminate()
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents mainpanel As System.Windows.Forms.Panel
    Friend WithEvents hozScroll As System.Windows.Forms.HScrollBar
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.mainpanel = New System.Windows.Forms.Panel
        Me.hozScroll = New System.Windows.Forms.HScrollBar
        Me.mainpanel.SuspendLayout()
        Me.SuspendLayout()
        '
        'mainpanel
        '
        Me.mainpanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.mainpanel.Controls.Add(Me.hozScroll)
        Me.mainpanel.Dock = System.Windows.Forms.DockStyle.Fill
        Me.mainpanel.Location = New System.Drawing.Point(0, 0)
        Me.mainpanel.Name = "mainpanel"
        Me.mainpanel.Size = New System.Drawing.Size(400, 400)
        Me.mainpanel.TabIndex = 0
        '
        'hozScroll
        '
        Me.hozScroll.Dock = System.Windows.Forms.DockStyle.Bottom
        Me.hozScroll.Location = New System.Drawing.Point(0, 379)
        Me.hozScroll.Name = "hozScroll"
        Me.hozScroll.Size = New System.Drawing.Size(396, 17)
        Me.hozScroll.TabIndex = 0
        '
        'vbnetWaveRender
        '
        Me.Controls.Add(Me.mainpanel)
        Me.Name = "vbnetWaveRender"
        Me.Size = New System.Drawing.Size(400, 400)
        Me.mainpanel.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
    Public Structure WaveData
        Dim m_AudioPathL As Drawing2D.GraphicsPath
        Dim m_AudioPathR As Drawing2D.GraphicsPath
    End Structure

    'Stucture for Render Information
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
    Private Structure PaintInfo
        Dim m_oCSD_SX As Integer
        Dim m_oCSD_SY As Integer
        Dim m_oCSD_LX As Integer
        Dim m_oCSD_LY As Integer
        Dim m_oCSD_PEN As Pen

        Dim m_oCHADT_SX As Integer
        Dim m_oCHADT_SY As Integer
        Dim m_oCHADT_LX As Integer
        Dim m_oCHADT_LY As Integer
        Dim m_oCHADT_PEN As Pen

        Dim m_oCHADB_SX As Integer
        Dim m_oCHADB_SY As Integer
        Dim m_oCHADB_LX As Integer
        Dim m_oCHADB_LY As Integer
        Dim m_oCHADB_PEN As Pen

        Dim m_oCMDTT_SX As Integer
        Dim m_oCMDTT_SY As Integer
        Dim m_oCMDTT_LX As Integer
        Dim m_oCMDTT_LY As Integer
        Dim m_oCMDTT_pen As Pen

        Dim m_oCMDTB_SX As Integer
        Dim m_oCMDTB_SY As Integer
        Dim m_oCMDTB_LX As Integer
        Dim m_oCMDTB_LY As Integer
        Dim m_oCMDTB_pen As Pen

        Dim m_oCMDBT_SX As Integer
        Dim m_oCMDBT_SY As Integer
        Dim m_oCMDBT_LX As Integer
        Dim m_oCMDBT_LY As Integer
        Dim m_oCMDBT_pen As Pen

        Dim m_oCMDBB_SX As Integer
        Dim m_oCMDBB_SY As Integer
        Dim m_oCMDBB_LX As Integer
        Dim m_oCMDBB_LY As Integer
        Dim m_oCMDBB_pen As Pen

        Dim m_WAVENDCoverRec As Drawing.Rectangle
        Dim m_WAVENDCoverBrh As Drawing.Brush

        Dim m_AudioPathL As Drawing2D.GraphicsPath
        Dim m_AudioPathR As Drawing2D.GraphicsPath
        Dim m_AudioPen As Pen

        Public Sub init()
            m_AudioPathL = New Drawing2D.GraphicsPath
            m_AudioPathR = New Drawing2D.GraphicsPath
        End Sub
    End Structure

    'Set Enums
    Public Enum EWaveViewerZoom
        e24to1 = -24
        e16to1 = -16
        e8to1 = -8
        e6to1 = -6
        e4to1 = -4
        e3to1 = -3
        e2to1 = -2
        e1to1 = 1
        e1to2 = 2
        e1to4 = 4
        e1to8 = 8
        e1to16 = 16
        e1to32 = 32
        e1to64 = 64
        e1to128 = 128
        e1to256 = 256
        e1to512 = 512
        e1to1024 = 1024
        e1to2048 = 2048
        e1to4196 = 4196
        e1to8192 = 8192
        e1to16384 = 16384
    End Enum

    'State Events
    Public Event HalfAmplitudeDividerColorChange()
    Public Event HalfAmplitudeDividerWidthChange()
    Public Event HalfAmplitudeDividerStyleChange()
    Public Event WaveForeColorChange()
    Public Event StereoDividerColorChange()
    Public Event StereoDividerWidthChange()
    Public Event StereoDividerStyleChange()
    Public Event MidDividerColorChange()
    Public Event MidDividerWidthchange()
    Public Event MidDividerStylechange()
    Public Event NoWaveBackColorChange()
    Public Event BorderStyleChange()
    Public Event RenderFinished()
    Public Event RenderStarted()

    Private m_cWAVRead As WaveFile
    Private m_FileOpen As Boolean
    'Private WithEvents m_cScroll As cScrollBars
    Private m_lSampleStep As Integer
    Private m_lPixelStep As Integer
    Private m_lSamplePerPixelStep As Integer
    Private m_bSetting As Boolean
    Private m_GraphicInfoReady As Boolean
    Private PaintData As PaintInfo

    'State Property Variables
    Private m_lZoom As EWaveViewerZoom
    Private m_oWaveBackColor As System.Drawing.Color
    Private m_oNoWaveBackColor As System.Drawing.Color
    Private m_oWaveForeColor As System.Drawing.Color
    Private m_oColorStereoDivider As System.Drawing.Color
    Private m_oColorMidDivider As System.Drawing.Color
    Private m_oColorHalfAmplitudeDivider As System.Drawing.Color
    Private m_oStereoDividerLineThickNess As Short
    Private m_oStereoDividerLineStyle As Drawing2D.DashStyle
    Private m_oMidDividerLineThickNess As Short
    Private m_oMidDividerLineStyle As Drawing2D.DashStyle
    Private m_oHalfAmplitudeDividerLineThickNess As Short
    Private m_oHalfAmplitudeDividerLineStyle As Drawing2D.DashStyle
    Private m_bUseThread As Boolean
    Private m_ThreadDone As Boolean
    Private m_ThreadResultOk As Boolean

    'Thread Headers for WaveInfo Function
    Delegate Function WaveInfoHandler(ByVal lLastx As Integer, ByVal lLastLeftY As Integer, ByVal lLastRightY As Integer, _
    ByVal lx As Integer, ByVal ly As Integer, ByVal lEnd As Integer, ByVal lAbsSizeY As Integer, _
    ByVal bRectangles As Boolean, ByVal lMidy As Integer) As WaveData
    Delegate Sub UpdateUIHandler(ByVal Statusmsg As String, ByVal result As WaveData)
    Private WaveInfo_handler As WaveInfoHandler = AddressOf WaveInfo
    Private WaveInfo_callback As AsyncCallback = AddressOf GetWaveInfo_callback

    'Set the file name, used to start render operation
    <Category("Control Options"), Description("Sets the file name")> _
        Public Property WaveFile() As String
        Get
            If m_FileOpen Then
                WaveFile = m_cWAVRead.Filename
            Else
                WaveFile = ""
            End If
        End Get
        Set(ByVal Value As String)
            If Len(Value) = 0 Then
                m_cWAVRead = New WaveFile
            End If
            m_cWAVRead.Filename = Value

            If m_cWAVRead.FileOpen Then
                m_FileOpen = True
            End If

            SetScroll()
            renderWave()
        End Set
    End Property

    'File open information - read only
    '-------------------------------------------------------------
    ' Must be called before calling any of the following read only
    ' properties
    <Category("Control Data"), Description("Is a file open")> _
    Public ReadOnly Property WaveOpen() As Boolean
        Get
            WaveOpen = m_FileOpen
        End Get
    End Property
    'Number of chanels in data - read only
    '-------------------------------------------------------------
    ' The host application should only call this after detemining
    ' that a file is open (see above)
    ' Will return the number of chanels in the wave form
    <Category("Control Data"), Description("Number of Channels")> _
    Public ReadOnly Property WaveChannels() As Int16
        Get
            WaveChannels = m_cWAVRead.Channels
        End Get
    End Property
    'Sampling Frequency of data - read only
    '-------------------------------------------------------------
    ' The host application should only call this after detemining
    ' that a file is open (see above)
    ' Will return the sampling frequency of the wave form
    <Category("Control Data"), Description("Sampling Frequency")> _
    Public ReadOnly Property WaveSamplingFreq() As Integer
        Get
            WaveSamplingFreq = m_cWAVRead.SamplingFrequency
        End Get
    End Property
    'Number of bits per sample in data - read only
    '-------------------------------------------------------------
    ' The host application should only call this after detemining
    ' that a file is open (see above)
    ' Will return the number of bits per sample in the wave form
    <Category("Control Data"), Description("Bits per sample")> _
    Public ReadOnly Property WaveBitsPerSample() As Integer
        Get
            WaveBitsPerSample = m_cWAVRead.BitsPerSample
        End Get
    End Property

    'Processing Options
    <Category("Processing"), Description("Alowes control to use process render information in a new thread")> _
    Public Property ThreadUse() As Boolean
        Get
            ThreadUse = m_bUseThread
        End Get
        Set(ByVal Value As Boolean)
            m_bUseThread = Value
        End Set
    End Property
    Public Sub ResetThreadUse()
        m_bUseThread = True
    End Sub

    'Property Stuctures
    <Category("Appearance"), Description("Sets boarderstyle of the control")> _
    Public Property BoarderStyle() As BorderStyle
        Get
            BoarderStyle = mainpanel.BorderStyle
        End Get
        Set(ByVal Value As BorderStyle)
            mainpanel.BorderStyle = Value
            RaiseEvent BorderStyleChange()
        End Set
    End Property
    Public Sub ResetBoarderStyle()
        mainpanel.BorderStyle = BorderStyle.Fixed3D
    End Sub

    <Category("Appearance"), Description("Sets the backgorund colour when no wave is rendered")> _
    Public Property NoWaveBackColor() As System.Drawing.Color
        Get
            NoWaveBackColor = m_oNoWaveBackColor
        End Get
        Set(ByVal Value As System.Drawing.Color)
            m_oNoWaveBackColor = Value
            renderWave()
            RaiseEvent NoWaveBackColorChange()
        End Set
    End Property
    Public Sub ResetNoWaveBackColor()
        m_oNoWaveBackColor = System.Drawing.SystemColors.ControlDark
        renderWave()
    End Sub

    <Category("Appearance"), Description("Sets the colour of the wave render")> _
    Public Property WaveForeColor() As System.Drawing.Color
        Get
            WaveForeColor = m_oWaveForeColor
        End Get
        Set(ByVal Value As System.Drawing.Color)
            m_oWaveForeColor = Value
            renderWave()
            RaiseEvent WaveForeColorChange()
        End Set
    End Property
    Public Sub ResetWaveForeColor()
        m_oWaveForeColor = System.Drawing.ColorTranslator.FromOle(&H600000)
        renderWave()
    End Sub

    'Stereo Divider Options
    <Category("Appearance"), Description("Sets the colour of the line between the two chanels")> _
    Public Property StereoDividerColor() As System.Drawing.Color
        Get
            StereoDividerColor = m_oColorStereoDivider
        End Get
        Set(ByVal Value As System.Drawing.Color)
            m_oColorStereoDivider = Value
            renderWave()
            RaiseEvent StereoDividerColorChange()
        End Set
    End Property
    Public Sub ResetStereoDividerColor()
        m_oColorStereoDivider = System.Drawing.ColorTranslator.FromOle(&H0S)
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the thickness of the line between the two chanels")> _
    Public Property StereoDividerLineThickness() As Short
        Get
            StereoDividerLineThickness = m_oStereoDividerLineThickNess
        End Get
        Set(ByVal Value As Short)
            m_oStereoDividerLineThickNess = Value
            renderWave()
            RaiseEvent StereoDividerWidthChange()
        End Set
    End Property
    Public Sub ResetStereoDividerLineThickness()
        m_oStereoDividerLineThickNess = 1
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the style of the line between the two chanels")> _
    Public Property StereoDividerLineStyle() As Drawing2D.DashStyle
        Get
            StereoDividerLineStyle = m_oStereoDividerLineStyle
        End Get
        Set(ByVal Value As Drawing2D.DashStyle)
            m_oStereoDividerLineStyle = Value
            renderWave()
            RaiseEvent StereoDividerStyleChange()
        End Set
    End Property
    Public Sub ResetStereoDividerLinestyle()
        m_oStereoDividerLineStyle = Drawing2D.DashStyle.Solid
        renderWave()
    End Sub

    'Mid Divider Options
    <Category("Appearance"), Description("Sets the colour of the center line")> _
    Public Property MidDividerColor() As System.Drawing.Color
        Get
            MidDividerColor = m_oColorMidDivider
        End Get
        Set(ByVal Value As System.Drawing.Color)
            m_oColorMidDivider = Value
            renderWave()
            RaiseEvent MidDividerColorChange()
        End Set
    End Property
    Public Sub ResetMidDividerColor()
        m_oColorMidDivider = System.Drawing.SystemColors.Control
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the thickness of the line between the two chanels")> _
    Public Property MidDividerLineThickness() As Short
        Get
            MidDividerLineThickness = m_oMidDividerLineThickNess
        End Get
        Set(ByVal Value As Short)
            m_oMidDividerLineThickNess = Value
            renderWave()
            RaiseEvent MidDividerWidthchange()
        End Set
    End Property
    Public Sub ResetMidDividerLineThickness()
        m_oMidDividerLineThickNess = 1
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the style of the line between the two chanels")> _
    Public Property MidDividerLineStyle() As Drawing2D.DashStyle
        Get
            MidDividerLineStyle = m_oMidDividerLineStyle
        End Get
        Set(ByVal Value As Drawing2D.DashStyle)
            m_oMidDividerLineStyle = Value
            renderWave()
            RaiseEvent MidDividerStylechange()
        End Set
    End Property
    Public Sub ResetMidDividerLinestyle()
        m_oMidDividerLineStyle = Drawing2D.DashStyle.Solid
        renderWave()
    End Sub

    'Half Amplitude Options
    <Category("Appearance"), Description("Sets the colour of the half amplitude line ")> _
        Public Property HalfAmplitudeDividerColor() As System.Drawing.Color
        Get
            HalfAmplitudeDividerColor = m_oColorHalfAmplitudeDivider
        End Get
        Set(ByVal Value As System.Drawing.Color)
            m_oColorHalfAmplitudeDivider = Value
            renderWave()
            RaiseEvent HalfAmplitudeDividerColorChange()
        End Set
    End Property
    Public Sub ResetHalfAmplitudeDividerColor()
        m_oColorHalfAmplitudeDivider = System.Drawing.ColorTranslator.FromOle(&HFF0000)
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the thickness of the line between the two chanels")> _
    Public Property HalfAmplitudeDividerLineThickness() As Short
        Get
            HalfAmplitudeDividerLineThickness = m_oHalfAmplitudeDividerLineThickNess
        End Get
        Set(ByVal Value As Short)
            m_oHalfAmplitudeDividerLineThickNess = Value
            RaiseEvent HalfAmplitudeDividerWidthChange()
            renderWave()
        End Set
    End Property
    Public Sub ResetHalfAmplitudeDividerLineThickness()
        m_oHalfAmplitudeDividerLineThickNess = 1
        renderWave()
    End Sub
    <Category("Appearance"), Description("Sets the style of the line between the two chanels")> _
    Public Property HalfAmplitudeDividerLineStyle() As Drawing2D.DashStyle
        Get
            HalfAmplitudeDividerLineStyle = m_oHalfAmplitudeDividerLineStyle
        End Get
        Set(ByVal Value As Drawing2D.DashStyle)
            m_oHalfAmplitudeDividerLineStyle = Value
            renderWave()
            RaiseEvent HalfAmplitudeDividerStyleChange()
        End Set
    End Property
    Public Sub ResetHalfAmplitudeDividerLinestyle()
        m_oHalfAmplitudeDividerLineStyle = Drawing2D.DashStyle.Solid
        renderWave()
    End Sub

    'Zoom control
    <Category("Control Options"), Description("Sets the zoom ratio at start up")> _
        Public Property Zoom() As EWaveViewerZoom
        Get
            Zoom = m_lZoom
        End Get
        Set(ByVal Value As EWaveViewerZoom)
            If Not (m_lZoom = Value) Then
                m_lZoom = Value
                SetScroll()
                renderWave()
            End If
        End Set
    End Property
    Public Sub ResetZoom()
        m_lZoom = EWaveViewerZoom.e1to1
        SetScroll()
        renderWave()
    End Sub

    Private Sub UserControl_Initialize()
        m_cWAVRead = New WaveFile

        m_GraphicInfoReady = False
        m_FileOpen = False

        PaintData.init()

        m_lZoom = EWaveViewerZoom.e1to1
        m_oWaveBackColor = System.Drawing.SystemColors.Window
        m_oNoWaveBackColor = System.Drawing.SystemColors.ControlDark
        m_oWaveForeColor = System.Drawing.ColorTranslator.FromOle(&H600000)
        m_oColorStereoDivider = System.Drawing.ColorTranslator.FromOle(&H0S)
        m_oStereoDividerLineThickNess = 1
        m_oStereoDividerLineStyle = Drawing2D.DashStyle.Solid
        m_oColorMidDivider = System.Drawing.SystemColors.HotTrack
        m_oMidDividerLineThickNess = 1
        m_oMidDividerLineStyle = Drawing2D.DashStyle.Solid
        m_oColorHalfAmplitudeDivider = System.Drawing.ColorTranslator.FromOle(&HFF0000)
        m_oHalfAmplitudeDividerLineThickNess = 1
        m_oHalfAmplitudeDividerLineStyle = Drawing2D.DashStyle.Solid

        m_ThreadDone = True
        m_bUseThread = True
        renderWave()


    End Sub

    'End Functions
    Private Sub UserControl_Terminate()
        'm_cScroll = Nothing
        m_cWAVRead = Nothing
    End Sub

    'Main Functions
    'Set Scroll
    Private Sub SetScroll()
        Dim lMax As Integer
        m_bSetting = True
        If m_FileOpen Then
            If m_lZoom <= 1 Then
                m_lSampleStep = 1
                m_lPixelStep = System.Math.Abs(m_lZoom)
                m_lSamplePerPixelStep = 1
                lMax = m_cWAVRead.AudioLength
            Else
                m_lSamplePerPixelStep = m_lZoom
                m_lSampleStep = m_lSamplePerPixelStep \ 32
                If (m_lSampleStep < 1) Then
                    m_lSampleStep = 1
                End If
                m_lPixelStep = 1

                lMax = (m_cWAVRead.AudioLength \ m_lSamplePerPixelStep) - MyBase.ClientRectangle.Width
            End If

            If lMax < 0 Then
                hozScroll.Value = 0
                hozScroll.Visible = False
                '            m_cScroll.ValueA(cScrollBars.EFSScrollBarConstants.efsHorizontal) = 0
                '            m_cScroll.Visible(cScrollBars.EFSScrollBarConstants.efsHorizontal) = False
            Else
                hozScroll.SmallChange = MyBase.ClientRectangle.Width \ 32
                hozScroll.LargeChange = MyBase.ClientRectangle.Width
                hozScroll.Maximum = lMax
                hozScroll.Visible = True
                '            m_cScroll.SmallChange(cScrollBars.EFSScrollBarConstants.efsHorizontal) = MyBase.ClientRectangle.Width \ 32
                '            m_cScroll.LargeChange(cScrollBars.EFSScrollBarConstants.efsHorizontal) = MyBase.ClientRectangle.Width
                '            m_cScroll.Max(cScrollBars.EFSScrollBarConstants.efsHorizontal) = lMax
                '            m_cScroll.Visible(cScrollBars.EFSScrollBarConstants.efsHorizontal) = True
            End If

        End If
        m_bSetting = False
    End Sub
    'Determin if there is a scroll change
    Private Sub hozscroll_change(ByVal sender As Object, ByVal e As EventArgs) Handles hozScroll.ValueChanged
        If m_FileOpen And (m_cWAVRead.AudioLength > 0) Then
            renderWave()
        End If
    End Sub
    'Determin if the scroll value changes
    Private Sub hozScroll_scroll(ByVal sender As Object, ByVal e As ScrollEventArgs) Handles hozScroll.Scroll
        If m_FileOpen And (m_cWAVRead.AudioLength > 0) Then
            renderWave()
        End If
    End Sub

    'Handle for mousewheel data... has to be passed to it from the host application
    Public Sub cont_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles hozScroll.MouseWheel
        Dim numberToMove As Integer = e.Delta * SystemInformation.MouseWheelScrollLines / 120

        Dim iTemp As Integer = hozScroll.Value + numberToMove
        If iTemp < 0 Then
            iTemp = 0
        End If
        If iTemp > hozScroll.Maximum Then
            iTemp = hozScroll.Maximum
        End If
        hozScroll.Value = iTemp
    End Sub

    'Private Sub mainpanel_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles mainpanel.MouseDown
    '    m_cScroll.ValueA(cScrollBars.EFSScrollBarConstants.efsHorizontal) = m_cScroll.ValueA(cScrollBars.EFSScrollBarConstants.efsHorizontal) - e.Delta * SystemInformation.MouseWheelScrollLines / 120
    'End Sub


    'Size
    Private Sub vbnetWaveRender_Resize(ByVal eventsender As System.Object, ByVal eventargs As System.EventArgs) Handles MyBase.Resize
        'SetScroll()
        renderWave()
    End Sub

    'Paint Graphics
    Protected Sub Main_Paint(ByVal sender As Object, ByVal pe As System.Windows.Forms.PaintEventArgs) Handles mainpanel.Paint

        If m_GraphicInfoReady Then
            Dim grfGraphics As Graphics
            grfGraphics = pe.Graphics
            grfGraphics.DrawLine(PaintData.m_oCSD_PEN, PaintData.m_oCSD_LX, PaintData.m_oCSD_LY, PaintData.m_oCSD_SX, PaintData.m_oCSD_SY)
            grfGraphics.DrawLine(PaintData.m_oCHADT_PEN, PaintData.m_oCHADT_LX, PaintData.m_oCHADT_LY, PaintData.m_oCHADT_SX, PaintData.m_oCHADT_SY)
            grfGraphics.DrawLine(PaintData.m_oCHADB_PEN, PaintData.m_oCHADB_LX, PaintData.m_oCHADB_LY, PaintData.m_oCHADB_SX, PaintData.m_oCHADB_SY)
            grfGraphics.DrawLine(PaintData.m_oCMDTT_pen, PaintData.m_oCMDTT_LX, PaintData.m_oCMDTT_LY, PaintData.m_oCMDTT_SX, PaintData.m_oCMDTT_SY)
            grfGraphics.DrawLine(PaintData.m_oCMDTB_pen, PaintData.m_oCMDTB_LX, PaintData.m_oCMDTB_LY, PaintData.m_oCMDTB_SX, PaintData.m_oCMDTB_SY)
            grfGraphics.DrawLine(PaintData.m_oCMDBT_pen, PaintData.m_oCMDBT_LX, PaintData.m_oCMDBT_LY, PaintData.m_oCMDBT_SX, PaintData.m_oCMDBT_SY)
            grfGraphics.DrawLine(PaintData.m_oCMDBB_pen, PaintData.m_oCMDBB_LX, PaintData.m_oCMDBB_LY, PaintData.m_oCMDBB_SX, PaintData.m_oCMDBB_SY)

            If m_FileOpen Then
                If m_bUseThread Then
                    If m_ThreadDone = False Then

                        'MessageBox.Show("Running Render")
                    Else
                        If m_ThreadResultOk = True Then
                            If Not hozScroll.Visible Then
                                grfGraphics.FillRectangle(PaintData.m_WAVENDCoverBrh, PaintData.m_WAVENDCoverRec)
                            End If
                            grfGraphics.DrawPath(PaintData.m_AudioPen, PaintData.m_AudioPathL)
                            grfGraphics.DrawPath(PaintData.m_AudioPen, PaintData.m_AudioPathR)
                        Else
                            MessageBox.Show("Thread Error")
                        End If
                    End If
                Else
                    If Not hozScroll.Visible Then
                        grfGraphics.FillRectangle(PaintData.m_WAVENDCoverBrh, PaintData.m_WAVENDCoverRec)
                    End If
                    grfGraphics.DrawPath(PaintData.m_AudioPen, PaintData.m_AudioPathL)
                    grfGraphics.DrawPath(PaintData.m_AudioPen, PaintData.m_AudioPathR)
                End If
            End If

            grfGraphics.Dispose()
        End If
    End Sub

    'WaveRender
    Private Sub renderWave()
        Dim lx As Integer
        Dim ly As Integer
        Dim lMidy As Integer
        Dim lEnd As Integer
        Dim lAbsSizeY As Integer
        Dim lLastX As Integer
        Dim lLastLeftY As Integer
        Dim lLastRightY As Integer
        Dim lMax As Integer
        Dim lWavEnd As Integer

        Dim iSample As Integer

        Dim bComplete As Boolean
        Dim bRectangles As Boolean

        Dim iWavL() As Short
        Dim iWavR() As Short
        Dim iwav() As Short

        bRectangles = (m_lPixelStep >= 8)

        lx = 0
        lEnd = MyBase.ClientRectangle.Width + m_lPixelStep
        lMidy = (MyBase.ClientRectangle.Height \ 2) - 10
        lAbsSizeY = lMidy / 2

        PaintData.m_oCSD_LX = 0
        PaintData.m_oCSD_LY = lMidy
        PaintData.m_oCSD_SX = lEnd
        PaintData.m_oCSD_SY = lMidy
        PaintData.m_oCSD_PEN = New Pen(m_oColorStereoDivider)
        PaintData.m_oCSD_PEN.Width = m_oStereoDividerLineThickNess
        PaintData.m_oCSD_PEN.DashStyle = m_oStereoDividerLineStyle

        PaintData.m_oCHADT_LX = 0
        PaintData.m_oCHADT_LY = lAbsSizeY
        PaintData.m_oCHADT_SX = lEnd
        PaintData.m_oCHADT_SY = lAbsSizeY
        PaintData.m_oCHADT_PEN = New Pen(m_oColorHalfAmplitudeDivider)
        PaintData.m_oCHADT_PEN.Width = m_oHalfAmplitudeDividerLineThickNess
        PaintData.m_oCHADT_PEN.DashStyle = m_oHalfAmplitudeDividerLineStyle


        PaintData.m_oCHADB_LX = 0
        PaintData.m_oCHADB_LY = lMidy + lAbsSizeY
        PaintData.m_oCHADB_SX = lEnd
        PaintData.m_oCHADB_SY = lMidy + lAbsSizeY
        PaintData.m_oCHADB_PEN = New Pen(m_oColorHalfAmplitudeDivider)
        PaintData.m_oCHADB_PEN.Width = m_oHalfAmplitudeDividerLineThickNess
        PaintData.m_oCHADB_PEN.DashStyle = m_oHalfAmplitudeDividerLineStyle

        PaintData.m_oCMDTT_LX = 0
        PaintData.m_oCMDTT_LY = lAbsSizeY \ 2
        PaintData.m_oCMDTT_SX = lEnd
        PaintData.m_oCMDTT_SY = lAbsSizeY \ 2
        PaintData.m_oCMDTT_pen = New Pen(m_oColorMidDivider)
        PaintData.m_oCMDTT_pen.Width = m_oMidDividerLineThickNess
        PaintData.m_oCMDTT_pen.DashStyle = m_oMidDividerLineStyle

        PaintData.m_oCMDTB_LX = 0
        PaintData.m_oCMDTB_LY = (3 * lAbsSizeY) \ 2
        PaintData.m_oCMDTB_SX = lEnd
        PaintData.m_oCMDTB_SY = (3 * lAbsSizeY) \ 2
        PaintData.m_oCMDTB_pen = New Pen(m_oColorMidDivider)
        PaintData.m_oCMDTB_pen.Width = m_oMidDividerLineThickNess
        PaintData.m_oCMDTB_pen.DashStyle = m_oMidDividerLineStyle

        PaintData.m_oCMDBT_LX = 0
        PaintData.m_oCMDBT_LY = lMidy + lAbsSizeY \ 2
        PaintData.m_oCMDBT_SX = lEnd
        PaintData.m_oCMDBT_SY = lMidy + lAbsSizeY \ 2
        PaintData.m_oCMDBT_pen = New Pen(m_oColorMidDivider)
        PaintData.m_oCMDBT_pen.Width = m_oMidDividerLineThickNess
        PaintData.m_oCMDBT_pen.DashStyle = m_oMidDividerLineStyle

        PaintData.m_oCMDBB_LX = 0
        PaintData.m_oCMDBB_LY = lMidy + (3 * lAbsSizeY) \ 2
        PaintData.m_oCMDBB_SX = lEnd
        PaintData.m_oCMDBB_SY = lMidy + (3 * lAbsSizeY) \ 2
        PaintData.m_oCMDBB_pen = New Pen(m_oColorMidDivider)
        PaintData.m_oCMDBB_pen.Width = m_oMidDividerLineThickNess
        PaintData.m_oCMDBB_pen.DashStyle = m_oMidDividerLineStyle

        If m_FileOpen Then

            If Not hozScroll.Visible Then
                lWavEnd = m_cWAVRead.AudioLength \ m_lSamplePerPixelStep
                PaintData.m_WAVENDCoverRec.X = lWavEnd
                PaintData.m_WAVENDCoverRec.Y = 0
                PaintData.m_WAVENDCoverRec.Width = MyBase.ClientRectangle.Width
                PaintData.m_WAVENDCoverRec.Height = MyBase.ClientRectangle.Height
                PaintData.m_WAVENDCoverBrh = New SolidBrush(m_oNoWaveBackColor)
            End If

            If (m_bSetting) Or (m_cWAVRead.AudioLength = 0) Then
                GoTo PaintCmd
            End If

            If m_lZoom <= 1 Then
                m_cWAVRead.SeekAbsolute(hozScroll.Value)
            Else
                m_cWAVRead.SeekAbsolute(hozScroll.Value * m_lSamplePerPixelStep)
            End If

            lLastX = lx
            lLastLeftY = lAbsSizeY
            lLastRightY = lMidy + lAbsSizeY
            PaintData.m_AudioPathL = New Drawing2D.GraphicsPath
            PaintData.m_AudioPathL.StartFigure()
            PaintData.m_AudioPathR = New Drawing2D.GraphicsPath
            PaintData.m_AudioPathR.StartFigure()
            PaintData.m_AudioPen = New Pen(m_oWaveForeColor)

            bComplete = False

            If m_ThreadDone = False Then
                Exit Sub
            End If

            If m_bUseThread Then
                RaiseEvent RenderStarted()
                m_ThreadDone = False
                m_ThreadResultOk = False
                WaveInfo_handler.BeginInvoke(lLastX, lLastLeftY, lLastRightY, lx, ly, lEnd, lAbsSizeY, bRectangles, lMidy, WaveInfo_callback, Nothing)
            Else
                RaiseEvent RenderStarted()
                Dim Result As WaveData = WaveInfo(lLastX, lLastLeftY, lLastRightY, lx, ly, lEnd, lAbsSizeY, bRectangles, lMidy)
                PaintData.m_AudioPathL = Result.m_AudioPathL
                PaintData.m_AudioPathR = Result.m_AudioPathR
                RaiseEvent RenderFinished()
            End If
        End If

PaintCmd:
        m_GraphicInfoReady = True
        mainpanel.Invalidate()
    End Sub

    'Threading Functions
    'Wave information function
    Private Function WaveInfo(ByVal lLastx As Integer, ByVal lLastLeftY As Integer, ByVal lLastRightY As Integer, _
    ByVal lx As Integer, ByVal ly As Integer, ByVal lEnd As Integer, ByVal lAbsSizeY As Integer, _
    ByVal bRectangles As Boolean, ByVal lMidy As Integer) As WaveData

        Dim iWavL() As Short
        Dim iWavR() As Short
        Dim iwav() As Short
        Dim Output As WaveData
        Dim bComplete As Boolean
        Dim iSample As Integer
        Dim bFirstLoop As Boolean = True

        Output.m_AudioPathL = New Drawing2D.GraphicsPath
        Output.m_AudioPathR = New Drawing2D.GraphicsPath

        Do While ((Not bComplete) And (lx < lEnd))
            bComplete = Not m_cWAVRead.Read()
            ReDim iWavL(m_cWAVRead.ReadbufferSize - 1)
            ReDim iWavR(m_cWAVRead.ReadbufferSize - 1)
            ReDim iwav((m_cWAVRead.ReadbufferSize * 2) - 1)

            Marshal.Copy(m_cWAVRead.ReadBufferPtr, iwav, 0, (m_cWAVRead.ReadbufferSize * 2))
            Dim j As Integer = 0
            For i As Integer = 0 To UBound(iwav)
                iWavL(j) = iwav(i)
                iWavR(j) = iwav(i + 1)
                j = j + 1
                i = i + 1
            Next
            For iSample = 0 To m_cWAVRead.ReadSize - 1 Step m_lSampleStep
                ly = lAbsSizeY + (iWavL(iSample) * lAbsSizeY) / &H8000
                If bFirstLoop = False Then
                    Output.m_AudioPathL.AddLine(lLastx, lLastLeftY, lx, ly)
                End If
                If bRectangles Then
                    Dim recttemp As Drawing.Rectangle
                    recttemp.Height = 5
                    recttemp.Width = 5
                    recttemp.X = lx - 2
                    recttemp.Y = ly - 2
                    If bFirstLoop = False Then
                        Output.m_AudioPathL.AddRectangle(recttemp)
                    End If
                End If
                lLastLeftY = ly
                ly = lMidy + lAbsSizeY + (iWavR(iSample) * lAbsSizeY) / &H8000
                If bFirstLoop = False Then
                    Output.m_AudioPathR.AddLine(lLastx, lLastRightY, lx, ly)
                End If
                If bRectangles Then
                    Dim recttemp As Drawing.Rectangle
                    recttemp.Height = 5
                    recttemp.Width = 5
                    recttemp.X = lx - 2
                    recttemp.Y = ly - 2
                    If bFirstLoop = False Then
                        Output.m_AudioPathR.AddRectangle(recttemp)
                    End If
                End If
                lLastRightY = ly
                lLastx = lx
                If (iSample Mod m_lSamplePerPixelStep) = 0 Then
                    lx = lx + m_lPixelStep
                End If
                If lx >= lEnd Then
                    Exit For
                End If
                bFirstLoop = False
            Next
        Loop
        ReDim iWavL(1)
        ReDim iWavR(1)
        ReDim iwav(1)
        Return Output
    End Function
    'Thread CallBack for waveinfo function
    Private Sub GetWaveInfo_callback(ByVal ar As IAsyncResult)
        Try
            Dim result As WaveData
            result = WaveInfo_handler.EndInvoke(ar)
            UpdateUI_Worker("Task Complete", result)
        Catch ex As Exception
            Dim msg As String
            msg = "Error: " & ex.Message
            UpdateUI_Worker(msg, Nothing)
        End Try

    End Sub
    'Thread side update sub
    Private Sub UpdateUI_Worker(ByVal StatusMsg As String, ByVal result As WaveData)
        If Me.InvokeRequired Then
            Dim handler As New UpdateUIHandler(AddressOf UpdateUI_Local)
            Dim args() As Object = {StatusMsg, result}
            Me.BeginInvoke(handler, args)
        Else
            UpdateUI_Local(StatusMsg, result)
        End If
    End Sub
    'Main program update sub
    Private Sub UpdateUI_Local(ByVal StatusMsg As String, ByVal result As WaveData)
        If StatusMsg = "Task Complete" Then
            m_ThreadDone = True
            m_ThreadResultOk = True
            PaintData.m_AudioPathL = result.m_AudioPathL
            PaintData.m_AudioPathR = result.m_AudioPathR
            m_GraphicInfoReady = True
            mainpanel.Invalidate()
            RaiseEvent RenderFinished()
        Else
            m_ThreadDone = True
            m_ThreadResultOk = False
        End If
    End Sub


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


Written By
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.

Comments and Discussions