How to ask for user input while playing audio? - java

I am trying to create a program that will play a audio file. During the time audio file is playing, a user will then start to give input (integers) and if the input is right, the audio will stop. For eg: audio will play and if user presses 5 during the audio playing then audio will stop. The problem I have below is that the audio will play and only after it stops will it ask for the input. Please help.
public static void main(String[] args) {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/C1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
Scanner reader = new Scanner(System.in);
System.out.println("Enter the first number");
int a = reader.nextInt();
if (a ==5){
clip.stop();
}
} catch(Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}

Related

Java AudioSystem prevent loop from repeating before song finishes

I have a program that will ask the user which songs they want to play out of a list of available songs and after the user selects one once the song finishes it asks the user which song they want to play again. My question is how do I prevent the loop from asking the user which song they want to play until the selected song is finished so they don't repeat?
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String[] pathnames;
File MusicFileChosen;
String musicDir;
boolean songComplete = false;
pathnames = ProgramMap.musicDir.list();
// Print the names of files and directories
for (int ListNum = 0; ListNum < pathnames.length; ListNum++) {
System.out.println(ListNum + 1 + ". " + pathnames[ListNum]);
}
for (int playlistLength = 0; playlistLength < pathnames.length; playlistLength++){
if (!songComplete) {
System.out.println("Which Song would you like to play?");
int musicChoice = input.nextInt();
musicDir = ProgramMap.userDir + "\\src\\Music\\" + pathnames[musicChoice - 1];
MusicFileChosen = new File(musicDir);
PlaySound(MusicFileChosen, pathnames[musicChoice - 1]);
}
}
}
public static void PlaySound(File sound, String FileName){
try{
// Inits the Audio System
Clip clip = AudioSystem.getClip();
AudioInputStream AudioInput = AudioSystem.getAudioInputStream(sound);
//Finds and accesses the clip
clip.open(AudioInput);
//Starts the clip
clip.start();
System.out.println("Now Playing " + FileName);
clip.drain();
}catch (Exception e){
System.out.println("Error playing music");
}
}
}
You can use a LineListener. Then, register and listen for LineEvent.Type.CLOSE.
By the way, you might do better to use SourceDataLine than Clip. Maybe not a big deal, but given what you've coded, there could be audible lag, depending on the size of the file, every time you open a clip and load the complete file into memory (this has to be completed before playing can start). The SourceDataLine will commence playing almost immediately (only loads one buffer before starting to play) and only consumes the one buffer of memory instead of the entire sound file.
A lot of people that are new to javax.sound.sampled are wary of using SourceDataLine but it really isn't that much more difficult to code than a Clip, and for the use you are showing, it would be a better fit.

Recording speakers Ouput using Java

I want to ask the repetitive question of how to record the audio send to the speakers. But I want some insights to the previously answered.
I went to this page: Capturing speaker output in Java
I saw this code posted by a developer:
import javax.sound.sampled.*;
import java.io.*;
public class JavaSoundRecorder {
// record duration, in milliseconds
static final long RECORD_TIME = 10000; // 1 minute
// path of the wav file
File wavFile = new File("E:/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 = 1;
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();
}
}
Now I have some questions I want to ask.
This code runs OK on my windows OS but it doesn't work on my Ubuntu on the same machine(dual boot). In Ubuntu it records silence and I tried to get all mixers but can't get it working
I want to get the output going to the speakers and I am getting the output of the speakers. The sound of the vicinity with a very little sound of what I actually want.
Please answer my queries of the above 2 questions.
What I want? I want the clear audio that is currently being played and fetched to the speakers of my laptop. I don't want the audio that is already emitted and then re-recorded because that is bad. Also I need a reason as of why my Ubuntu is not supporting this code.(This is vague info but I am using BlueJ in windows to run this and NetBeans on Ubuntu(without sudo)).
I saw some YouTube videos to understand the theory:
https://www.youtube.com/watch?v=GVtl19L9GxU
https://www.youtube.com/watch?v=PTs01qr9RlY
I read 1 and a half page documentation of oracle here: https://docs.oracle.com/javase/tutorial/sound/accessing.html
There was this thing mentioned in the docs:
An applet running with the applet security manager can play, but not record, audio.
An application running with no security manager can both play and record audio.
An application running with the default security manager can play, but not record, audio.
But I don't think I turned any security manager.
In the end I found no success in what I want to do. Instead of going further in the documentation I thought to ask the question here.

set time interval between repeating audio clip in java when using clip.loop(Clip.LOOP_CONTINUOUSLY);

I am trying to loop a small ".wav" audio file. The code I used worked perfectly but I want to set some time interval between looping audio. Code is provided below.
try {
// from a wave File
File soundFile = new File("path");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
clip = AudioSystem.getClip();
clip.open(audioIn);
clip.loop(Clip.LOOP_CONTINUOUSLY); //IS THERE ANY WAY TO CREATE TIME INTERVAL???
} catch (Exception e) {
JOptionPane.showMessageDialog(null,
"Hi. This is background music error \n" + e);
}
while (playing)
{
yourBeepClip.setFramePosition(0);
yourBeepClip.start();
Thread.sleep(pauseAmount);
}
The Clip is only instantiated & opened ONE TIME.
Also, the above while loop is assumed to be occurring in its own thread.

Multithreading only way to play background music in Java?

I have a game with game logic happening in the main. I just added sound playing as per documentation I found:
//////////////////////SOUND/////////////////////////
SourceDataLine soundLine = null;
int BUFFER_SIZE = 64*1024; // 64 KB
// Set up an audio input stream piped from the sound file.
try {
File soundFile = new File("tim ph3 samplepart1.wav");
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
AudioFormat audioFormat = audioInputStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
soundLine = (SourceDataLine) AudioSystem.getLine(info);
soundLine.open(audioFormat);
soundLine.start();
int nBytesRead = 0;
byte[] sampledData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(sampledData, 0, sampledData.length);
if (nBytesRead >= 0) {
// Writes audio data to the mixer via this source data line.
soundLine.write(sampledData, 0, nBytesRead);
}
}
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} finally {
soundLine.drain();
soundLine.close();
}
/////////////////////////////////////////////////////
It plays the file I specified out of the files in my project folder in Eclipse.
The problem? It blocks all game logic after it that appears in the main.
This makes sense - the program is sequential and until the ENTIRE song is done...I figure the game can't go on.
This obviously isn't going to work, and it appears I'm going to have to go to dreaded multithreading...BUT BEFORE I DO...I wonder...is there a Java library or some other clever solution to avoid multithreading in this case?
Yes, you need to use a separate thread. There's nothing to be afraid of. Multithreading in Java is a piece of cake. Look at the Concurrency packages.
http://docs.oracle.com/javase/tutorial/essential/concurrency/
Beware: knowing how to start a thread and knowing how to safely multithread your programs are 2 different things. For now, make sure you avoid touching the same music from multiple threads.

Capturing speaker output in Java

Using Java is it possible to capture the speaker output? This output is not being generated by my program but rather by other running applications. Can this be done with Java or will I need to resort to C/C++?
I had a Java based app. that used Java Sound to tap into the sound flowing through the system to make a trace of it. It worked well on my own (Windows based) machine, but failed completely on some others.
It was determined that in order to get it working on those machines, would take nothing short of an audio loop-back in either software or hardware (e.g. connect a lead from the speaker 'out' jack to the microphone 'in' jack).
Since all I really wanted to do was plot the trace for music, and I figured how to play the target format (MP3) in Java, it became unnecessary to pursue the other option further.
(And I also heard that Java Sound on Mac. was horribly broken, but I never looked closely into it.)
Java is not the best tool when dealing with the OS. If you need/want to use it for this task, probably you will end using Java Native Interface (JNI), linking to libraries compiled in other languages (probably c/c++).
Take an AUX cable, connect to HEADPHONE JACK and other end to MICROPHONE JACK and run this code
https://www.codejava.net/coding/capture-and-record-sound-into-wav-file-with-java-sound-api
import javax.sound.sampled.*;
import java.io.*;
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();
}
}

Categories

Resources