So I am writing a voice activated recording program, and one of the things I would like it to do is plot the current and past volume level on a JPanel.

Write now I am simply reading one byte from the audio buffer, converting it to an int, taking its absolute value, and more or less directly plotting the value on a JPanel. Things more or less work, but I get the feeling that my method is not very orthodox.

So my question basically boils down to the following:
how is audio data typically interpreted when used to represent the current volume level?

Here are some bits of code:

In the following code the byte read from the microphone input is converted to an int, and sent to the JPanel osc, for drawing.

int bufferSize = (int)format.getSampleRate() * format.getFrameSize();
        byte buffer[] = new byte[bufferSize];

...

while (running) {
              int count =
                line.read(buffer, 0, buffer.length);
              if (count > 0) {
                  osc.addLevel(Math.abs((int)buffer[0]));

                out.write(buffer, 0, count);
              }

The following is the actual JPanel code used to plot the int.

public void addLevel(int i)
    {
        columns.add(i);
        draw();
    }

    public void draw()
    {
        g = getGraphics();
        int bottom = getHeight();
        g.setColor(Color.black);
        g.fillRect(0,0,getWidth(),bottom);
        g.setColor(Color.green);
        //int mult = bottom/128;

        int edge = getWidth()-1;
        for(int c = columns.size()-1; c>-1;  c--)
        {
            g.drawRect(--edge,bottom-columns.get(c),1,columns.get(c));
            System.out.println(edge+" "+bottom+" 1 "+columns.get(c));
        }
    }

The previous code results in this:
[IMG]http://i12.photobucket.com/albums/a202/kimbokasteniv/panle.png[/IMG]

And the actual audio format:

float sampleRate = 8000;
        int sampleSizeInBits = 8;
        int channels = 1;
        boolean signed = true;
        boolean bigEndian = true;

So how should this be done? Should I read more bytes? Should I take an average of several bytes? Or is using plain byte information for the volume level foolish altogether?

Recommended Answers

All 2 Replies

It depends on why you are displaying the level - if it's to ensure the signal is loud enough, you can just pick a subset of the samples (say 10 / sec) and average them. If you're trying to avoid clipping you need to check every sample and keep the max. value (once again in maybe 10 values / second).
Check out this WikiP article http://en.wikipedia.org/wiki/VU_meter which gives links to useful data on how to scale the output and what time constants to use for different needs.

Alright, that is helpful information. I think that is all I need to know for my purposes, thanks for the help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.