1

i am working with a library that records audio and i can listen each time a new byte array if buffer if filled so i get this callback :

public void onVoiceReceived(byte[] buffer) {

}

now i want to take the buffer and translate it to a level so i can draw the amplitude meter. how can i translate this data? i dont want to create another recorder and use the read() command.

this is the drawing code

    private void drawCircleView(Canvas canvas, double ampValue) {
    // paint a background color
    canvas.drawColor(android.R.color.holo_blue_bright);

    // paint a rectangular shape that fill the surface.
    int border = 0;
    RectF r = new RectF(border, border, canvas.getWidth(), canvas.getHeight());
    Paint paint = new Paint();
    paint.setARGB(255, 100, 0, 0); // paint color GRAY+SEMY TRANSPARENT
    canvas.drawRect(r, paint);

    /*
     * i want to paint to circles, black and white. one of circles will bounce, tile the button 'swap' pressed and then other circle begin bouncing.
     */
    calculateRadiuses();
    // paint left circle(black)
    paint.setStrokeWidth(0);
    paint.setColor(getResources().getColor(android.R.color.holo_blue_light));
    canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, ampValue, paint);
}

thanks!

orthehelper
  • 4,009
  • 10
  • 40
  • 67

1 Answers1

6

The byte[] buffer is the raw unformatted data. To move forward, you'll need to know something about the format of the data. How many bits per sample, the endianness, and how many channels of data. 16 bits per sample is the most common. Assuming there are two channels of data and it is 16 bits, then the bytes are going to be arranged like this [ch1 hi byte, ch1 lo byte, ch2 hi byte, ch2 lo byte, ...] and so on.

Once that information is known you can convert to a double. Typically, a double amplitude is kept in the range (-1.0, 1.0).

double[] samples = new double[buffer.Length];
for (int i = 0; i < buffer.Length; ++i)
{
    int intSample = ((buffer[i*2] << 8) | buffer[i*2 + 1]) << 16; 
    samples[i] = intSample * (1/4294967296.0); // scale to double (-1.0,1.0)
}

Now to get a crude level meter, first you need to decide if you want a peak meter or an RMS meter. For a peak meter just find the max of the abs of all the samples.

jaket
  • 9,140
  • 2
  • 25
  • 44