|
Schlichter
Guest
|
 |
« on: 27 Nov '06 - 08:05 » |
Quote
|
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: 15269
|
 |
« Reply #1 on: 27 Nov '06 - 15:35 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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? 
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #6 on: 24 Jan '07 - 16:37 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
Hello members! Sorry my english, I'm braziliam.
I need an example in Delphi. please help me.
Thanks.
Israel
|
|
|
|
|
Logged
|
|
|
|
|
Chris
Posts: 1507
|
 |
« Reply #11 on: 3 Nov '08 - 16:01 » |
Quote
|
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 » |
Quote
|
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?  ?? ¿¿¿ void CALLBACK NormalizeDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, DWORD peak)  What is handle,*buffer, etc. please HELP!! Thanks
|
|
|
|
|
Logged
|
|
|
|
|
radio42
Posts: 4012
|
 |
« Reply #13 on: 24 Nov '08 - 08:14 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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 » |
Quote
|
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
|
|
|
|
|