1

So, my main problem here is I don't yet know what the actual problem is. I have a two microphones, and when using either one, my program that detects the volume in db will only detect 90 max. I'm not sure if this is a limit on the microphone, or if it's the program, but it clearly shows that it's 90db and it won't go any higher, regardless of whether or not it is. If this proves helpful, the microphones I have are a cheap logitech webcam and a blue yeti microphone (not cheap).

In the event that it is the microphone, why exactly does this happen, and if not, well then here's the code I have for figuring out what the db level is:

AudioFormat audioFormat = getAudioFormat();
TargetDataLine targetDataLine;
try {
    targetDataLine = (TargetDataLine) AudioSystem.getTargetDataLine(audioFormat);
    targetDataLine.open();
    targetDataLine.start();
    byte [] buffer = new byte[2000];
    while (true) {
        int bytesRead = targetDataLine.read(buffer,0,buffer.length);
         if (bytesRead >= 0) {
             max = (int) (buffer[0] + (buffer[1] << 8));
             for (int p=2;p<bytesRead-1;p+=2) {
                 int thisValue = (int)(buffer[p] + (buffer[p+1] << 8));
                 if (thisValue > max) max = thisValue;
             }

         }
    }
} catch (LineUnavailableException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
currentDecibelLabel.setText(Integer.toString((int)(20 * Math.log10(max)))));

Any ideas? Thanks!!

EDIT: Just so you know, 'max' is a global int.

tdog
  • 169
  • 2
  • 11
  • My guess would be that ``(buffer[p] + (buffer[p+1] << 8)`` returns a negative int (it at least has the potential for it). to convert a signed byte to an "unsigned" integer you need to mask it to remove the signed bit. – Pinkie Swirl Aug 16 '18 at 13:48

1 Answers1

3

Your maxvariable is a short.

A short maximal value is 32767 (signed 16 bits/2 bytes value) according to oracle

20*log10(32767) = 90.3087

As you cast it to int, it's round to 90.

If the API gives you only 2 bytes to get the volume, and if (and only if) it's unsigned, you could define maxas an int instead of double raising the maximum value to 96dB.

jhamon
  • 3,603
  • 4
  • 26
  • 37
  • Dang it, I really wanted you to be right, and I thought you were. However, while that makes perfect sense, after correcting and replacing every mention of `short` with `int`, it still won't rise above 90. – tdog Aug 16 '18 at 13:41
  • @PinkieSwirl Yes I did that. – tdog Aug 16 '18 at 13:43
  • @PinkieSwirl This answer is still valid. You build `max` from 2 bytes only. Maximum value is 65535 (96dB) but if API returned a signed value, maximal value still is 32767 (90dB) – jhamon Aug 16 '18 at 13:46
  • @jhamon I didn't say your answer is wrong. One can interpret a signed byte as an unsigned integer (commen in java APIs) and that might be the problem. – Pinkie Swirl Aug 16 '18 at 13:52
  • woups, I wanted to tag the OP – jhamon Aug 16 '18 at 13:55