1

I am trying to determine the amplitude of an instrument (trumpet, guitar, etc.) that is being recorded using the Java Sound API and display an amplitude vs. time graph. I haven't had much experience with this API and am not quite sure how to compute a RMS or FFT for a sound wave input. How do I go about achieving this?

import javax.swing.*; 
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;

public class FrequencyAmplitude extends JFrame {
/**
     * 
     */
    private static final long serialVersionUID = 1173050310536562125L;
//CAPTURE AUDIO TEST #1
  protected boolean running;
  ByteArrayOutputStream out;

  public FrequencyAmplitude() {
    super("Recording Demo");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container content = getContentPane();

    final JButton capture = new JButton("Record");
    final JButton stop = new JButton("Stop");
    final JButton play = new JButton("Play");

    capture.setEnabled(true);
    stop.setEnabled(false);
    play.setEnabled(false);

    ActionListener captureListener = 
        new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        capture.setEnabled(false);
        stop.setEnabled(true);
        play.setEnabled(false);
        captureAudio();
      }
    };
    capture.addActionListener(captureListener);
    content.add(capture, BorderLayout.NORTH);

    ActionListener stopListener = 
        new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        capture.setEnabled(true);
        stop.setEnabled(false);
        play.setEnabled(true);
        running = false;
      }
    };
    stop.addActionListener(stopListener);
    content.add(stop, BorderLayout.CENTER);

    ActionListener playListener = 
        new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        playAudio();
      }
    };
    play.addActionListener(playListener);
    content.add(play, BorderLayout.SOUTH);
  }

  private void captureAudio() {
    try {
      final AudioFormat format = getFormat();
      DataLine.Info info = new DataLine.Info(
        TargetDataLine.class, format);
      final TargetDataLine line = (TargetDataLine)
        AudioSystem.getLine(info);
      line.open(format);
      line.start();
      Runnable runner = new Runnable() {
        int bufferSize = (int)format.getSampleRate() 
          * format.getFrameSize();
        byte buffer[] = new byte[bufferSize];

        public void run() {
          out = new ByteArrayOutputStream();
          running = true;
          try {
            while (running) {
              int count = 
                line.read(buffer, 0, buffer.length);
              if (count > 0) {
                out.write(buffer, 0, count);
              }
            }
            out.close();
          } catch (IOException e) {
            System.err.println("I/O problems: " + e);
            System.exit(-1);
          }
        }
      };
      Thread captureThread = new Thread(runner);
      captureThread.start();
    } catch (LineUnavailableException e) {
      System.err.println("Line unavailable: " + e);
      System.exit(-2);
    }
  }

  private void playAudio() {
    try {
      byte audio[] = out.toByteArray();
      InputStream input = 
        new ByteArrayInputStream(audio);
      final AudioFormat format = getFormat();
      final AudioInputStream ais = 
        new AudioInputStream(input, format, 
        audio.length / format.getFrameSize());
      DataLine.Info info = new DataLine.Info(
        SourceDataLine.class, format);
      final SourceDataLine line = (SourceDataLine)
        AudioSystem.getLine(info);
      line.open(format);
      line.start();

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

        public void run() {
          try {
            int count;
            while ((count = ais.read(
                buffer, 0, buffer.length)) != -1) {
              if (count > 0) {
                line.write(buffer, 0, count);
              }
            }
            line.drain();
            line.close();
          } catch (IOException e) {
            System.err.println("I/O problems: " + e);
            System.exit(-3);
          }
        }
      };
      Thread playThread = new Thread(runner);
      playThread.start();
    } catch (LineUnavailableException e) {
      System.err.println("Line unavailable: " + e);
      System.exit(-4);
    } 
  }

  private AudioFormat getFormat() {
    float sampleRate = 8000;
    int sampleSizeInBits = 8;
    int channels = 1;
    boolean signed = true;
    boolean bigEndian = true;
    return new AudioFormat(sampleRate, 
      sampleSizeInBits, channels, signed, bigEndian);
  }
  public static void main(String args[]) {
    JFrame frame = new FrequencyAmplitude();
    frame.pack();
    frame.setVisible(true);
  }
}

    enter code here
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
user1058860
  • 513
  • 2
  • 9
  • 21
  • What does the code you've posted have to do with the problem you're trying to solve? What's wrong with your current implementation? – Matt Ball Nov 22 '11 at 01:17
  • nothings wrong, I did not say anything was wrong, my question is from this setup how I would go about calculating the volume of the audio? – user1058860 Nov 22 '11 at 05:12
  • oh and the code is used to record audio – user1058860 Nov 22 '11 at 05:37
  • At first I was going to suggest [DataLine.getLevel()](http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/DataLine.html#getLevel), but it doesn't seem to be implemented. There's a discussion about it [here](https://forums.oracle.com/forums/thread.jspa?threadID=1270831) and workarounds. – prunge Nov 22 '11 at 05:42

1 Answers1

-1

Convert the an array of bytes to an array of floats. that's basically it .The length of the float array will be 1/8 the length of the byte array.

if you paste the output of the code in excel or libre office calc(ubuntu), you will see the waveform

    ByteBuffer buf = ByteBuffer.wrap(bytes);
    long[] longs = new long[bytes.length / 8];
    for (int i = 0; i < longs.length; i++)
     {
        longs[i] = buf.getLong(i*8);
        System.out.println(longs[]i);

     }

THIS IS NOT THE IDEAL THING TO DO, but for simplicity sake put the code in the while block of CaptureAudio. Dont recoed more than about two seonds and then copy the output to excel an plot a line graph . Youll see the waveform.

FutureSci
  • 1,750
  • 1
  • 19
  • 27