Hello

I'm new to programming and I'm trying to make a java application that will "hear" (not record necessarily) the sound and display how loud is.I'm thinking of converting the sound recordings to numbers,so I can see the difference on the sound levels.I got this code and I added the "getLevel()" method,which returns the amplitude of the current recording,but it's returning -1 everytime.I guess I'm not using it properly. Any ideas how I must call this method?I have to deliver my project in a week,so any help will be much appreciated!

public class Capture extends JFrame {

      protected boolean running;
      ByteArrayOutputStream out;

      public Capture() {
        super("Capture Sound Demo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        Container content = getContentPane();

        final JButton capture = new JButton("Capture");
        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);

                    System.out.println(line.getLevel());  // |-this is what i added-|
                  }
                }
                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);
      }

      @SuppressWarnings("deprecation")
    public static void main(String args[]) {
        JFrame frame = new Capture();
        frame.pack();
        frame.show();
      }   
}

Recommended Answers

All 7 Replies

It seems that getLevel was not implemented in the early releases (just returns -1 error code) It was listed as a bug around version 1.4.1, but as far as I could see it was never fixed. Part of the justification is that they could not agree a definition of "level" - instantaneous, peak, average, RMS or what?

The usual advice seems to be that you should implement your own algorithm by looking at the data in the buffer and taking an average or max value or whatever seems most appropriate. You are in good shape to do that because you have the buffer available right there in your loop.

Ok,I managed to make it capture audio and print on a xls file the timestamp and the value of the current sample,but there is a problem : even I've put some spaces between the time and the value and it seems that they are in different columns,they are actualy on the same column of the xls,it's just expanded and covers the next column (I can put a print screen if you don't understand).How can I make it print the data of time and amplitude in two different columns?Here's my code of the class which creates the file and saves the data on xls :

package soundRecording;

import java.io.File;
import java.util.Formatter;

public class Save {

    static Formatter y;

    public static void createFile() {

        Date thedate = new Date();
        final String folder = thedate.curDate();
        final String fileName = thedate.curTime();

    try {
        String name = "Time_"+fileName+".csv";
        y = new Formatter(name);
        File nof = new File(name);
        nof.createNewFile();
        System.out.println("A new file was created.");
    }
    catch(Exception e) {
        System.out.println("There was an error.");
        }
    }

    public void addValues(byte audio) {
        Date d = new Date();
        y.format("%s    " + "  %s%n",d.curTime(), audio);
    }

    public void closeFile() {
        y.close();
    }
}

If it's a csv file then you need commas to separate the values, not spaces. For importing to Excel you can also separate the values with tab characters \t

ps don't ever do this

catch(Exception e) {
   System.out.println("There was an error.");
}

The Exception contains a huge amout of info about exactly what the eror was, but you are discarding all of it. Use e.printStackTrace(); to see all the info about the error.

Thanks,I've used "\t",but I was using csv format and that's why it wasn't working,now it's working.My professor suggested me to use the csv format,I didn't even know about it.

About the error message,how do I use e.printStackTrace()?I tried "System.out.println("e.printStackTrace()")" and "System.err.println("e.printStackTrace()")".I guess I'm using it wrong,but I'm still learning :)

Also posted Here.
Anyone answering may wish to check that they are not repeating anything already stated.

It's very simply...

catch(Exception e) {
   e.printStackTrace();
}

Thanks James,I fixed it

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.