Is my audio normalization code correct?

147 views Asked by At

I want to normalize an audio file to the maximum.

To do that, I'm using this code:

Dim iHighestDataValue As Integer
Dim iLowestDataValue As Integer

Dim i&
For i = 1 To dc.wavedatasize / 2
    Get #iFile, , DataValue(i) ' reads data value into array

    If DataValue(i) > iHighestDataValue Then
        iHighestDataValue = DataValue(i)
    End If

    If DataValue(i) < iLowestDataValue Then
        iLowestDataValue = DataValue(i)
    End If
Next

Dim sngVolumeLevel As Single
sngVolumeLevel = ((iHighestDataValue + (iLowestDataValue * -1)) / 2) / 32767

It works fine for almost all files, but for one file, the last line fails.

iHighestDataValue is 13445, iLowestDataValue is -21940.

I guess something is wrong in the last line. Is it just an error that occurs with VB6 because it can't handle this (correct) calculation, or did I introduce any erros?

When I put the last line into separate calculations, it works fine:

Dim sngHighest As Single
If iHighestDataValue > 32767 Then
    sngHighest = 32767
Else
    sngHighest = iHighestDataValue
End If

Dim sngLowest As Single
If iLowestDataValue < -32767 Then
    sngLowest = -32767
Else
    sngLowest = iLowestDataValue
End If
sngLowest = sngLowest * -1

Dim sngVolumeLevel As Single
sngVolumeLevel = (sngHighest + sngLowest) / 2
sngVolumeLevel = (sngVolumeLevel / 32767)

Thank you!

ps: Here is the last, normalizing part of the function:

Dim tem As Long

For i = 1 To dc.wavedatasize / 2
    tem = CLng(DataValue(i) * 1 / sngVolumeLevel)
    If tem > 32767 Then
        tem = 32767 ' prevents integer overflow error
    End If
    If tem < -32767 Then
        tem = -32767 ' prevents integer overflow error
    End If
    DataValue(i) = CInt(tem) ' changes data value
Next i

wh.riffdatasize = dc.wavedatasize + Len(wh) + Len(wf) 'Riff chunk size may be different
' beacause some input wave files may contain information chunk which is not written in output file

iFile = FreeFile

Kill uPath 'Delete the original / source file. We will overwrite it with the normalized version of this file

Open uPath For Binary As #iFile
Put #iFile, , wh ' writes the wave header
Put #iFile, , wf ' writes wave format
Put #iFile, , dc ' writes the 8 byte string "data" and wave dataa size

For i = 1 To dc.wavedatasize / 2
    Put #iFile, , DataValue(i) ' writes data value in ouput file
Next i

Close #iFile
1

There are 1 answers

0
Hartmut Pfitzinger On BEST ANSWER

It's not correct because it produces a significant amount of clipping.

Instead of:

sngVolumeLevel = ((iHighestDataValue + (iLowestDataValue * -1)) / 2) / 32767

Better do this:

If iHighestDataValue >= -iLowestDataValue Then
    sngVolumeLevel = iHighestDataValue / 32767.
Else
    sngVolumeLevel = iLowestDataValue / -32768.
End If