If you have read access to the audio wave, there are a few ways to do it. I will cover an accurate, and a fast method. If you do not have read access to the audio wave, you need to get access to the audio wave.
I'm not familiar with libGDX, but I highly doubt it has built-in functionality for this. It's not functionality that is typically needed, or asked of, in any software. Including software like Audacity. That said, here are my solutions:
Accurate Method

What you want are the green lines there. The length of that green line (the difference between the top of the wave, and the bottom), is going to correlate to a percentage of the max volume. The percentage could be calculated by float percentage = greenLineLength / MaxLength;
If it ranged from -1 to 1, MaxLength = 2
. If it ranges from 0 to 255, MaxLength = 255
The green lines going to be a little tricky though. First your going to need to identify those peaks. say you're analyzing the wave at point i
. If you were to take the difference between i
and i+1
(getSample(i) - getSample(i+1)
), you would end up with a value representing the direction that the wave is headed at point i
. If the value is positive, then it is going up. If it is negative, then it is going down.
If that were put into sudo code:
float GetDifference(int i)
{
return GetSample(i) - GetSample(i+1);
}
A peak is when it changes from going up to going down, or when it's going down and then up. Since we already know how to find out if it's going up or down. We just need to compare the value with the previous value. In sudo code:
bool IsPeak(int i)
{
float a, b;
a = GetDifference(i); // direction of the current sample
b = GetDifference(i-1); // direction of the previous sample
if ( ((a > 0) and (b < 0)) // if it's going up then down.
or ((a < 0) and (b > 0)) ) // if it's going down then up.
{
return true; // it's a peak!
}
// otherwise
return false;
}
From there, we just need to find peak 1, store that value, then find peak 2, and difference the two.
float FindVolumeFromSample(int i)
{
int Peak1, Peak2; // our two peaks
bool FoundPeak; // = true; if we have found the peak. Otherwise, false;
// find our first peak
FoundPeak = false;
Peak1 = i; // start out at the point we're searching from
while (not FoundPeak)
{
if (IsPeak(Peak1)) // check to see if this is a peak
{
FoundPeak = true; // found the peak
}
else // this is not a peak
{
Peak1 = Peak1 + 1; // move to the next sample
}
}
// loop to our second peak
FoundPeak = false;
Peak2 = Peak1 + 1; // Start off just after the previous peak
while (not FoundPeak)
{
if (IsPeak(Peak2)) // check to see if this is a peak
{
FoundPeak = true; // found the peak
}
else // this is not a peak
{
Peak2 = Peak2 + 1; // move to the next sample
}
}
return (GetSample(Peak1) - GetSample(Peak2)) / Maxlength;
}
Fast Method
Since looping through all that data can be a little too cpu intensive, there is also a simpler method: Loop through a small section of audio, find the highest point, and the lowest point, and find the difference between those. The difference between them being proportional to the percentage of the max volume as stated in the first paragraph, above.
So lets say you can access the samples through GetSample(i)
, your given a start point, and an end point. You want to find the volume between start and end. You loop through all values from start to end, and keep the two most extreme values. In sudo code:
float FindVolumeBetweenSamples(int start, int end)
{
float max, min; // the maximum, and minimum, points.
// the current sample i, is initially equal to start
// continue the loop while i has not reached or passed end, and,
// increment until then.
for (int i = start; i < end; i++)
{
float sample = GetSample(i);
if (sample > max) // the new one is bigger
{
max = sample;
}
else if (sample < min) // the new one is smaller
{
min = sample
}
}
return (max - min) / MaxLength;
}
As your start and end point get closer and closer, it will become more and more accurate, to a point. This method fails when you start trying to measure volume between peaks. You'll just have to hope that doesn't happen.