locked
System.NullReferenceException was unhandled trying to read RIFF file header using FileGetObject() RRS feed

  • Question

  •     Structure RIFFHeader
            <VBFixedString(4)> Public RIFFtag As String ' "RIFF"
            Public Filesize As Long
            <VBFixedString(4)> Public WAVtag As String  ' "WAVE"
            <VBFixedString(4)> Public FMTtag As String  ' "fmt "
            Public FMTsize As Long
            Public CompressType As Integer
            Public Channels As Integer
            Public SampleRate As Long                   ' Samples per sec
            Public BytesPerSecond As Long               ' = SampleRate * BytesPerSample
            Public BytesPerSample As Integer
            Public BitsPerSample As Integer
        End Structure

    In a function to read the RIFF header...

       Dim WaveHeader As New RIFFHeader
    
       FileOpen(1, WaveFile, OpenMode.Binary)
    
       FileGetObject(1, WaveHeader)

    I'm getting an error

    System.NullReferenceException was unhandled
      Message=Object reference not set to an instance of an object.
      Source=Microsoft.VisualBasic
      StackTrace:
           at Microsoft.VisualBasic.FileSystem.FileGetObject(Int32 FileNumber, Object& Value, Int64 RecordNumber)
           at Time.Radio.OnTheAir.WavLength(String WaveFile) in C:\Users\jhart\Personal\Time.Radio\Time.Radio\OnTheAir.vb:line 96
           at Time.Radio.OnTheAir.Ticker_Tick(Object sender, EventArgs e) in C:\Users\jhart\Personal\Time.Radio\Time.Radio\OnTheAir.vb:line 45
           at System.Windows.Forms.Timer.OnTick(EventArgs e)
           at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
           at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
           at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
           at Time.Radio.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: 
    

    I don't know how to fix this.
    Wednesday, August 29, 2012 8:02 PM

Answers

  • Cut down copy of your code for anyone who might follow in my footsteps

    Declarations:

        Const _Byte As Integer = 1
        Const _word As Integer = 2
        Const _dword As Integer = 4
        Const _qword As Integer = 8
    
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
    
        Public Enum Format As UInt16
            Standard = 1
        End Enum
    
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
    
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
    
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Public Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
    
        Public Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
    
        Public Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
    
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
    Logic:
    Public Sub OpenFile(FileName As String)
            Try
                If Not My.Computer.FileSystem.FileExists(FileName) Then
                    Throw New Exception("File Does Not Exist!")
                End If
    
                Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
    
                'Get Header
    
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0)
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
    
                'Get FormatSubChunk
    
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
    
                'Get DataSubChunck
    
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch
                Throw New Exception("File Is Invalid or corrupt!")
            End Try
        End Sub
    
        Private Function GetDataFromByteArray(ByVal ByteArray As Byte(), ByVal BlockOffset As Long, ByVal RangeStartOffset As Long, ByVal DataLength As Long) As Byte()
            On Error Resume Next
    
            Dim AnswerL As New List(Of Byte)
            Dim Answer(0 To CInt((DataLength - 1))) As Byte
    
            Dim CurrentOffset As Long
    
            For I = 0 To UBound(ByteArray)
                CurrentOffset = BlockOffset + I
    
                If CurrentOffset >= RangeStartOffset And CurrentOffset <= RangeStartOffset + DataLength Then
                    AnswerL.Add(ByteArray(I))
                End If
            Next
    
            Dim Count As Integer = 0
    
            For Each bt As Byte In AnswerL
                Answer(Count) = bt
                Count += 1
            Next
    
            GetDataFromByteArray = Answer
        End Function

    The length of the sound file in seconds:

        Function WavLength(ByVal WaveFile As String) As Long
            OpenFile(WaveFile)
    
            WavLength = Me.FileDataSubChunk.Subchunk2Size / Me.FileFormatSubChunk.ByteRate ' length in seconds
        End Function



    Responsibilities first...

    • Marked as answer by John L Hart IV Saturday, September 1, 2012 2:08 AM
    Wednesday, August 29, 2012 9:02 PM

All replies

  • Please try the openfile method in my class I wrote, you can then access the individual structures of the wave file.

    Public Class Wave
        'By Paul Ishak
        'WAVE PCM soundfile format 
        'The Canonical WAVE file format
        'As Described Here: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
        Const _Byte As Integer = 1
        Const _word As Integer = 2
        Const _dword As Integer = 4
        Const _qword As Integer = 8
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
        Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
        Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
        Public Sub OpenFile(FileName As String)
            Try
                If Not InStr(LCase(FileName), ".wav") Then Throw New Exception("Invalid File Extension Specified!")
                If Not My.Computer.FileSystem.FileExists(FileName) Then Throw New Exception("File Does Not Exist!")
                Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0)
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch
                Throw New Exception("File Is Invalid or corrupt!")
            End Try
        End Sub
        Public Sub SetDirectBytes(FileBytes() As Byte)
            Try
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0)
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch ex As Exception
                ' Throw New Exception("File Is Invalid or corrupt!")
                MsgBox(ex.StackTrace)
            End Try
        End Sub
     
        Public Function GetBytes() As Byte()
            Dim Results As Byte() = Nothing
            Results = CombineArrays(FileHeader.ChunkID, BitConverter.GetBytes(FileHeader.ChunkSize))
            Results = CombineArrays(Results, FileHeader.Format)
            Results = CombineArrays(Results, FileFormatSubChunk.Subchunk1ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.Subchunk1Size))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.AudioFormat))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.NumChannels))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.SampleRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.ByteRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BlockAlign))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BitsPerSample))
            Results = CombineArrays(Results, FileDataSubChunk.Subchunk2ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileDataSubChunk.Subchunk2Size))
            Results = CombineArrays(Results, FileDataSubChunk.Data)
            Return Results
        End Function
        Function CombineArrays(Array1() As Byte, Array2() As Byte) As Byte()
            Dim AllResults(Array1.Length + Array2.Length - 1) As Byte
            Array1.CopyTo(AllResults, 0)
            Array2.CopyTo(AllResults, Array1.Length)
            Return AllResults
        End Function
        Private Function GetDataFromByteArray(ByVal ByteArray As Byte(), ByVal BlockOffset As Long, ByVal RangeStartOffset As Long, ByVal DataLength As Long) As Byte()
            On Error Resume Next
            Dim AnswerL As New List(Of Byte)
            Dim Answer(0 To CInt((DataLength - 1))) As Byte
            Dim CurrentOffset As Long
            For I = 0 To UBound(ByteArray)
                CurrentOffset = BlockOffset + I
                If CurrentOffset >= RangeStartOffset Then
                    If CurrentOffset <= RangeStartOffset + DataLength Then
                        AnswerL.Add(ByteArray(I))
                    End If
                End If
            Next
            Dim count As Integer = -1
            For Each bt As Byte In AnswerL
                count = count + 1
                Answer(count) = bt
            Next
            Return Answer
        End Function
        Public Function ViewBinary(Optional HexOffsets As Boolean = True) As String
            Dim asc As New StringBuilder
            Dim Hex As New StringBuilder
            Dim result As New StringBuilder
            Dim MB As Byte() = Me.GetBytes
            Select Case HexOffsets
                Case True
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  " & "    " & "0123456789ABCDEF" & vbCrLf & vbCrLf)
                Case False
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  " & "    " & "0123456789012345" & vbCrLf & vbCrLf)
            End Select
            Dim Count As Integer = -16
            For Each B As Byte In MB
                Count = Count + 1
                Hex.Append(B.ToString("X2") & "  ")
                If B > 32 And B < 128 Then
                    asc.Append(Chr(B))
                Else
                    asc.Append(".")
                End If
                If Count Mod 16 = 0 Then
                    Select Case HexOffsets
                        Case True
                            result.Append(Count.ToString("X").PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                        Case False
                            result.Append(Count.ToString.PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                    End Select
                    Hex.Remove(0, Hex.ToString.Length)
                    asc.Remove(0, asc.ToString.Length)
                End If
            Next
            Dim Counts As String = String.Empty
            Select Case HexOffsets
                Case True
                    Counts = (Count + (16 - (Count Mod 16))).ToString("X").PadLeft(8, "0").ToString
                Case False
                    Counts = (Count + (16 - (Count Mod 16))).ToString.PadLeft(8, "0").ToString
            End Select
            Dim H As Integer = 64 - Hex.ToString.Length
            Dim FinalHex As String = Hex.ToString & Space(H)
            result.Append(Counts & "    " & FinalHex & "    " & asc.ToString & vbCrLf)
            Return result.ToString
        End Function
        Public Shared Function SelectWavData(PictureBox As PictureBox, SelectionColor As Color, Origin As Integer, TextColor As Color, Optional SetLocal As Integer = -1) As SelectedData
            Dim LocalMousePosition As Point = PictureBox.PointToClient(Cursor.Position)
            Dim BM As New Bitmap(PictureBox.Size.Width, PictureBox.Size.Height)
            Dim gr As Graphics = Graphics.FromImage(BM)
            Dim Pen As New Pen(Brushes.Green, 1)
            If SetLocal > -1 Then
                LocalMousePosition.X = SetLocal
            End If
            If LocalMousePosition.X > PictureBox.ClientRectangle.Width Then
                LocalMousePosition.X = PictureBox.ClientRectangle.Width
            End If
            If LocalMousePosition.X < 0 Then
                LocalMousePosition.X = 0
            End If
            Dim Line1point1 As New Point(LocalMousePosition.X, 0)
            Dim Line1point2 As New Point(LocalMousePosition.X, PictureBox.ClientRectangle.Height)
            Dim Line2point1 As New Point(Origin, 0)
            Dim Line2point2 As New Point(Origin, PictureBox.ClientRectangle.Height)
            Dim Poly(3) As Point
            Poly(0) = Line1point1
            Poly(1) = Line2point1
            Poly(2) = Line2point2
            Poly(3) = Line1point2
            If Origin = LocalMousePosition.X = False Then
                gr.FillPolygon(New SolidBrush(SelectionColor), Poly)
                '  gr.DrawPolygon(New Pen(Brushes.Yellow, 2), Poly)
            End If
            PictureBox.Image = BM
            Select Case LocalMousePosition.X > Origin
                Case True
                    gr.DrawString("Selected Range(" & Origin & "-" & LocalMousePosition.X & ")", New Font("Consolas", 8), New SolidBrush(TextColor), 1, 1)
                    Return New SelectedData(Origin, LocalMousePosition.X)
                Case Else
                    gr.DrawString("Selected Range(" & LocalMousePosition.X & "-" & Origin & ")", New Font("Consolas", 8), New SolidBrush(TextColor), 1, 1)
                    Return New SelectedData(LocalMousePosition.X, Origin)
            End Select
        End Function
        Public Shared Sub DrawWave(PictureBox As PictureBox, GridSize As Integer, CurrentWaveFile As Wave, GridColor As Color, SineColor As Color)
            Dim Bytes As Byte() = CurrentWaveFile.FileDataSubChunk.Data
            Dim Data(0 To UBound(Bytes)) As UInt16
            Dim Count As Integer = -1
            For Each b As Byte In Bytes
                Count = Count + 1
                Data(Count) = CType(b, UInt16)
            Next
     
            Dim InvertedData(0 To UBound(Bytes)) As UInt32
            For I = 0 To UBound(Data)
                InvertedData(I) = ((255 - Data(I)) \ 2) + ((PictureBox.Height - (255 \ 2)) \ 2)
            Next
            Dim Points As New List(Of Point)
            For I = 0 To UBound(InvertedData)
                Dim Point As New Point(InvertedData(I), I + 1)
                Points.Add(Point)
            Next
            Dim PointsArr() As Point = Points.ToArray
            Dim BM As New Bitmap(PictureBox.Height, PictureBox.Width)
            Dim gr As Graphics = Graphics.FromImage(BM)
            Dim Pen As New Pen(SineColor, 1)
            Dim pen2 As New Pen(Brushes.Red, 3)
            Dim pen3 As New Pen(GridColor, 1)
            For I = 1 To PictureBox.Width Step GridSize
                gr.DrawLine(pen3, New Point(0, I), New Point(PictureBox.Height, I))
                gr.DrawLine(pen3, New Point(I, 0), New Point(I, PictureBox.Width))
            Next
            gr.DrawLines(Pen, PointsArr)
            gr.DrawLine(pen2, New Point(0, PictureBox.ClientRectangle.Width / 2), New Point(PictureBox.Height, PictureBox.ClientRectangle.Width / 2))
            gr.DrawLine(pen3, New Point(0, PictureBox.ClientRectangle.Width / 2), New Point(PictureBox.Height, PictureBox.ClientRectangle.Width / 2))
            BM.RotateFlip(RotateFlipType.Rotate270FlipNone)
            PictureBox.BackgroundImage = BM
        End Sub
        Public Structure SelectedData
            Public SelectionStart As Integer
            Public SelectionEnd As Integer
            Sub New(SelectionStart As Integer, SelectionEnd As Integer)
                Me.SelectionStart = SelectionStart
                Me.SelectionEnd = SelectionEnd
            End Sub
        End Structure
        Sub New(Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileHeader.ChunkSize = 4 + (8 + FileFormatSubChunk.Subchunk1Size) + (8 + FileDataSubChunk.Subchunk2Size)
            FileHeader.Format = Encoding.ASCII.GetBytes("WAVE")
            FileFormatSubChunk.Subchunk1ID = Encoding.ASCII.GetBytes("fmt ")
            FileFormatSubChunk.AudioFormat = Options.AudioFormat
            FileFormatSubChunk.SampleRate = Options.SampleRate
            FileFormatSubChunk.ByteRate = Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileFormatSubChunk.BlockAlign = Options.NumberOfChannels * Options.BitsPerSample / 8
            FileDataSubChunk.Subchunk2ID = Encoding.ASCII.GetBytes("data")
            FileDataSubChunk.Data = Options.Data
        End Sub
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
        Public Enum Format As UInt16
            Standard = 1
        End Enum
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    End Class


    If you want something you've never had, you need to do something you've never done.

    • Proposed as answer by Mike Feng Friday, August 31, 2012 7:49 AM
    Wednesday, August 29, 2012 8:07 PM
  • I don't want to read the entire file, I'm just trying to determine the playing length - as follows.

    WavLength = WaveHeader.Filesize \ WaveHeader.BytesPerSecond ' length in seconds


    Responsibilities first...

    Wednesday, August 29, 2012 8:14 PM
  • I don't want to read the entire file, I'm just trying to determine the playing length - as follows.

    WavLength = WaveHeader.Filesize \ WaveHeader.BytesPerSecond ' length in seconds


    Responsibilities first...


    If you use the open file method in my class, you can then access any element of the riff wave header. You can look and see how I am populating that field if you somehow think loading the file will consume too many resources. But the fields you are looking for are populated(individually) when you load my class.

    If you want something you've never had, you need to do something you've never done.

    Wednesday, August 29, 2012 8:19 PM
  • The code you offered worked... got me past my problem (thanks)

     WavLength = Me.FileDataSubChunk.Subchunk2Size / Me.FileFormatSubChunk.ByteRate ' length in seconds

    Yields the length of the audio in seconds


    Responsibilities first...

    • Proposed as answer by Mike Feng Friday, August 31, 2012 7:49 AM
    Wednesday, August 29, 2012 8:59 PM
  • The strange thing is that when I used the FileGet() method instead - the NullReferenceException went away and I was able to pull something (admittedly garbage) from the file... Why was FileGetObject upset with me?...

    Responsibilities first...

    Wednesday, August 29, 2012 8:59 PM
  • Cut down copy of your code for anyone who might follow in my footsteps

    Declarations:

        Const _Byte As Integer = 1
        Const _word As Integer = 2
        Const _dword As Integer = 4
        Const _qword As Integer = 8
    
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
    
        Public Enum Format As UInt16
            Standard = 1
        End Enum
    
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
    
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
    
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Public Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
    
        Public Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
    
        Public Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
    
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
    Logic:
    Public Sub OpenFile(FileName As String)
            Try
                If Not My.Computer.FileSystem.FileExists(FileName) Then
                    Throw New Exception("File Does Not Exist!")
                End If
    
                Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
    
                'Get Header
    
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0)
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
    
                'Get FormatSubChunk
    
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
    
                'Get DataSubChunck
    
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch
                Throw New Exception("File Is Invalid or corrupt!")
            End Try
        End Sub
    
        Private Function GetDataFromByteArray(ByVal ByteArray As Byte(), ByVal BlockOffset As Long, ByVal RangeStartOffset As Long, ByVal DataLength As Long) As Byte()
            On Error Resume Next
    
            Dim AnswerL As New List(Of Byte)
            Dim Answer(0 To CInt((DataLength - 1))) As Byte
    
            Dim CurrentOffset As Long
    
            For I = 0 To UBound(ByteArray)
                CurrentOffset = BlockOffset + I
    
                If CurrentOffset >= RangeStartOffset And CurrentOffset <= RangeStartOffset + DataLength Then
                    AnswerL.Add(ByteArray(I))
                End If
            Next
    
            Dim Count As Integer = 0
    
            For Each bt As Byte In AnswerL
                Answer(Count) = bt
                Count += 1
            Next
    
            GetDataFromByteArray = Answer
        End Function

    The length of the sound file in seconds:

        Function WavLength(ByVal WaveFile As String) As Long
            OpenFile(WaveFile)
    
            WavLength = Me.FileDataSubChunk.Subchunk2Size / Me.FileFormatSubChunk.ByteRate ' length in seconds
        End Function



    Responsibilities first...

    • Marked as answer by John L Hart IV Saturday, September 1, 2012 2:08 AM
    Wednesday, August 29, 2012 9:02 PM
  • The strange thing is that when I used the FileGet() method instead - the NullReferenceException went away and I was able to pull something (admittedly garbage) from the file... Why was FileGetObject upset with me?...

    Responsibilities first...

    Actually, check this out - Maybe you can retrace your steps?

    http://msdn.microsoft.com/en-us/library/y1swwyc4%28v=vs.90%29.aspx


    If you want something you've never had, you need to do something you've never done.


    • Edited by Paul Ishak Wednesday, August 29, 2012 9:19 PM
    • Proposed as answer by Mike Feng Friday, August 31, 2012 7:48 AM
    Wednesday, August 29, 2012 9:17 PM
  • I'm not sure that cutting down my original answer constitutes a unique and different answer. Either way glad my answer solved your poblem.

    If you want something you've never had, you need to do something you've never done.


    • Edited by Paul Ishak Saturday, September 1, 2012 2:30 AM
    Saturday, September 1, 2012 2:21 AM