Record coming sound in Java - java

In my program, i want to record a sound when user say something like Talking Tom Cat, but I only find a way always start recording.
Please, help me. Sorry for my English

This is how to capture and record sound in Java using Sound API
import javax.sound.sampled.*;
import java.io.*;
/**
* A sample program is to demonstrate how to record sound in Java
* author: www.codejava.net
*/
public class JavaSoundRecorder {
// record duration, in milliseconds
static final long RECORD_TIME = 60000; // 1 minute
// path of the wav file
File wavFile = new File("E:/Test/RecordAudio.wav");
// format of audio file
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
// the line from which audio data is captured
TargetDataLine line;
/**
* Defines an audio format
*/
AudioFormat getAudioFormat() {
float sampleRate = 16000;
int sampleSizeInBits = 8;
int channels = 2;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
channels, signed, bigEndian);
return format;
}
/**
* Captures the sound and record into a WAV file
*/
void start() {
try {
AudioFormat format = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
// checks if system supports the data line
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Line not supported");
System.exit(0);
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start(); // start capturing
System.out.println("Start capturing...");
AudioInputStream ais = new AudioInputStream(line);
System.out.println("Start recording...");
// start recording
AudioSystem.write(ais, fileType, wavFile);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
/**
* Closes the target data line to finish capturing and recording
*/
void finish() {
line.stop();
line.close();
System.out.println("Finished");
}
/**
* Entry to run the program
*/
public static void main(String[] args) {
final JavaSoundRecorder recorder = new JavaSoundRecorder();
// creates a new thread that waits for a specified
// of time before stopping
Thread stopper = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(RECORD_TIME);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
recorder.finish();
}
});
stopper.start();
// start recording
recorder.start();
}
}
SOURCE: http://www.codejava.net/coding/capture-and-record-sound-into-wav-file-with-java-sound-api

Related

Java Sound API unable to stop recording on a button click from UI of a web Application

I am using Java Sound API for creating a Web Application .User Interface(UI) has a button which on click starts recording the speech ,the recorded audio is saved in an audio file (.wav ext) .UI also has a play button which accesses the same audio file and plays the recording back.
Currently I am recording the audio for a specified duration which is hardcoded in my application or getting passed from UI as a parameter while the recording starts.But now the requirement is to stop the recording on click of a button on UI.
Now the issue is while capturing the audio I am opening a targetline using below code :
public void capture(int record_time)
{
try {
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if(!AudioSystem.isLineSupported(info))
{
System.out.println("Line not supported");}
final TargetDataLine targetDataLine = (TargetDataLine)AudioSystem.getLine(info);
targetDataLine.open();
targetDataLine.start();
Thread thread = new Thread()
{
#Override public void run()
{
AudioInputStream audioStream = new AudioInputStream(targetDataLine);
File audioFile = new File(fileName);
System.out.println("Recording is going to get saved in path :::: "+ audioFile.getAbsolutePath());
try{
AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, audioFile);
}
catch (IOException e){
e.printStackTrace();
}
System.out.println("Stopped Recording");
}
};
thread.start();
Thread.sleep(record_time*1000);
targetDataLine.stop();
targetDataLine.close();
System.out.println("Ended recording test");
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Above code will stop recording once the record time is elapsed.
But I want another method like below which when invoked from jsp (stop button click) should be able to get the same targetline object which is responsible for current recording and stop the current recording.
Below code does not work for me and recording goes on
public void stop(){
try{
System.out.println("stop :: in stop");
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if(!AudioSystem.isLineSupported(info))
{
System.out.println("Line not supported");}
final TargetDataLine targetDataLine = (TargetDataLine)AudioSystem.getLine(info);
System.out.println("stop Recording....");
System.out.println("targetDataLine.getLineInfo() in stop:::::::"+targetDataLine.getLineInfo());
System.out.println("targetDataLine.isActive() in stop:::::::"+targetDataLine.isActive());
System.out.println("targetDataLine.isOpen() in stop:::::::"+targetDataLine.isOpen());
targetDataLine.stop();
targetDataLine.close();
}
catch (Exception e) {
System.err.println("Line unavailable: " + e);
}
}
Please suggest some resolution.
One more thing that might ..not sure but might has some role to play is the way I am calling these methods from my servlet ..below is the code....
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("buttonName");
String record_time = request.getParameter("time");
System.out.println("action:::"+action +"time in minutes:::"+ record_time);
int record_time_int =(Integer.parseInt(record_time));
String fileName = "studentXYZ.wav";
System.out.println("action:::"+action +"----wavfile:::"+fileName+"time in minutes:::"+ record_time);
Recorder01 record = new Recorder01();
if (action != null && (action.equalsIgnoreCase("Capture")) ){
record.capture(fileName, action,record_time_int);
request.setAttribute("fileName", fileName);
request.getRequestDispatcher("/recordAudio.jsp").forward(request, response);
}
else if (action != null && action.equalsIgnoreCase("play")) {
Recorder01 playsound = new Recorder01();
playsound.play(fileName);
System.out.println("finished playing recording");
request.setAttribute("fileName", fileName);
request.getRequestDispatcher("/recordAudio.jsp").forward(request, response);
}
else if(action!=null && action.equalsIgnoreCase("Stop")){
System.out.println("stop recording called");
record.stop();
request.getRequestDispatcher("/recordAudio.jsp").forward(request, response);
}
}
private TargetDataLine targetDataLine;
public void capture() {
if (targetDataLine == null) {
try {
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Line not supported");
}
targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open();
targetDataLine.start();
Thread thread = new Thread() {
#Override
public void run() {
AudioInputStream audioStream = new AudioInputStream(targetDataLine);
File audioFile = new File(fileName);
System.out.println("Recording is going to get saved in path :::: " + audioFile.getAbsolutePath());
try {
AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, audioFile);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Stopped Recording");
}
};
thread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}
}
public void stop() {
if (targetDataLine != null) {
System.out.println("stop :: in stop");
targetDataLine.stop();
targetDataLine.close();
targetDataLine = null;
}
}

Sound loading working in ubuntu but not working in windows

I have written a method in java to play a sound. It works fine on my ubuntu laptop but doesnt work on windows. There is no error but i think it might be bypassing the drain method on windows for some reason.
public static void runOnce(final String location) {
new Thread(new Runnable() {
public void run() {
try {
File audioFile = new File(Game.gameFolder + "/sounds/" + location);
final AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
final Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.start();
audioClip.drain();
try {
audioClip.close();
audioStream.close();
} catch (Exception e) {
System.out.println("heyeyeyeyye");
}
System.out.println("sound method ran");
} catch(Exception e) {}
}
}).start();
}
thanks -Tyler
EDIT:
i remember actually it worked on windows before i used drain but after a certain amount of time it wouldnt load anymore so i switched to drain
I suggest you use try-with-resources and that you join() the Thread you start and never swallow the message from your Exception. Something like,
public static void runOnce(final String location) {
File audioFile = new File(Game.gameFolder + "/sounds/" + location);
Thread t = new Thread(new Runnable() {
public void run() {
try (AudioInputStream audioStream = AudioSystem
.getAudioInputStream(audioFile);) {
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
try (Clip audioClip = (Clip) AudioSystem.getLine(info);) {
audioClip.open(audioStream);
audioClip.start();
audioClip.drain();
}
System.out.println("heyeyeyeyye");
System.out.println("sound method ran");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
}

extreme lag after having .wav, .au sound in my game?

i tried to search up online there are very limited resources. in the action Performed Method:
actionPerformed(){
---------------
new Sound();}
and in Sound class
public Sound(){
try {
String filePath="path\\file.wav";
File path= new File(filePath);
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
Clip clip;
stream = AudioSystem.getAudioInputStream(path);
format = stream.getFormat();//becomes formatted
info = new DataLine.Info(Clip.class, format);// info
clip = (Clip) AudioSystem.getLine(info);// casting for clip
clip.open(stream); // clip opens stream with path
clip.start();
}
catch (Exception e) {
System.out.println("errors");
}
}
Thank you.
As per the Javadoc of the .start() method:
Allows a line to engage in data I/O. If invoked on a line that is
already running, this method does nothing. Unless the data in the
buffer has been flushed, the line resumes I/O starting with the first
frame that was unprocessed at the time the line was stopped. When
audio capture or playback starts, a START event is generated.
There is no mention of the audio being played in an asynchronous manner. This means that your sound will be tackled by the thread which calls the start method, which since you are calling it in your event handler, will eventually mean that your Event Dispatching Thread is taking care of playing audio.
This thread is also responsible for drawing stuff on screen, so any other thing that runs on it, audio in your case, will have a negative effect on your rendering.
You could use some code like below (taken from here) to make your audio be played on a separate thread. This should cater for your lagging problems.
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AePlayWave extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb
enum Position {
LEFT, RIGHT, NORMAL
};
public AePlayWave(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
public AePlayWave(String wavfile, Position p) {
filename = wavfile;
curPosition = p;
}
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT)
pan.setValue(1.0f);
else if (curPosition == Position.LEFT)
pan.setValue(-1.0f);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
You might want to check out the Lightweight Java Game Library's OpenAL bindings.
It worked very nicely for me when I had to write a game with a large number of sound files.
Other than that, Clips are named Clips for a reason; they're supposed to be very brief and very small, as they're loaded instead of streamed in real-time.
LWJGL:
http://www.lwjgl.org/

How to make sound loop using this method?

I did sound in a REALLY wierd way, do you think that there may be a way to loop it? cuz it only plays once then stops. Here is code for sound:
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class Sound {
private final static int BUFFER_SIZE = 12800000;
private static File soundFile;
private static AudioInputStream audioStream;
private static AudioFormat audioFormat;
private static SourceDataLine sourceLine;
/**
*
* #param filename the name of the file that is going to be played
*
*/
public static void playSound(String filename){
String strFilename = filename;
try {
soundFile = new File(strFilename);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
try {
audioStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e){
e.printStackTrace();
System.exit(1);
}
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
e.printStackTrace();
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
sourceLine.start();
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0, abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
#SuppressWarnings("unused")
int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
}
}
To activate it i do:
new Thread(new Runnable() {
public void run() {
Sound.playSound("hurt.au");
}
}).start();
(if i do just Sound.playSound("hurt.au"); the game freezes because the sound plays on the games main thread so i put the sound in it's own thread to save the game from freezing)
So the question is, how do i loop it?
You will need some sort of test to see whether the sound currently playing is finished or not. If you are making a game, I might suggest using some libraries to make it easier. Such as slick2d. This has inbuilt functions to loop a sound instead of just playing it once. If you choose not to, you will have to keep track of the thread and on every update of your game state look at the sound object and ask the sourceline if it has finished playing or not. If it has then sourceline.start() else no-op. You could also put the thread inside the sound.playsound method itself, thereby making your code a little bit less coupled.
http://www.slick2d.org/
I really recommend using a 3rd party library to make it easier on yourself though.

How can i get beep audio input from mic and process it in java

I want to calculate the max, min and average time for which the beep was high from mic input.
Following is the code to capture an playbak it from mic. But I want to sense the beep sound coming and calculate time of each beep.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class AudioCapture01 extends JFrame{
boolean stopCapture = false;
ByteArrayOutputStream
byteArrayOutputStream;
AudioFormat audioFormat;
TargetDataLine targetDataLine;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
public static void main(String args[]){
new AudioCapture01();
}//end main
public AudioCapture01(){ //constructor
final JButton captureBtn = new JButton("Capture");
final JButton stopBtn = new JButton("Stop");
final JButton playBtn = new JButton("Playback");
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(false);
setResizable(false);
setLocationRelativeTo(null);
//Register anonymous listeners
captureBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
//Capture input data from the microphone until the Stop button is clicked.
captureAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(captureBtn);
stopBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
//Terminate the capturing of input data from the microphone.
stopCapture = true;
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(stopBtn);
playBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//Play back all of the data that was saved during capture.
playAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(playBtn);
getContentPane().setLayout(new FlowLayout());
setTitle("Capture/Playback Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300,70);
setVisible(true);
}//end constructor
//This method captures audio input from a microphone and saves it in a ByteArrayOutputStream object.
private void captureAudio(){
try{
//Get everything set up for capture
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo =new DataLine.Info(TargetDataLine.class,audioFormat);
targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
targetDataLine.open(audioFormat);
targetDataLine.start();
//Create a thread to capture the microphone data and start it
// running. It will run until the Stop button is clicked.
Thread captureThread =new Thread(new CaptureThread());
captureThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end captureAudio method
//This method plays back the audio
// data that has been saved in the
// ByteArrayOutputStream
private void playAudio() {
try{
//Get everything set up for
// playback.
//Get the previously-saved data
// into a byte array object.
byte audioData[] =byteArrayOutputStream.toByteArray();
//Get an input stream on the
// byte array containing the data
InputStream byteArrayInputStream= new ByteArrayInputStream(audioData);
AudioFormat audioFormat =getAudioFormat();
audioInputStream =new AudioInputStream(byteArrayInputStream,audioFormat,audioData.length/audioFormat.getFrameSize());
DataLine.Info dataLineInfo =new DataLine.Info(SourceDataLine.class,audioFormat);
sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
//Create a thread to play back
// the data and start it
// running. It will run until
// all the data has been played
// back.
Thread playThread =new Thread(new PlayThread());
playThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end playAudio
//This method creates and returns an
// AudioFormat object for a given set
// of format parameters. If these
// parameters don't work well for
// you, try some of the other
// allowable parameter values, which
// are shown in comments following
// the declarations.
private AudioFormat getAudioFormat(){
float sampleRate = 8000.0F; //8000,11025,16000,22050,44100
int sampleSizeInBits = 16; //8,16
int channels = 1; //1,2
boolean signed = true; //true,false
boolean bigEndian = false; //true,false
return new AudioFormat(sampleRate,sampleSizeInBits,channels,signed,bigEndian);
}//end getAudioFormat
//===================================//
Inner class to capture data from microphone
class CaptureThread extends Thread {
//An arbitrary-size temporary holding buffer
byte tempBuffer[] = new byte[10000];
public void run(){
byteArrayOutputStream =new ByteArrayOutputStream();
stopCapture = false;
try{//Loop until stopCapture is set
// by another thread that
// services the Stop button.
while(!stopCapture){
//Read data from the internal
// buffer of the data line.
int cnt = targetDataLine.read(tempBuffer,0,tempBuffer.length);
if(cnt > 0){
//Save data in output stream object.
byteArrayOutputStream.write(tempBuffer, 0, cnt);
}//end if
}//end while
byteArrayOutputStream.close();
}catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end run
}//end inner class CaptureThread
//===================================//
//Inner class to play back the data that was saved.
class PlayThread extends Thread{
byte tempBuffer[] = new byte[10000];
public void run(){
try{
int cnt;
//Keep looping until the input read method returns -1 for empty stream.
while((cnt = audioInputStream.
read(tempBuffer, 0,
tempBuffer.length)) != -1){
if(cnt > 0){
//Write data to the internal buffer of the data line
// where it will be delivered to the speaker.
sourceDataLine.write(tempBuffer, 0, cnt);
}//end if
}//end while
//Block and wait for internal buffer of the data line to empty.
sourceDataLine.drain();
sourceDataLine.close();
}catch (Exception e) {
System.out.println(e);
System.exit(0);
}//end catch
}//end run
}//end inner class PlayThread
}//end outer class AudioCapture01.java
I am able to capture and playback the audio but I can't sense the audio. Any help will be appreciated.

Categories