I'm quite a newbie in JAVA and I am trying to read a clip. Here is my code :
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
public class TestClipBis {
protected static AudioFormat audioFormat;
public static void main(String[] args) throws Exception {
// Specification of the sound to play
// No control. We assume that the sound can be played on audio system
//File soundFile = new File("chimes.wav");
File soundFile = new File("test.wav");
InputStream is = new FileInputStream(soundFile);
InputStream bufferedIn = new BufferedInputStream(is);
//AudioInputStream sound = AudioSystem.getAudioInputStream(soundFile);
AudioInputStream sound = AudioSystem.getAudioInputStream(bufferedIn);
audioFormat = sound.getFormat();
System.out.println(audioFormat);
// Loading the sound into the memory (a Clip)
DataLine.Info info = new DataLine.Info(Clip.class, sound.getFormat());
System.out.println(info);
//Clip clip = (Clip) AudioSystem.getClip();
Clip clip = (Clip) AudioSystem.getLine(info);
System.out.println("Sound frame lenght : "+sound.getFrameLength());
System.out.println("Clip FrameLength before opening : "+clip.getFrameLength());
System.out.println("Clip will open - "+info);
System.out.println("Info format : "+info.getLineClass());
// Check before this line that everything is in memory
// Yes, but how ?
clip.open(sound);
System.out.println("Clip is open");
System.out.println("Clip FrameLength after opening : "+clip.getFrameLength());
// Due to a bug in Java Sound,
// we explicitly out of the VM when the sounds stop
clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
System.out.println("Methode de sortie");
event.getLine().close();
System.exit(0);
}
}
});
// Playing the clip
clip.start();
System.out.println("IsActive : "+clip.isActive());
//clip.close();
}
}
My problem is how to be sure that the clip is loaded in memory before opening and playing it ? With the above code, when I open and play the sound file, I have few seconds of playing but never the same length, randomly, and never the full song.
Or should I use something else than a clip to play a song? But I want to "move" into the song and not only streaming it from the start to the end.
Edit:
Ok, I tried few things. First, I tried to see if the "ByteArrayOuptputStream" was written. I had a "println" in the loop and yes, all is written but it don't fix the problem.
Then, when I open the clip, I tried to add the parameters : audioformat, bytearray, startpoint, bufferlength. Nothing better.
Then, I noticed that when the sounds stop, the method to exit was used. So, I tried to "mute" that method (with comment signs). The result is different : it read the file but the sound is jerky. And when I check the CPU use, it's around 100%. Is it a first clue to guess what's the problem ?
I tried to make a loop that indicates the frameposition after the start : all the frames are read but the sound is still jerky. I also tried the thead.sleep before and after the start method : nothing better.
So, here is the code I use. Many code parts are between "comment quotes" because they are try, unsuccessfull...
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
public class TestBufferedClip {
protected static AudioFormat audioFormat;
public static ByteBuffer buffer;
public static void main(String[] args) throws Exception {
// Specification of the sound to play
// No control. We assume that the sound can be played on audio system
//File soundFile = new File("chimes.wav");
File soundFile = new File("test.wav");
FileInputStream fis = new FileInputStream(soundFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream((int)soundFile.length());
byte[] buf = new byte[1024];
int n = 0;
int loop = 0;
while ((n=fis.read(buf))>=0) {
baos.write(buf);
buf=new byte[1024];
System.out.println("Loop = "+loop);
loop+=1;
}
byte[] ba = baos.toByteArray();
System.out.println("ByteArray size : "+ba.length);
ByteArrayInputStream bais = new ByteArrayInputStream(ba);
//AudioInputStream sound = AudioSystem.getAudioInputStream(soundFile);
AudioInputStream sound = AudioSystem.getAudioInputStream(bais);
audioFormat = sound.getFormat();
System.out.println(audioFormat);
// Loading the sound into the memory (a Clip)
DataLine.Info info = new DataLine.Info(Clip.class, sound.getFormat());
System.out.println("Info :"+info);
//Clip clip = (Clip) AudioSystem.getClip();
Clip clip = (Clip) AudioSystem.getLine(info);
System.out.println("Sound frame lenght : "+sound.getFrameLength());
System.out.println("Info format : "+info.getLineClass());
// Check before this line that everything is in memory
// Yes, but how ?
clip.open(audioFormat, ba, 0, ba.length);
//clip.open(sound);
System.out.println("Clip is open");
System.out.println("Clip FrameLength after opening : "+clip.getFrameLength());
// Due to a bug in Java Sound,
// we explicitly out of the VM when the sounds stop
/*
clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
System.out.println("Methode de sortie");
event.getLine().close();
System.exit(0);
}
}
});
*/
// Playing the clip
System.out.println("Before thread sleep");
try {
Thread.sleep(31000);
} catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("After thread sleep");
clip.start();
System.out.println("IsActive : "+clip.isActive());
/*
while (clip.isActive()==true) {
System.out.println("Position = "+clip.getFramePosition());
}
*/
//clip.close();
}
}
@Phil Freihofner :
I thought about your solution to read and discards data until I reach my "start" point. You wrote "In order to start at a point within the audio file, using a SourceDataLine, you would have to read and discard data from the audio input line until you got to the desired starting spot". How do you do that ? When I use the "SourceDataLine" method, my start method is a loop with a line.write(bytes, 0, bytesreads); to point the sound on the speakers.
So, how do you just read and discard ? I didn't find any "read" method with the line.