# Android QuestionHow to Get dB and Hz from Buffer (AudioStreamer)

#### abbas abedi

##### Member
Hi
I used AudioStreamer for get stream voice as Live and how can I Get Buffer byte info ?
for example like dB volume or Hz or dB of any Hz #### abbas abedi

##### Member
I used this code for dB but I think dont work correctly

B4X:
``````Sub streamer_RecordBuffer (Buffer() As Byte)

Dim Sum As Int

For i = 0 To 480 Step 2
Sum=Sum+(Buffer(i)*256)+Buffer(i+1)
Next

Sum=Sum/240+(32767/2)
Sum=20*Logarithm(Sum/32767,10)

Log("dB " & Sum )

End Sub``````

#### JordiCP

##### Expert
Longtime User
dB is a logarithmic measure of power, usually relative (for instance, the gain of an amplifier) or 'absolute' when you reference it to a given unit (for instance dBm, when you compare a given electric power refered to a miliwatt)

The difference between them is only an additive factor, which is the reference

In your calculation, if buffer contains a wave amplitude which can take both positive and negative values, these values must always be squared (power is proportional to the square of the amplitude), otherwise the resulting sum could be null.

also, when calculating dBs from a dynamic input, which I guess is the case, the way to proceed is by a sliding a time window and/or time segments which include N samples.

hope it helps #### abbas abedi

##### Member
hi @JordiCP
thanks
actually, I want analyst bytes of a buffer as Real-time, for example get dB or Hz like tuner apps , do you have any simple codes ?

#### kimstudio

##### Active Member
Longtime User
Byte in B4A is signed, so this (Buffer(i)*256)+Buffer(i+1) to convert byte to short is not correct. ByteConverter lib can solve this.

As converted short also signed, calculate mean value will almost always get zero. We can get the max absolute value of this buffer and use
db=20*Logarithm(max(abs(buffer short))/32768,10) to get db. If mean is prefered then db=20*Logarithm(mean(abs(buffer short))/32768,10).

Also, sum should be defined as double, not int.

#### emexes

##### Expert
I feel like audio level (power?) would be proportional to the average difference between sample values in a block of audio (or perhaps the square of that).

If you take the simple maximum or high-low sample value of range of a block of audio, then high frequency energy will probably be hidden by lower frequency energy.

Having said that, I am scouring the internet for some actual code based on more than just feeling.

• Shelby

#### emexes

##### Expert
Having said that, I am scouring the internet for some actual code based on more than just feeling.
Well that was harder to find than you'd think. Closest I got was:

https://stackoverflow.com/questions...he-level-amplitude-db-of-audio-signal-in-java

which also now has me wondering whether your sixteen-bit samples are big-endian or little-endian; two's-complement or sign+magnitude or offset; and mono or stereo?

Anyway, once you've got the sample values correctly interpreted, that code then normalises the samples to +/- 1.0, then does a rms average, from which you can then do the "20 * log10(rms) + 0 dB offset" conversion.

• Shelby and abbas abedi

#### abbas abedi

##### Member
Well that was harder to find than you'd think. Closest I got was:

https://stackoverflow.com/questions...he-level-amplitude-db-of-audio-signal-in-java

which also now has me wondering whether your sixteen-bit samples are big-endian or little-endian; two's-complement or sign+magnitude or offset; and mono or stereo?

Anyway, once you've got the sample values correctly interpreted, that code then normalises the samples to +/- 1.0, then does a rms average, from which you can then do the "20 * log10(rms) + 0 dB offset" conversion.
excellent, could you please convert Java codes to b4a ?

#### emexes

##### Expert
excellent, could you please convert Java codes to b4a ?
Sure, I've got a few free minutes. B4X:
``````'convert audio bytes to Shorts (16-bit signed integers -32768..32767)

Dim bc As ByteConverter
'''bc.LittleEndian = True / False   'depending on your data, eg: [URL]https://www.nicklandis.com/blog/little-endian-vs-big-endian[/URL]
Dim samples() As Short = bc.ShortsFromBytes(AudioBytes())

Dim rms As Double = 0
Dim peak As Float = 0

For I = 0 to samples.length - 1
Dim ThisSample As Float = samples(I) / 32768.0    'normalise to +/- 1.0

Dim AbsSample = Abs(ThisSample)
If AbsSample > peak then
peak = AbsSample
End If

rms = rms + ThisSample * ThisSample
Next

rms = Sqrt(rms)

Peak = LastPeak * 0.875
End If
LastPeak = Peak

'in fact, that whole peak thing should probably just be based on rms value

'setMeterOnEDT(rms, peak);``````

from original code at https://stackoverflow.com/questions...he-level-amplitude-db-of-audio-signal-in-java
Java:
``````byte[] buf = new byte[bufferByteSize];
float[] samples = new float[bufferByteSize / 2];

float lastPeak = 0f;

line.start();
for(int b; (b = line.read(buf, 0, buf.length)) > -1;) {

// convert bytes to samples here
for(int i = 0, s = 0; i < b;) {
int sample = 0;

sample |= buf[i++] & 0xFF; // (reverse these two lines
sample |= buf[i++] << 8;   //  if the format is big endian)

// normalize to range of +/-1.0f
samples[s++] = sample / 32768f;
}

float rms = 0f;
float peak = 0f;
for(float sample : samples) {

float abs = Math.abs(sample);
if(abs > peak) {
peak = abs;
}

rms += sample * sample;
}

rms = (float)Math.sqrt(rms / samples.length);

if(lastPeak > peak) {
peak = lastPeak * 0.875f;
}

lastPeak = peak;

setMeterOnEDT(rms, peak);``````

Last edited:

#### kimstudio

##### Active Member
Longtime User
Typo: ThisSample = Sample?

This makes the peak bar (line) in UI drops down gradually:
Peak = LastPeak * 0.875
End If
LastPeak = Peak

If the DB number is really needed as title says instead of a general volume meter, suggest to use the formulas I provided... or I think the above code by emexes is totally fine.
If you want Hz, search FFT lib in forum.

• abbas abedi

#### emexes

##### Expert
Typo: ThisSample = Sample?
Fixed, thanks I'd like to say that was me testing to see if anybody was paying attention, but... that'd be not quite true • Shelby

#### emexes

##### Expert
This makes the peak bar (line) in UI drops down gradually:
B4X:
``````If LastPeak > Peak Then    'not sure about this re: * 0.875
Peak = LastPeak * 0.875
End If
LastPeak = Peak``````
I feel that it will act oddly if Peak is inside the range of LastPeak * 0.875 to LastPeak

but I suspect it is a momentary thing that users don't notice or don't care about

• abbas abedi and Shelby