I'm coding something with an audio part with WAV Files and after 2 days of searching for a bug, I really don't know where the problem is. I guess my thread doesn't stop and that prevents me from deleting a file, but when I'm debugging everything goes well and I've no exceptions or errors.
Here is my interface:
Picture of my interface
So when I want to delete a file by clicking on delete button that launches 'DeleteTrack' method and it works, but when I listen to it first thanks to listen button that launches 'PlaySound' method, I can't delete it, it's like if nothing happen.
Also, when I use 'PlaySound' and then I try to delete my file from windows I have this:
Windows error
Thank you for reading and I'll be very grateful if you could help me and sorry if my English isn't perfect.
GatherFiles method just return my list of waves I've verified it's not null
MajListAudio method refresh my list if I add or delete a song
public void DeleteTrack() {
String song_name = audioList.getSelectedValue();
File[] listeOfFiles = GatherFiles(null);
// Loop to find the file to delete and then delete it.
for(int i=0;i<listeOfFiles.length;i++){
if(song_name.equals(listeOfFiles[i].getName())){
listeOfFiles[i].delete();
}
}
// Refresh the list
MajListAudio();
}
}
So here is the function when I guess there is a problem.
public void PlaySound(File sound){
thread = new Thread(){
#Override public void run(){
try {
// Initialize a clip with our sound file
AudioInputStream audioStream = AudioSystem.getAudioInputStream(sound);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
// Variable that will updated to fix the percentage of the progressBar
int progressContains =0;
// Size in Seconds of our music
int sizeAudio = (int) (clip.getMicrosecondLength()/1000000);
clip.start();
do{
// indice allow us to know how much the progress bar has to grow every second. We divide with 100 because it's the maximum
//of the bar
int indice = 100/sizeAudio;
// Refresh the value of the bar and prepare her next value
progressBar.setValue(progressContains);
progressContains+= indice;
// The main thread is sleeping for 1s
Thread.sleep(1000);
}while(clip.isActive());
//Reset the bar after a play
clip.stop();
clip.close();
audioStream.close();
progressBar.setValue(0);
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
};
thread.start();
}
Others functions
public File[] GatherFiles(DefaultListModel myModel){
// If you want to get the list without implementing the model
if(myModel == null){
File[] both = Concatenate(getListOfFiles("\\cryptedAudio"), getListOfFiles("\\audio"));
return both;
// Same with a model
}else{
audioList.setModel(myModel);
File[] both = Concatenate(getListOfFiles("\\cryptedAudio"), getListOfFiles("\\audio"));
return both;
}
}
public File[] getListOfFiles(String endPath){
String folderPath = new File(".").getAbsolutePath();
folderPath= folderPath.substring(0, folderPath.length()-1);
File folder = new File(folderPath+endPath);
File[] listeOfFiles = folder.listFiles();
return listeOfFiles;
}
/*
*Return a new Array that contains borh arrays in parameters
*/
public <T> T[] Concatenate (T[] a, T[] b) {
int aLen = a.length;
int bLen = b.length;
#SuppressWarnings("unchecked")
T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen+bLen);
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
I really suspect your threading is an issue. You wait one second after the sound finishes, at the very least. So maybe your delete happens too soon. One way around this, is to read everything from the file, and then make the sound. That way the file should always be closed.
byte[] bytes = Files.readAllBytes(sound.toPath());
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(bytes)
);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
Since your problem appears to be your file not getting released to the system, we use File.readAllbytes which reads the whole file, and release it back to the OS before you even play a sound.
The concept behind your original setup should work, but it appears that your loop does not finish before you try and delete the file. It could also be that you start more than one thread to access the file.
Have you tried something like
AudioInputStream audioStream = AudioSystem.getAudioInputStream(sound);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
// play the audio...
clip.close();
audioStream.close();
This is just making sure that the AudioInputStream is getting closed properly since I'm not sure that clip.close() is closing it (though one would think it should...)
This method API AudioSystem.getAudioInputStream(sound) returns an AudioInputStream that you should close.
So better if you first assign the returned value to a local variable:
AudioInputStream inputAudioStream = AudioSystem.getAudioInputStream(sound);
And then you can open it using the clip instance:
Clip clip = AudioSystem.getClip();
clip.open(inputAudioStream);
Finally don't forget to close the inputAudioStream variable:
clip.close();
inputAudioStream.close();
I strongly suggest to use the try-with-resources Statement
try(AudioInputStream inputAudioStream = AudioSystem.getAudioInputStream(sound)) {
// Initialize a clip with our sound file
Clip clip = AudioSystem.getClip();
clip.open(inputAudioStream);
[.... ] your code
clip.close();
progressBar.setValue(0);
}
[.... ] your catch code
Related
I am trying to make a program that plays sound back to you. How I got the sound was I went to this link and I had it speak some words for about 9 seconds. While he was speaking, I was recording him with Audacity. It recorded him at 16-bit PCM, 48 khz and a stereo channel.
The code I use to play the sound is,
public void playSound(String Path) {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(Variables.class.getResourceAsStream("/com/project/resources/" + Path));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
}
}
and the error that pops up is at this link.
I have stored the file in another package located at com.project.resources.
If you have any questions about this situation, let me know.
I'm trying to write a file from an AudioInputStream. The stream can read the original file just fine (as far as I can tell). But when it tries to write, it writes what should be a 15 KB file in 44 bytes. Windows Media Player gives the error "either the file type is unsupported, or WMP doesn't recognize the codec used to convert the file."
I got most of this code from http://docs.oracle.com/javase/tutorial/sound/converters.html. I've looked all over StackOverflow but nothing seemed to pertain to this problem.
I've tried getting the format of the AudioInputStream and it's definitely a .wav. As far as I can tell, a codec is software that converts analog to digital data, and both the wav file and the AudioInputStream are digital already.
EDIT: It looks like the stream is writing the WAVE file header to my new file, but nothing else. That's where my 44 byte file is coming from.
Here's the code. I think the problem is in writeFile() but I included the rest just in case:
public static void getFile()
{
try
{
File test = new File("C:\\Users\\Audrey\\Steganography\\correctamundo.wav"); //file to be written from
AudioInputStream stream = AudioSystem.getAudioInputStream(test);
AudioFileFormat format = AudioSystem.getAudioFileFormat(test);
int bytesPerFrame = stream.getFormat().getFrameSize();
byte[] b = new byte[30000]; //array of arbitrary size to hold the bytes in stream
if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) //not sure why this is necessary
{
bytesPerFrame = 1;
}
int i = 0;
while(stream.available() > 0)
{
byte currentByte = (byte)stream.read();
b[i] = currentByte; //read bytes to array
System.out.println(b[i] + " " +(i+1)); //test statement
i++;
}
writeFile(format, stream);
} catch (IOException | UnsupportedAudioFileException e)
{
e.printStackTrace();
}
}
public static void writeFile (AudioFileFormat format, AudioInputStream stream) //format and stream created in getFile() under the same names
{
try
{
File fileOut = new File("C:\\Users\\Audrey\\Steganography\\testFile2.wav");
AudioFileFormat.Type fileType = format.getType(); //type of file the AudioInputStream can write to, since format refers to stream
if (AudioSystem.isFileTypeSupported(fileType, stream))
{
AudioSystem.write(stream, fileType, fileOut);
System.out.println(stream.getFrameLength()); //test statement
}
System.out.println(fileType); //test statement
}
catch (IOException e)
{
e.printStackTrace();
}
}
For my parents I am writing a simple program to copy files from their digital photocamera to their 'My Documents' folder. They always need my help (they are not so technically advanced) to get their pictures off their camera so I decided to help them out. I called it The Copying Machine. Since I couldn't find a suitable USB-Listener in Java, I wrote one myself:
private void sync()
{
// All devices in an ArrayList
File[] roots = File.listRoots();
ArrayList<File> newList = new ArrayList<File>();
for(File f : roots)
{
newList.add(f);
}
// Delete unavailable devices
ArrayList<File> removeThese = new ArrayList<File>();
for(File f : devices)
{
if(!newList.contains(f))
{
removeThese.add(f);
}
}
devices.removeAll(removeThese);
// Add unknown devices
for(File f : newList)
{
if(!devices.contains(f) && f.canRead() && f.canWrite())
{
alarm(f); // Called when new device inserted
devices.add(f);
}
}
}
This method is called every 1000ms in a seperate Thread and I guess that will do. Admitted, this is a dirty method but it works. I tested this function often and I always had the result I wanted. When I continued building my programm, I found that the thread would stop detecting new devices when I hide my programm to the SystemTray. When I open it again, the detection thread still won't work. Could anyone tell me what causes this and how this is to be solved?
Upon saving the data inserted by the user, I stopped detection of new devices. This was foolish of me so I thank you for making me aware of this.
public boolean saveSettings()
{
File f = new File(fsv.getHomeDirectory() + File.separator + "settings.cms");
ObjectOutputStream objOut;
try
{
// Here was my problem.
detector.stopDetection();
if(gui.saveSettings())
{
// Settings-file wegschrijven
objOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
objOut.writeObject(settings);
objOut.flush();
objOut.close();
return true;
}
else
{
return false;
}
}
catch (IOException e)
{
handleExceptions(e);
return false;
}
}
I'm very beginner in Java, so ...
I've written a simple Java code to display images from my hard drive wherever I click the mouse, not on the applet, on panel, now how can I make a sound play automatically when I view 6 pictures ?
public void mouseClicked(MouseEvent e) {
if (count == images.length - 1) {
???????????????????????
} else {
count++;
}
x = e.getX();
y = e.getY();
frameTest.repaint();
}
I want to play a sound file from the Hard drive, in the place of question marks ..
can some one help plz ?
Try to write this inside your if :
try
{
Clip clickClip = AudioSystem.getClip();
URL clipURL = new URL("file://C:/aFile.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(clipURL);
clickClip.open(ais);
clickClip.start();
}
catch(Exception e)
{
System.out.ptintln("Something didn't work !\n" + e.printStackTrace());
}
Hope this helps.
I send WAV files using a client and server, but I want to play the WAV when it received. I try this method but it did not work:
Runtime.getRuntime().exec("C:\\Documents and Settings\\Administratore\\Desktop\\gradpro\\test1\\s1.wav") ;
This the exception that I get:
"Error! It didn't work! java.io.IOException: Cannot run program "C:\Documents": CreateProcess error=193, %1 is not a valid Win32 application"
What am I doing wrong?
You need to execute the audio player program (probably windows media player or something similar) and then pass the filename (the full path to the file) in as a parameter:
String wavPlayer = "/path/to/winmediaplayer.exe";
String fileToPlay = "/path/to/wav/file.wav";
Runtime.getRuntime().exec(wavPlayer, new String[]{fileToPlay}) ;
That should work.
What's wrong with Javas built in WAV playback support? You can play it back using AudioClip:
private void playBackClip(String fileName) {
try {
AudioInputStream soundStream = null;
if (fileName.startsWith("res:")) {
soundStream = AudioSystem.getAudioInputStream(
Object.class.getResourceAsStream(fileName.substring(4)));
} else {
File audioFile = resMap.get(fileName);
soundStream = AudioSystem.getAudioInputStream(audioFile);
}
AudioFormat streamFormat = soundStream.getFormat();
DataLine.Info clipInfo = new DataLine.Info(Clip.class,
streamFormat);
Clip clip = (Clip) AudioSystem.getLine(clipInfo);
soundClip = clip;
clip.open(soundStream);
clip.setLoopPoints(0, -1);
clip.start();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
Is the use of the default audio player mandatory?
If not you might want to look into Java's AudioSystem.
Instead of specifying the media player to use, let windows look it up for you:
String comspec = System.getenv().get("ComSpec");
String fileToPlay = "/path/to/wav/file.wav";
Runtime.getRuntime().exec(comspec, new String[]{"/c", "start", fileToPlay}) ;
You are basically doing something like:
cmd.exe /c start path_to_wav_file.wav
To see all the options start gives you (start is a built-in operation of cmd.exe, not a stand-alone program, which is why you have to run cmd.exe instead of a 'start.exe'), do
start /h
Old question, but for the record:
java.awt.Desktop.getDesktop().open(new java.io.File(my_filename));
Try:
Runtime.getRuntime().exec("'C:\Documents and Settings\Administratore\Desktop\gradpro\test1\s1.wav'") ;
Note the extra single quotations. I'm not even sure if your method will work, but give that a go.