19 May '13 - 11:05 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1] 2  All
  Reply  |  Print  
Author Topic: Normalizing audio tracks  (Read 11684 times)
Schlichter
Guest
« on: 27 Nov '06 - 08:05 »
Reply with quoteQuote

Is there any possibility to normalize audio tracks, i.e. setting their peak level to 100% or 0 dB, without changing the channel's volume?

Thanks for your suggestions

H.Schlichter
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #1 on: 27 Nov '06 - 15:35 »
Reply with quoteQuote

If you want to normalize a track, you'll need to pre-scan it to find the peak (which could take a while), and then adjust the gain/volume accordingly during playback, eg. using a DSP function. Assuming 16-bit sample data, something like this...

int GetPeak(DWORD channel)
{
int a, c, peak=0;
short buf[50000];
BASS_ChannelSetPosition(channel, 0); // make sure to start from the start
while (BASS_ChannelIsActive(channel)) { // not reached the end yet
c=BASS_ChannelGetData(channel, buf, sizeof(buf)); // decode some data
for (a=0; a<c/2; a++) // scan the data for the peak
if (peak<abs(buf)) peak=abs(buf); // new highest peak
}
if (peak>32767) peak=32767;
return peak;
}

void CALLBACK NormalizeDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, DWORD peak)
{
short *s=buffer;
int a;
for (a=0; a<length/2; a++)
s[a]=s[a]*32767/peak; // apply normalization
}

...

HSTREAM decoder=BASS_StreamCreateFile(FALSE, filename, 0, 0, BASS_STREAM_DECODE); // create decoder to pre-scan
int peak=GetPeak(decoder); // get the peak
BASS_StreamFree(decoder); // free the decoder

stream=BASS_StreamCreateFile(FALSE, filename, 0, 0, 0); // create the playback channel
BASS_ChannelSetDSP(stream, NormalizeDSP, peak, 0); // set the normalization DSP on it
BASS_ChannelPlay(stream, 0); // start playing

Another (slightly simpler) option is to use BASS_ChannelGetLevel to find the peaks, instead of BASS_ChannelGetData.

int GetPeak(DWORD channel)
{
int peak=0;
BASS_ChannelSetPosition(channel, 0); // make sure to start from the start
while (BASS_ChannelIsActive(channel)) { // not reached the end yet
DWORD level=BASS_ChannelGetLevel(channel);
int left=LOWORD(level), right=HIWORD(level); // extract left & right peaks
if (peak<left) peak=left;
if (peak<right) peak=right;
}
if (peak>32767) peak=32767;
return peak;
}
Logged
Schlichter
Guest
« Reply #2 on: 27 Nov '06 - 17:38 »
Reply with quoteQuote

Pretty much simple, if one knows...
Thank you very much for your support.

H.Schlichter
Logged
se
Posts: 22


« Reply #3 on: 28 Nov '06 - 20:00 »
Reply with quoteQuote

Sorry for this question if it seems stupid.

I did understand that normalizing a channel can be done in reference to another channel.
for example 2 audio files played one after the other, and we don't want to have one played with a higher level than the first one.

In this sample you are just referring to a unique file, to normalize it.

Do I miss the point on the absolute level in dB?

best
and thank you for all the new updates I didn't play with! very exciting indeed!

Logged
Schlichter
Guest
« Reply #4 on: 29 Nov '06 - 08:20 »
Reply with quoteQuote

The highest possible (digital) level of an audio track is 32767, equivalent to 0 dB. The peak level of any audio track is measured to this value.

Naturally you can normalize an audio track to another one.

H.Schlichter
Logged
prl
Guest
« Reply #5 on: 24 Jan '07 - 11:42 »
Reply with quoteQuote

I'm having problem with the System.Windows.Forms.Control.Right() property. It turns out to be a read only and can't be initialized to any value, in this example HiWord(level). How do I solve this problem?  Smiley
Logged
radio42
Posts: 4012


« Reply #6 on: 24 Jan '07 - 16:37 »
Reply with quoteQuote

Don't know what you are doing...but...the "System.Windows.Forms.Control.Right":
gets the distance, in pixels, between the right edge of the control and the left edge of its container's client area.
So why would you set that to a level value.

The value of the "Right" property is equal to the sum of the "Left" property value and the "Width" property value.
The "Right" property is read-only. You can change this property value indirectly by changing the value of the "Left" or "Width" properties or calling the "SetBounds", "SetBoundsCore", "UpdateBounds", or "SetClientSizeCore" methods.

Or take a look to the .Net documentation...as I copied the above text from there :-)
Logged
prl
Guest
« Reply #7 on: 25 Jan '07 - 01:58 »
Reply with quoteQuote

thank you so much radio. I'm really not that good in programming but I'll try to work it out. :-)
Logged
prl
Guest
« Reply #8 on: 25 Jan '07 - 02:13 »
Reply with quoteQuote

thank you so much radio. I'm really not that good in programming but I'll try to work it out. :-)

Also, I overlooked the right in the example above. I thought it was a SystemForms.Control object. All along it was just a variable declared as an int. hehehe... sorry.
Logged
Nicolás
Guest
« Reply #9 on: 27 Oct '08 - 18:50 »
Reply with quoteQuote



Hi, i need some example for normalizing audio but in VB please!!..

Realy thanks!
Logged
IsraelMS
Posts: 13


« Reply #10 on: 3 Nov '08 - 12:54 »
Reply with quoteQuote

Hello members! Sorry my english, I'm braziliam.

I need an example in Delphi. please help me.

Thanks.

Israel
Logged
Chris
Posts: 1501


« Reply #11 on: 3 Nov '08 - 16:01 »
Reply with quoteQuote

try this
function ScanPeak(const FileName: string): integer;
var
  a, c, Peak: Integer;
  buf: array[0..20000] of SmallInt;
  Channel: DWORD;
begin
  peak := 0;
  Bass_SetDevice(0);
  Channel := BASS_StreamCreateFile(false, PChar(FileName), 0, 0, BASS_STREAM_DECODE);
  if Channel = 0 then
    exit;
  while (BASS_ChannelIsActive(channel) <> 0) do
  begin
    c := BASS_ChannelGetData(channel, @buf, 40000);
    c := c div 2;
    for a := 0 to c do
      if (peak < Abs(buf[a])) then
peak := abs(buf[a]);
  end;
  BASS_StreamFree(channel);
  Result := Peak;
end;

Chris
Logged
Nicolás
Guest
« Reply #12 on: 24 Nov '08 - 06:05 »
Reply with quoteQuote

Hi, i need help, i'm programming this in VB.net, but i have the "peak value" that work's good but when i try to put this line;:

            Bass.BASS_ChannelSetDSP(strm, NormalizeDSP, peak, 0)

I haven't the NormalizeDSP function in VB, somebody can help me??

¿¿¿¿¿NormalizeDSP in VB?Huh??

¿¿¿ void CALLBACK NormalizeDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, DWORD peak) Huh

What is handle,*buffer, etc.  please HELP!!  Thanks
Logged
radio42
Posts: 4012


« Reply #13 on: 24 Nov '08 - 08:14 »
Reply with quoteQuote

Here is a VB.Net translation of Ian's original NormalizeDSP code:
Private _peakValue As Integrer = 1
Private _sampleData As Short() = Nothing

' a DSP callback - which will apply a gain factor
Private Sub NormalizeDSP(handle As Integer, channel As Integer,
                   buffer As IntPtr, length As Integer, user As IntPtr)
  If _peakValue = 1f Or length = 0 Or buffer = IntPtr.Zero Then
      Return
   End If

  ' length is in bytes, so the number of 16-bit values to process is length/1
  Dim l2 As Integer = length / 2

  ' increase the data buffer as needed
  If _sampleData Is Nothing Or _sampleData.Length < l2 Then
    _sampleData = New Single(l2) {}
  End If

  ' copy from unmanaged to managed memory
  Marshal.Copy(buffer, _sampleData, 0, l2)

  ' apply the gain, assuming 16-bit (no clipping)
  Dim a As Integer
  For a = 0 To l2 - 1
    _sampleData(a) = _sampleData(a) * 32737/_peakValue
  Next a

  ' copy back from unmanaged to managed memory
  Marshal.Copy(_sampleData, 0, buffer, l2)
End Sub
Logged
Nicolás
Guest
« Reply #14 on: 24 Nov '08 - 16:38 »
Reply with quoteQuote


Hi Radio42, Thank you very much.

Now i have the function, but, when i put the line;:

Bass.BASS_ChannelSetDSP(strm, NormalizeDSP, peak, 0) ' for apply normalization

I need to put the variables in::. Bass.BASS_ChannelSetDSP(strm, NormalizeDSP(X,X,X,X,X), peak, 0)

Where are these variables?
Logged
Nicolás
Guest
« Reply #15 on: 24 Nov '08 - 16:44 »
Reply with quoteQuote



And one more...

When i put variables in these line::. Bass.BASS_ChannelSetDSP(strm, NormalizeDSP(X,X,X,X,X), peak, 0)

I have then next error: "Expression does not produce a value"

Thanks


Logged
radio42
Posts: 4012


« Reply #16 on: 24 Nov '08 - 17:03 »
Reply with quoteQuote

PLease take a look to the BASS and BASS.NET doc - there are a lot of VB.Net examples included:
Private _myDSPProc As DSPPROC ' make it global, so that the GC can not remove it
...
_myDSPProc = New DSPPROC(AddressOf NormalizeDSP)
Bass.BASS_ChannelSetDSP(_stream, _myDSPProc, IntPtr.Zero, 0)
...
Replace "_stream" with your stream handle as returned by "BASS_StreamCreateFile"
Logged
Nicolás
Guest
« Reply #17 on: 24 Nov '08 - 17:35 »
Reply with quoteQuote



Ok thanks again, but.. i have a similar problem, now in the line::

_myDSPProc = New DSPPROC(AddressOf NormalizeDSP)

becouse in the AddressOf "NormalizeDSP" i have the error:

"Method Private Sub Normalize(handle...... does not have the same signature as Delegate Sub DSPROC(handle as....


Thanks
Logged
radio42
Posts: 4012


« Reply #18 on: 24 Nov '08 - 17:44 »
Reply with quoteQuote

Then you are using an old version of BASS/BASS.NET - which version are you using?
And please, please also consult the documentation!
Logged
Nicolás
Guest
« Reply #19 on: 24 Nov '08 - 17:50 »
Reply with quoteQuote



I-m using Bass.Net 2.3.0.2 Version,

Please give your e/mail, for send you my code via email ok__ thanks man
Logged
Pages: [1] 2  All
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines