19 Jun '13 - 10:53 *
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]
  Reply  |  Print  
Author Topic: Finding the Max Amplitude of a Wav File  (Read 850 times)
piano18
Posts: 3


« on: 14 Jun '12 - 10:22 »
Reply with quoteQuote

Hello everyone,

I'm very new to Bass.net, and have only been using it for a couple of days, but I am searching for a way to find the maximum amplitude of a Wav file, so that I can batch compare some and put them in order of "loudness" (this is for instrument samples recorded to use as a virtual instrument!).

I have tried using the BASS_ChannelGetLevel method, but I do not really understand as this varies like a VU Meter as an audio file plays (I assume the amplitude of the current point in the file). Ideally, I would like to find out the loudest value of amplitude without having to play the file (is there a way?).

Another way I have thought is to play a file and then read the BASS_ChannelGetLevel as a VU Meter from a timer "tick", then put this into an array and find the largest value - however again, this is both too time-consuming (in actual processing-wise, I don't want my user to sit there for weeks (exaggeration, I hope XD) waiting in realtime!), and not accurate enough (the files are sublty different - they are different in amplitude as I have looked at them in Cubase - but if the timer is too long then it is likely it could miss measuring the parts of the file I would like).

I am quite a beginner to programming, and completely new to audio programing (though I understand a lot of the physics behind it just not how the coding etc works). I am using VB.Net but if anyone has any help if it's in C# then I could probably undestand because of how similar the languages are! At the end of the day, I am a musician trying to make life easier Smiley

Thanks a lot in advance! I have been trying to get my head around this for days so thought it would be best to ask on here!

Rob Smiley
Logged
gnag
Posts: 160


« Reply #1 on: 14 Jun '12 - 12:26 »
Reply with quoteQuote

If you have a pre-recorded file you should create a decoding channel (Use Flag BASSFlag.BASS_STREAM_DECODE when creating the Channel!) which is used to process files without playing them.

After that you can make for example a loop with BASS_ChannelGetLevel which is "running through the file", it means it outputs the level of one part and then advances some bytes to the next part until it reaches the end of the file and it doesn't need to be actually played to the speakers.

Also each time in your loop you can do a simple check to store the value for example in variable "float PeakLvl" if its a peak. This means that the loop needs to check every iteration if the current Level is greater than the content of the PeakLvl Variable and if yes, the PeakLvl will be set to the current retrieved level.

They way you were thinking of is not good, if you make it with a timer you may loose Data since its not "always" called, if the Timer is not fast enough it doesn't check the Level often enough. Besides this the user would have to wait until then File is fully played. Also it would have another performance issue, if the Timer is called very fast it would be almost like a Loop and therefore waste CPU Power and block the Main Thread.

As a general note, Audio Programming is not simple - you need to have very good knowledge of programming, need to understand the Physics&Maths behind it (How Frequencies, Soundwaves, Harmonics, Distortions work and how their Amplitudes look like,Howto Calculate RMS;FFT;Fundamental Frequencies) and also Musical Knowledge (Note Systems, How Note Frequencies are calculated, Harmonics, Chords, Beats like 3/4, 4/4 etc).
Logged
piano18
Posts: 3


« Reply #2 on: 14 Jun '12 - 14:06 »
Reply with quoteQuote

Hi, thank you for your reply.

I understand what you are saying, I will look into these features and work with them.

Yes, I agree, I never thought that programming audio would be so difficult! This is the only function that I require though (the rest is simply organising files based on their maximum ampitude) and so hopefully I should be fine. I am programing something very small to organise sounds that I have sampled from an instrument, I had originally of course thought of more ambitious things but I am just not good enough (nor have the time to study it in detail)! After this I will go back to being a just a music student, to be honest, programming is something I used to do, but I don't really belong with it anymore.. Smiley

But again, thank you very much for your help,

Rob
Logged
radio42
Posts: 4030


« Reply #3 on: 14 Jun '12 - 17:11 »
Reply with quoteQuote

As you are using Bass.Net you might also use the build-in helper method called "GetNormalizationGain", which can be found in the "Utils" namespace.

E.g. call it the following way:
float peak = 0f;
Utils.GetNormalizationGain("C:\\Test.mp3", 1f, -1.0, -1.0, ref peak);
The returned 'peak' value is the maximum peak level as a float value between 0.0 (silence) and 1.0 (0dB).

Or (if you want to do it manually):
// create a decoding stream
int decodingStream = Bass.BASS_StreamCreateFile(filename, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE);
// setup a buffer (1sec. long)
int blockLength = (int)Bass.BASS_ChannelSeconds2Bytes(decodingStream, 1f);
float[] buffer = new float[blockLength / 4]; // 32-bit!

float mypeak = 0f;
float maxPeak = 0f;
long start = 0L;
long end = long.MaxValue;
while (start < end)
{
    // scan the stream in blocks (returns the PCM sample data in buffer)
    int len = Bass.BASS_ChannelGetData(decodingStream, buffer, blockLength | (int)BASSData.BASS_DATA_FLOAT);
    if (len < 0)
        start = end;
    else
    {
        start += len;
        len /= 4;
        // get the peak in this block
        for (int a = 0; a < len; a++)
        {
            mypeak = Math.Abs(buffer[a]);
            if (mypeak > maxPeak)
                maxPeak = mypeak;
        }
    }
}
// free the stream
if (decodingStream != 0)
    Bass.BASS_StreamFree(decodingStream);
// maxPeak now contains your maximum peak level value
Logged
piano18
Posts: 3


« Reply #4 on: 15 Jun '12 - 21:53 »
Reply with quoteQuote

Oh okay! Thank you very much, that is just what I was looking for!

The added manual code also helps me understand how to call other functions correctly,

Again, thanks a lot!

Rob
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines