filosofis
Posts: 3
Joined: Wed Jan 30, 2013 9:03 pm

java audio recording crash

Wed May 22, 2013 3:05 pm

Hi I am atempting to make a little recording device based on raspberry pi and a usb mixer.

I have written a little java aplication to handle this. The program basically have 4 buttons: record, play, stop and save. Record starts the recording, Stop stops it, Play plays it, and Save saves it to user specified location.

I can record audio using just arecord. So the hardware seems to be working fine.

The program runs correctly on windows, but when i run it on the pi it seems to start recording and stop the recording corectly, but then when I try to either play or save the program crashes with the following error:

javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian not supported.

Now I do not really have a clue where to go from here, thus Im asking for help. here is the intresting part of the code.

Code: Select all

package audio;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Port;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

public class Controller {
	AudioFormat format;
	TargetDataLine targLine = null;
	ByteArrayOutputStream output = null;
	AudioInputStream input;
	SourceDataLine srcLine = null;
	boolean stopCapture = false;



	// Metoden fångar ljud ingång från mikrofonen och sparar den i ett
	// ByteArrayOutPutStream object.
	public void startRecord() {
		try {
			format = getAudioFormat();
			DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, format);
		
			 
			if(!AudioSystem.isLineSupported(dataLineInfo)){
				JOptionPane.showMessageDialog(null,"Line is Not Supported");
			}

			// Lines är digital audio.
			// targetdataline är en typ av datalinje som audio data kan läsas
			// från.
			
			targLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
			targLine.open(format);
			targLine.start();

			// Skapar en tråd för att fånga data från mikrofonen och startar
			// micken och avslutar tills man tryckt på stop knappen
			Thread captureThread = new CaptureThread();
			captureThread.start();

		} catch (Exception e) {
			System.out.println(e);
			System.exit(0);
		}

	}

	// // En inre klass som fångar data från microfonen

	// en data array som temporärt håller i data.
	private class CaptureThread extends Thread {
		byte data[] = new byte[100000];

		public void run() {
			output = new ByteArrayOutputStream();
			stopCapture = false;
			// Loopar till stop knappen är tryckt.
			try {
				while (!stopCapture) {
					// Läser data från targetDataline.
					int count = targLine.read(data, 0, data.length);
					if (count > 0) {
						// Sparar data i en output stream objekt.
						output.write(data, 0, count);
					}
				}
				output.close();
			} catch (Exception e) {
				System.out.println(e);
				System.exit(0);
			}
		}
	}

	// Metoden skapar och returnerar ett AudioFormat object.
	public AudioFormat getAudioFormat() {
		float sampleRate = 44100;
		int sampleSizeInBits = 16;
		int channels = 2;
		boolean signed = true;
		boolean bigEndian = true;
		return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,
				bigEndian);
	}

	// Denna metod spelar tillbaka den ljud data som har lagrats i
	// ByteArrayOutputStream,
	public void startPlay() {
		// Här så kommer vi att hämta den föregående data som sparats i en byte
		// array objekt.
		try {
			byte audioData[] = output.toByteArray();
			InputStream byteArrayInputStream = new ByteArrayInputStream(
					audioData);
			AudioFormat audioFormat = getAudioFormat();
			input = new AudioInputStream(byteArrayInputStream, audioFormat,
					audioData.length / audioFormat.getFrameSize());
			DataLine.Info dataLineInfo = new DataLine.Info(
					SourceDataLine.class, audioFormat);

			// Sourcedataline är en data linje där man kan skriva in data.
			srcLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
			srcLine.open(audioFormat);
			srcLine.start();

			// Skapar en tråd som spelar upp datan och startar den och den körs
			// till all data har spelats så vida du inte trycker
			// på stop.
			Thread playThread = new PlayThread();
			playThread.start();
		} catch (Exception e) {
			System.out.println(e);
			System.exit(0);
		}
	}

	private class PlayThread extends Thread {
		byte buff[] = new byte[100000];

		public void run() {
			try {
				int count;
				while ((count = input.read(buff, 0, buff.length)) != -1) {
					if (count > 0) {
						srcLine.write(buff, 0, count);
					}
				}
				srcLine.drain();
				srcLine.close();
			} catch (Exception e) {
				System.out.println(e);
				System.exit(0);
			}
		}
	}

	public void save() {
		try {
			byte audioData[] = output.toByteArray();
			InputStream byteArrayInputStream = new ByteArrayInputStream(
					audioData);
			AudioFormat audioFormat = getAudioFormat();
			input = new AudioInputStream(byteArrayInputStream, audioFormat,
					audioData.length / audioFormat.getFrameSize());
			DataLine.Info dataLineInfo = new DataLine.Info(
					SourceDataLine.class, audioFormat);
			srcLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
			srcLine.open(audioFormat);
			srcLine.start();

			Thread saveThread = new SaveThread();
			saveThread.start();
		} catch (Exception e) {
			System.out.println(e);
			System.exit(0);
		}
	}

	class SaveThread extends Thread {
		public void run() {
			AudioFileFormat.Type type = AudioFileFormat.Type.WAVE;
			File file = new File("");
			JFileChooser choose = new JFileChooser();
			choose.setSelectedFile(new File(".mp3"));
			int use = choose.showSaveDialog(choose);

			if (use == JFileChooser.APPROVE_OPTION) {
				file = choose.getSelectedFile();
				JOptionPane.showMessageDialog(null,
						"Congratulations You Have Just Saved Your File");
			} else if (use == JFileChooser.CANCEL_OPTION) {
				JOptionPane.showMessageDialog(null, "Srry");

			}

			try {

				byte audio[] = output.toByteArray();
				InputStream input = new ByteArrayInputStream(audio);
				final AudioFormat format = getAudioFormat();
				final AudioInputStream audioInputStream = new AudioInputStream(
						input, format, audio.length / format.getFrameSize());
				AudioSystem.write(audioInputStream, type, file);

			} catch (Exception e) {
				System.out.println(e);
				System.exit(0);
			}

		}
	}

	public void stopPlay() {
		try {
			targLine.flush();
			targLine.drain();
			targLine.stop();
			targLine.close();
			if (srcLine != null) {
				srcLine.flush();
				srcLine.drain();
				srcLine.stop();
				srcLine.close();
			}

			byte audioData[] = output.toByteArray();
			InputStream byteArrayInputStream = new ByteArrayInputStream(
					audioData);
			AudioFormat audioFormat = getAudioFormat();
			input = new AudioInputStream(byteArrayInputStream, audioFormat,
					audioData.length / audioFormat.getFrameSize());
			DataLine.Info dataLineInfo = new DataLine.Info(
					SourceDataLine.class, audioFormat);
			srcLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
			srcLine.open(audioFormat);
			srcLine.start();

			output.flush();
			output.close();
			byteArrayInputStream.close();

		} catch (Exception e) {
			System.out.println(e);
			System.exit(0);
		}

	}
	
	public void mixer(){
		Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
		 for (int i = 0; i < mixerInfo.length; i++) {
			 System.out.println(mixerInfo[i].getName());
			 }// end for loop
		
	}
	
}
Attachments
audio.rar
the entire projekt
(4.75 KiB) Downloaded 285 times

Beron
Posts: 12
Joined: Tue Feb 05, 2013 11:41 pm

Re: java audio recording crash

Wed May 22, 2013 7:13 pm

Hi!

I think the problem is related to the OS you are using.

Are you using the standard "Wheezy" OS or the soft-float version?
http://www.raspberrypi.org/downloads

I think you might need the second one to make proeper Oracle Java work as it should.

Good luck!

/Peter

User avatar
xranby
Posts: 540
Joined: Sat Mar 03, 2012 10:02 pm
Contact: Website

Re: java audio recording crash

Thu May 23, 2013 8:47 am

Rasbian work fine for java keep using it, this is a common raspberry pi kernel driver limitation for both hardfloat and soft float distributions.

The error is self explenatory, big-endian audio format is not supported by the raspberry pi soundcard driver, change the getAudioFormat() function to request a little-endian format:
boolean bigEndian = false;

This can also be fixed properly by improving the Raspberry Pi ALSA audio linux kernel driver to support big-endian formats.
Xerxes Rånby @xranby I once had two, then I gave one away. Now both are in use every day!
twitter.com/xranby

filosofis
Posts: 3
Joined: Wed Jan 30, 2013 9:03 pm

Re: java audio recording crash

Thu May 23, 2013 1:09 pm

xranby wrote:Rasbian work fine for java keep using it, this is a common raspberry pi kernel driver limitation for both hardfloat and soft float distributions.

The error is self explenatory, big-endian audio format is not supported by the raspberry pi soundcard driver, change the getAudioFormat() function to request a little-endian format:
boolean bigEndian = false;

This can also be fixed properly by improving the Raspberry Pi ALSA audio linux kernel driver to support big-endian formats.
Thank you so much! this did the trick, now just a couple of little kinks to work out and its all done =)

ossama
Posts: 5
Joined: Thu Sep 12, 2013 8:05 am

Re: java audio recording crash

Thu Sep 12, 2013 8:09 am

Great, I have the same issue,

will this work if I simply put

boolean bigEndian = false;

Code: Select all

next to the code??
or do I need to do somehing else.

Code: Select all

URL url1 = this.getClass().getClassLoader().getResource("Audio/duha.wav");
boolean bigEndian = false;
Clip clip1 = AudioSystem.getClip();
AudioInputStream ais1 = AudioSystem.getAudioInputStream( url1 );
clip1.open(ais1);
clip1.start();
Please

User avatar
xranby
Posts: 540
Joined: Sat Mar 03, 2012 10:02 pm
Contact: Website

Re: java audio recording crash

Thu Sep 12, 2013 10:20 am

ossama wrote:Great, I have the same issue,

will this work if I simply put

boolean bigEndian = false;

Code: Select all

next to the code??
When you create the AudioInputStream you need to use the constructor that takes an AudioFormat.
You pass false to the big endian argument of the AudioFormat constructor.

The boolean bigEndian = false; needs to be in the function of your code that setup this AudioFormat instance!
Look for the getAudioFormat in filosofis code to see where this line fits.
Xerxes Rånby @xranby I once had two, then I gave one away. Now both are in use every day!
twitter.com/xranby

ossama
Posts: 5
Joined: Thu Sep 12, 2013 8:05 am

Re: java audio recording crash

Thu Sep 12, 2013 11:12 am

Thanks, I only use the following lines to play the file nothing else. I don't know ehere I should put the boolean,

Code: Select all

URL url1 = this.getClass().getClassLoader().getResource("Audio/duha.wav");
Clip clip1 = AudioSystem.getClip();
AudioInputStream ais1 = AudioSystem.getAudioInputStream( url1 );
clip1.open(ais1);
clip1.start();

ossama
Posts: 5
Joined: Thu Sep 12, 2013 8:05 am

Re: java audio recording crash

Thu Sep 12, 2013 11:25 am

ok so i figured that i need the following

Code: Select all

 private AudioFormat getAudioFormat() {
float sampleRate = 8000.0F;
 int sampleInbits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleInbits, channels, signed, bigEndian);
}
but where do i call from the following

Code: Select all

URL url = this.getClass().getClassLoader().getResource("Audio/athan1.wav");
AudioFormat adFormat = getAudioFormat();
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream( url );

Vakeesar
Posts: 26
Joined: Thu Jun 11, 2015 1:49 pm

Re: java audio recording crash

Sun Feb 28, 2016 4:58 pm

I am trying to run this code posted by filosofis (on the May 22, 2013 3:05 pm) as I have a Similar Issue with JAVA Sound library. However, I am getting the following error on Raspberry Pi 2 model B:

java.lang.illegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian is supported.

What Sort of tweaks I have to make on the Raspberry Pi to make it work

Return to “Java”