Fog Creek Software
Discussion Board




Comparing two sound files


Is there a tool I can use to compare two sound files, say .mid files? The reason I ask is when I send a .mid file from a client end to a server end on a socket on Windows, the file that reaches at the server has the same size but seems to have corrupt data. I checked using WinDiff that comes with Visual Studio 6 Enterprise Edition, but I couldn't make head or tail out of it.

What I am doing is:

(1) Package the sound file into a byte array
(2) Insert a four byte header containing the size of the file into the byte array
(3) Send it on a socket

Here's the relevant code snippet:

[CLIENT]

Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long

Private Const SERVER_NAME As String = "Satya"
Private Const SERVER_PORT As Long = 9000
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)


Private Sub cmdSend_Click()

Dim temp() As Byte
Dim FileData() As Byte
Dim FileName As String
Dim FileSize As Long

If w.State <> sckConnected Then Exit Sub

FileName = App.Path & "\a.mid"
FileSize = FileLen(FileName)

ReDim temp(0 To FileLen(FileName) - 1)
Call ReadFile(FileName, temp())
ReDim FileData(0 To UBound(temp) + 4)
CopyMemory FileData(0), ByVal VarPtr(FileSize), 4
CopyMemory FileData(4), temp(0), UBound(temp) + 1

w.SendData FileData

End Sub

Public Sub ReadFile(ByVal FileName As String, ByRef FileData() As Byte)

Dim IntFile As Integer
Dim pos As Long
    IntFile = FreeFile
    Open FileName For Binary As IntFile
    Get #IntFile, , FileData()
    Close #IntFile
End Sub
[/CLIENT]

Okay, this is just rough work so spare your puristic comments on coding style. I know it is sub-optimal because right now I am just scribbling stuff.

[SERVER]

Dim NumUsers As Long
Dim ClientIndex As Long

Dim FileData() As Byte
Dim FileSize As Long
Dim BytesRead As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub w_DataArrival(Index As Integer, ByVal bytesTotal As Long)

Dim TempData() As Byte
Dim StrData As String
Dim BytesRemaining As Long
Dim PrevUbound As Long

    w(Index).GetData StrData
   
    If Trim(StrData) = vbNullString Then Exit Sub
    If Left(StrData, 5) = "Meta:" Then
        If Not ClientExists(StrData) Then lstOnlineUsers.AddItem Mid(StrData, 6): lstOnlineUsers.ItemData(LngCounter) = ClientIndex
    Else
       
        TempData = StrConv(StrData, vbFromUnicode)
       
        If BytesRead = 0 Then
            'Means that this is the first packet, read the file size
            CopyMemory ByVal VarPtr(FileSize), TempData(0), 4
            Erase FileData
            ReDim FileData(0 To UBound(TempData) - 4)
            CopyMemory FileData(0), TempData(4), UBound(TempData) + 1 - 4
            BytesRead = bytesTotal
        Else
            BytesRemaining = (FileSize + 4 - BytesRead)
            'This is a continuation of a previous message, append
            If bytesTotal <= BytesRemaining Then
                PrevUbound = UBound(FileData)
                ReDim FileData(0 To PrevUbound + bytesTotal)
                CopyMemory FileData(PrevUbound + 1), TempData(0), UBound(TempData) + 1
                BytesRead = BytesRead + bytesTotal
            Else
            'This is a composite message, wherein the first part is a remnant from a previous
            'message and the remaining part is the start of a new message
            'LATER
            End If
        End If
       
        If BytesRead = FileSize + 4 Then
            Call WriteFile(App.Path & "\b.mid", FileData())
            BytesRead = 0
            Erase FileData
        End If
    End If
   
    Debug.Assert BytesRead < 30000
End Sub
[/SERVER]

The file I am sending just to test my code is a midi file of 57.5K bytes. When I receive the byte array at the server, it is all okay except when the size crosses over 36,000 bytes, it starts to corrupt the data in the byte array. The new file saved is exactly of the same size as the one the client send but cannot be played, has no header containing the time length etc.

Any tool I could use? Or I might be missing something here. Any kind of help greatly appreciated.

Sathyaish Chakravarthy
Monday, June 07, 2004

MD5 and compare hashes. If they're different, the files aren't the same.

Philo

Philo
Monday, June 07, 2004

Don't tell me Windows has no cmp !?

Sending sound files over sockets works the same as sending any other type of file. Ditto for comparing sound files.

"diff" style programms won't be much help with sound files because they're tailored toward finding differences in text files, line by line (no lines in binary files...)

If you're expecting the two binary files to be very similar --maybe just a couple of bytes out of sync due to the padding you added--, it might help converting them to hex and then using diff or two windows side-by-side to compare the files.

Can't read the code, sorry way to much to handel without proper formatting/editor/syntax highlighting.

  -tim

a2800276
Monday, June 07, 2004


Sorry for the bother, guys. I reran the code in debug mode a several times more to find out I was committing a silly mistake. I'd left out the "Preserve" keyword in the Redim statement while redimensioning my array in the following line,

                ReDim FileData(0 To PrevUbound + bytesTotal)

and that caused the array to loose its previous contents and have all vbNullChars (0s).

What's MD5, BTW?

Sathyaish Chakravarthy
Monday, June 07, 2004

Google, unfortunately, is a verb. MD --> Message Digest.

Feynman's Electron
Monday, June 07, 2004

http://www.google.co.uk/search?sourceid=mozclient&ie=utf-8&oe=utf-8&q=MD5

Simon Lucy
Monday, June 07, 2004


This MD5 hex is yummy. Dellllicious...

Thanks for the link. Excellent!

Sathyaish Chakravarthy
Monday, June 07, 2004

*  Recent Topics

*  Fog Creek Home