I'm trying to make music play with one button(First click is play, second is stop, third is play again etc etc). The problem is it does not want to stop. Second click is blank and then third music starts to impose itself. Any suggestions?
public void music() {
File file = new File("music.wav");
AudioInputStream audioStream = null;
Clip clip = null;
try {
audioStream = AudioSystem.getAudioInputStream(file);
clip = AudioSystem.getClip();
clip.open(audioStream);
} catch (LineUnavailableException e) {
throw new RuntimeException(e);
} catch (UnsupportedAudioFileException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (m % 2 == 1) {
clip.start();
m++;
} else {
clip.stop();
m++;
}
}
public void playmusic() {
if(m%2==1) {
File file = new File("music.wav");
AudioInputStream audioStream = null;
try {
audioStream = AudioSystem.getAudioInputStream(file);
clip = AudioSystem.getClip();
clip.open(audioStream);
} catch (LineUnavailableException e) {
throw new RuntimeException(e);
} catch (UnsupportedAudioFileException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
clip.start();
m++;
}
else {
clip.stop();
m++;
}
}
I did it like this, thanks for helping Karl. To be honest it still feels overly complicated. I just don't know the tools to do it better.
I'm making anti-phase sound with java.(anti-phase is reflected wave. x-coordinate is not changed, but y-coordinate is upside down.)
Before reflecting sound wave, I have to get byte array(or int array) from sound.
I get sound from microphone of my laptop.
Here is my CODE(I got original code, which record sound as file, in web. I modified it little)
public class NoiseController extends Thread{
private TargetDataLine line;
private AudioInputStream audioInputStream;
public NoiseController(TargetDataLine line) {
this.line = line;
this.audioInputStream = new AudioInputStream(line);
}
public void start() {
line.start();
super.start();
}
public void stopRecording() {
line.stop();
line.close();
}
public void run() {
try {
int packet;
while((packet = audioInputStream.read()) != -1)
System.out.println(packet);
}
catch(IOException ioe) {
ioe.getStackTrace();
}
}
public static void main(String[] args) {
AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 2, 4, 44100.0F, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
TargetDataLine targetDataLine = null;
try {
targetDataLine = (TargetDataLine)AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
}
catch(LineUnavailableException lue) {
out("unable to get a recording line");
lue.printStackTrace();
System.exit(-1);
}
AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;
NoiseController recorder = new NoiseController(targetDataLine);
System.out.println(targetDataLine);
System.out.println(targetType);
out("Press ENTER to start the recording.");
try {
System.in.read();
}
catch(IOException ioe) {
ioe.printStackTrace();
}
recorder.start();
out("Recording...");
out("Press ENTER to stop the recording.");
try {
System.in.read();
System.in.read();
}
catch(IOException ioe) {
ioe.getStackTrace();
}
recorder.stopRecording();
out("Recording stopped.");
}
private static void out(String msg) {
System.out.println(msg);
}
}
However, Console doesn't print anything while recording...
It shows just
com.sun.media.sound.DirectAudioDevice$DirectTDL#25154f_
WAVE
Press ENTER to start the recording.
Recording...
Press ENTER to stop the recording.
Recording stopped.
If I edit run() like AudioSystem.write(stream, fileType, out);
instead of
int packet;
while((packet = audioInputStream.read()) != -1)
System.out.println(packet);
program saves wav file.
What is wrong in my program?
you are not printing the Exception as Uwe Allner said.
I´ve also try to correct it and I think the result must be like this:
public class NoiseController extends Thread {
private final TargetDataLine line;
private final AudioInputStream audioInputStream;
public NoiseController(final TargetDataLine line) {
this.line = line;
this.audioInputStream = new AudioInputStream(line);
}
#Override
public void start() {
line.start();
super.start();
}
public void stopRecording() {
line.stop();
line.close();
try {
audioInputStream.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
final int bufferSize = 1024;
int read = 0;
final byte[] frame = new byte[bufferSize];
while ((read = audioInputStream.read(frame)) != -1 && line.isOpen()) {
// only the first read bytes are valid
System.out.println(Arrays.toString(frame));
}
} catch (final IOException ioe) {
ioe.printStackTrace();
}
}
public static void main(final String[] args) {
final AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 2, 4, 44100.0F, false);
final DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
TargetDataLine targetDataLine = null;
try {
targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
} catch (final LineUnavailableException lue) {
out("unable to get a recording line");
lue.printStackTrace();
System.exit(-1);
}
final AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;
final NoiseController recorder = new NoiseController(targetDataLine);
System.out.println(targetDataLine);
System.out.println(targetType);
out("Press ENTER to start the recording.");
try {
System.in.read();
} catch (final IOException ioe) {
ioe.printStackTrace();
}
recorder.start();
out("Recording...");
out("Press ENTER to stop the recording.");
try {
System.in.read();
System.in.read();
} catch (final IOException ioe) {
ioe.printStackTrace();
}
recorder.stopRecording();
out("Recording stopped.");
}
private static void out(final String msg) {
System.out.println(msg);
}
}
I am developing a drum metronome. So I have .wav sound files and I need to play them with using minimum computer memory and CPU because it's very important for the metronome to play the sample on the exact time. Currently I use the code from this link
How to play .wav files with java
class MakeSound {
private final int BUFFER_SIZE = 128000;
private File soundFile;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
/**
* #param filename the name of the file that is going to be played
*/
public 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();
}
}
This code works but it's too slow for using it in a metronome app. So which is the fastest way of playing wav sound files. Please take into account that sometimes I need to play them simultaneously so the sound should play as a separate thread I think.
Thanks
i am assuming that you have a working method that looks like this:
example #1: (don't do this)
public void startMetronome(){
boolean abort = false;
String audoFileName = new String("myAudioFile);
do{
playSound(audoFileName );
while(abort != false);
}
or maybe you've done some better implementation like this:
exapmle#2: (don't do this either)
Runnable r = new Runnable(){
boolean abort = false;
String audoFileName = new String("myAudioFile);
do{
playSound(audoFileName );
try{
Thread.sleep(500);
}catch (Exception e);
while(abort != false);
}
new Thread(r).start();
in any case you're doing a big mistake: you initialize every time you play a sound the sound line and every time you load the file again and again.
but thats a toally wrong approach, you have to load the file once, open the line once and play the sound repetially on the line!
(cheap) solution #3:
adjust your playSoundmethode like this:
public void playSound(String filename){
//same as above
String strFilename = filename;
soundFile = new File(strFilename); //i've shorened the catch/throws, to make it more readable
audioStream = AudioSystem.getAudioInputStream(soundFile);
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
sourceLine.start();
//right now, the line is set up and all data is availible
boolean isRunning = true;
while(isRunning){ //this is an endless loop!
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
nBytesRead = audioStream.read(abData, 0, abData.length);
//and your timing here
try{
Thread.sleep(500);
}catch (Exception e);
}
sourceLine.drain();
sourceLine.close();
}
and best practice would be to play the whole thing in an seperate thread... (as example #2)
I am trying to write a little program that reads a wav file and sends the output as if it would come from my microphone. Unfortunately I do not have much experience with the sound API.
Background: What I am basically trying to realize is a program that plays a sound while I am in a voicechat (i.e Teamspeak, Ventrilo). To get that to work now I would have to switch the recording device to "What you hear", play the sound and then switch back to microphone. The program should simulate input from the microphone.
So far I could not get any further than just playing the sound. I guess I just need a different SourceLine?
public class Player {
private final int BUFFER_SIZE = 128000;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
public void playSound(File soundFile) {
try {
audioStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
audioFormat = audioStream.getFormat();
DataLine.Info infoIn = new DataLine.Info(SourceDataLine.class,
audioFormat);
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(infoIn);
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();
}
}
Solution:
Install VB Audio Cable (http://vb-audio.pagesperso-orange.fr/Cable/). It's donationware. Make VB-Output standard recording device. In the microphone properties choose VB-Input as playback.
public class Player {
private final int BUFFER_SIZE = 128000;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
public void playSound(File soundFile) {
try {
audioStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
audioFormat = audioStream.getFormat();
DataLine.Info infoIn = new DataLine.Info(SourceDataLine.class,
audioFormat);
try {
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
Mixer mixer = null;
for (int i = 0; i < mixerInfos.length; i++) {
System.out.println(mixerInfos[i].getName());
if (mixerInfos[i].getName().equals(
"CABLE Input (VB-Audio Virtual Cable)")) {
mixer = AudioSystem.getMixer(mixerInfos[i]);
break;
}
}
sourceLine = (SourceDataLine) mixer.getLine(infoIn);
sourceLine.open(audioFormat);
} catch (LineUnavailableException 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();
}
}
You can install some program like Virtual Audio Cable and from your music player redirect playing sound to virtual input. In your program you must listen that virtual input source and you can for test redirect to normal headphones or speaker received signal or saved it to file.
I am trying to play a *.wav file with Java. I want it to do the following:
When a button is pressed, play a short beep sound.
I have googled it, but most of the code wasn't working. Can someone give me a simple code snippet to play a .wav file?
Finally I managed to do the following and it works fine
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 MakeSound {
private final int BUFFER_SIZE = 128000;
private File soundFile;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
/**
* #param filename the name of the file that is going to be played
*/
public 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();
}
}
Here is the most elegant form I could come up without using sun.*:
import java.io.*;
import javax.sound.sampled.*;
try {
File yourFile;
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
Clip clip;
stream = AudioSystem.getAudioInputStream(yourFile);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
clip.start();
}
catch (Exception e) {
//whatevers
}
Shortest form (without having to install random libraries) ?
public static void play(String filename)
{
try
{
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File(filename)));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
The only problem is there is no good way to make this method blocking to close and dispose the data after *.wav finishes.
clip.drain() says it's blocking but it's not. The clip isn't running RIGHT AFTER start().
The only working but UGLY way I found is:
// ...
clip.start();
while (!clip.isRunning())
Thread.sleep(10);
while (clip.isRunning())
Thread.sleep(10);
clip.close();
You can use an event listener to close the clip after it is played
import java.io.File;
import javax.sound.sampled.*;
public void play(File file)
{
try
{
final Clip clip = (Clip)AudioSystem.getLine(new Line.Info(Clip.class));
clip.addLineListener(new LineListener()
{
#Override
public void update(LineEvent event)
{
if (event.getType() == LineEvent.Type.STOP)
clip.close();
}
});
clip.open(AudioSystem.getAudioInputStream(file));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
The snippet here works fine, tested with windows sound:
public static void main(String[] args) {
AePlayWave aw = new AePlayWave( "C:\\WINDOWS\\Media\\tada.wav" );
aw.start();
}
A class that will play a WAV file, blocking until the sound has finished playing:
class Sound implements Playable {
private final Path wavPath;
private final CyclicBarrier barrier = new CyclicBarrier(2);
Sound(final Path wavPath) {
this.wavPath = wavPath;
}
#Override
public void play() throws LineUnavailableException, IOException, UnsupportedAudioFileException {
try (final AudioInputStream audioIn = AudioSystem.getAudioInputStream(wavPath.toFile());
final Clip clip = AudioSystem.getClip()) {
listenForEndOf(clip);
clip.open(audioIn);
clip.start();
waitForSoundEnd();
}
}
private void listenForEndOf(final Clip clip) {
clip.addLineListener(event -> {
if (event.getType() == LineEvent.Type.STOP) waitOnBarrier();
});
}
private void waitOnBarrier() {
try {
barrier.await();
} catch (final InterruptedException ignored) {
} catch (final BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
private void waitForSoundEnd() {
waitOnBarrier();
}
}
Another way of doing it with AudioInputStream:
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
public class CoreJavaSound extends Object implements LineListener {
File soundFile;
JDialog playingDialog;
Clip clip;
public static void main(String[] args) throws Exception {
CoreJavaSound s = new CoreJavaSound();
}
public CoreJavaSound() throws Exception {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
soundFile = chooser.getSelectedFile();
System.out.println("Playing " + soundFile.getName());
Line.Info linfo = new Line.Info(Clip.class);
Line line = AudioSystem.getLine(linfo);
clip = (Clip) line;
clip.addLineListener(this);
AudioInputStream ais = AudioSystem.getAudioInputStream(soundFile);
clip.open(ais);
clip.start();
}
public void update(LineEvent le) {
LineEvent.Type type = le.getType();
if (type == LineEvent.Type.OPEN) {
System.out.println("OPEN");
} else if (type == LineEvent.Type.CLOSE) {
System.out.println("CLOSE");
System.exit(0);
} else if (type == LineEvent.Type.START) {
System.out.println("START");
playingDialog.setVisible(true);
} else if (type == LineEvent.Type.STOP) {
System.out.println("STOP");
playingDialog.setVisible(false);
clip.close();
}
}
}
A solution without java reflection DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat)
Java reflection decrease performance.
to run: java playsound absoluteFilePathTo/file.wav
import javax.sound.sampled.*;
import java.io.*;
public class playsound {
public static void main (String args[]) throws Exception {
playSound (args[0]);
}
public static void playSound () throws Exception {
AudioInputStream
audioStream = AudioSystem.getAudioInputStream(new File (filename));
int BUFFER_SIZE = 128000;
AudioFormat audioFormat = null;
SourceDataLine sourceLine = null;
audioFormat = audioStream.getFormat();
sourceLine = AudioSystem.getSourceDataLine(audioFormat);
sourceLine.open(audioFormat);
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) {
int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
}
}
You can use AudioStream this way as well:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class AudioWizz extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L; //you like your cereal and the program likes their "serial"
static AudioWizz a;
static JButton playBuddon;
static JFrame frame;
public static void main(String arguments[]){
frame= new JFrame("AudioWizz");
frame.setSize(300,300);
frame.setVisible(true);
a= new AudioWizz();
playBuddon= new JButton("PUSH ME");
playBuddon.setBounds(10,10,80,30);
playBuddon.addActionListener(a);
frame.add(playBuddon);
frame.add(a);
}
public void actionPerformed(ActionEvent e){ //an eventListener
if (e.getSource() == playBuddon) {
try {
InputStream in = new FileInputStream("*.wav");
AudioStream sound = new AudioStream(in);
AudioPlayer.player.start(sound);
} catch(FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
I took #greenLizard's code and made it more robust.
I closed the AudioInputStream.
I used a BufferedInputStream. The AudioSystem getAudioInputStream was throwing an occasional IOException because the getAutoInputSytream method couldn't back up the input stream and start over.
Hopefully, there are no more exceptions to be found.
Here's the modified code. The ErrorDisplayDialog shows an exception as a JDialog in a Java Swing application. Just replace with e.printStackTrace();.
private void playWavFile(String fileName) {
InputStream inputStream = getClass().getResourceAsStream(fileName);
BufferedInputStream bufferedInputStream = new BufferedInputStream(
inputStream);
AudioInputStream audioStream = null;
AudioFormat audioFormat = null;
try {
audioStream = AudioSystem.getAudioInputStream(bufferedInputStream);
audioFormat = audioStream.getFormat();
} catch (UnsupportedAudioFileException e) {
new ErrorDisplayDialog(view.getFrame(),
"UnsupportedAudioFileException", e);
return;
} catch (IOException e) {
new ErrorDisplayDialog(view.getFrame(), "IOException", e);
return;
}
DataLine.Info info = new DataLine.Info(SourceDataLine.class,
audioFormat);
SourceDataLine sourceLine;
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
new ErrorDisplayDialog(view.getFrame(), "LineUnavailableException",
e);
return;
}
sourceLine.start();
int nBytesRead = 0;
byte[] abData = new byte[128000];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0, abData.length);
} catch (IOException e) {
new ErrorDisplayDialog(view.getFrame(), "IOException", e);
return;
}
if (nBytesRead >= 0) {
sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
try {
audioStream.close();
} catch (IOException e) {
new ErrorDisplayDialog(view.getFrame(), "IOException", e);
}
}