Why does attempting to get a Clip throw exception? - java

I have been following this tutorial for Java 1.7 and I am sure I have the code right. However, Java throws an IllegalArgumentException at runtime.
I've tried to catch it in an existing catch block, using Java's slightly-newer multi-catch. However, it simply throws exceptions.
Here is the beginning of my code.
Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
/*
for (Mixer.Info info : mixInfos)
{
System.out.println(info.getName() + " - " + info.getDescription());
}
*/
mixer = AudioSystem.getMixer(mixInfos[0]);
DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
try
{
clip = (Clip) mixer.getLine(dataInfo);
}
I expect that the code will continue running and play the Clip but I get this exception:
Exception in thread "main" java.lang.IllegalArgumentException: Line unsupported: interface Clip
at java.desktop/com.sun.media.sound.PortMixer.getLine(PortMixer.java:131)
at main.Driver.main(Driver.java:35)
Note: If this isn't forward compatible, please explain.

I think you should check your imports. AFAIK, the libraries for sound are all in javax.sound.sampled. The PortMixer is in com.sun.media.sound.
The author of the tutorial is going to a lot more trouble than is necessary. Instead of hardcoding a specific Mixer, you can just let the system pick defaults. This is probably the best strategy, as PC's out in the world are going to have diverse hardware configurations.
Following is an example that might be helpful. Notice that we don't even bother to declare a Mixer.
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class BasicClipExample {
public static void main(String[] args) {
BasicClipExample bc = new BasicClipExample();
try {
bc.run();
} catch (UnsupportedAudioFileException | IOException
| LineUnavailableException | InterruptedException e) {
e.printStackTrace();
}
}
private void run() throws UnsupportedAudioFileException,
IOException, LineUnavailableException, InterruptedException
{
String filename = "a3.wav";
URL url = this.getClass().getResource("audio/" + filename);
System.out.println(url);
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
Thread.sleep(6000);
clip.close();
}
}
This example assumes that your audio file is in a subdirectory called "/audio".
It also has a sleep command to keep the program running while the Clip is playing. Clips run under their own thread, but the thread is a "daemon" type and will not prevent a Java program from closing. My a3.wav is a recording of a bell that happens to last about 5 seconds.
Last thing, the above code does not use a Clip in the ideal fashion. The concept of a Clip is that it is for re-use. Reloading the clip variable before playing it each time it is played is inefficient. The clip variable should be loaded only once, and then played on demand. If you have clip.open() and clip.start() as contiguous lines of code, you should probably either be using a SourceDataLine instead of a Clip, or you should recode and put the two commands into separate methods.

Related

Play audio files in Java

I am trying to play a simple audio file which is in the same directory near the class file. I tried many examples from the internet, but all the others gave me errors which I couldn't even understand.
Then I found this, and I am using it now.
There are neither compile errors nor runtime errors. But the problem is I cannot hear any noise.
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
class A{
public static void main (String[]args){
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("abc.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
} catch(Exception ex) {
System.out.println("Error with playing sound.");
}
}
}
Please note that my system volume is 80%, and the audio file plays in VLC media player.
Starting the audio clip does not block the main method. So
clip.start();
starts playing and then returns. Now your main method ends and therefore the Java process ends. No sound.
If you do
clip.start();
Thread.sleep(20000);
you should hear the clip playing for 20 seconds.
So for a working program just must make sure that the main thread does not end as long as you want to play the clip.
Hold the thread for a while until the audio clip plays.
long audioPlayTime = 1000; //clip duration in miliseconds.
try {
Thread.sleep(audioPlayTime);
} catch (InterruptedException ex){
//TODO
}

How to play .wav files in Java (looped)?

I've been rampaging about for a couple of hours now looking for sample code that can play simple wav files in Java. However, none of the ones I've received are working for me. Maybe it's just me that doesn't understand how to operate the sample code but could anyone provide me with sample code and "instructions" on how to get it working correctly. Any help would be much appreciated.
This code will create a clip and play it continuously once started:
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new URL(filename)));
clip.start();
clip.loop(Clip.LOOP_CONTINUOUSLY);
There are more modern ways to do this, but the applet class AudioClip might satisfy your needs:
import java.applet.Applet;
import java.applet.AudioClip;
final AudioClip clip = Applet.newAudioClip(resourceUrl);
To play it once:
clip.play();
To loop:
clip.loop();
clip.stop();
See Javadocs for Applet and AudioClip
getAudioClip
public AudioClip getAudioClip(URL url)
Returns the AudioClip object specified by the URL argument.
This method always returns immediately, whether or not the audio clip exists. When this applet attempts to play the audio clip, the data will be loaded.
Parameters:
url - an absolute URL giving the location of the audio clip.
Returns:
the audio clip at the specified URL.
You don't need to actually be doing anything with applets for this to work. It will work fine in a regular Java application.
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);
}
}

Error getting audio input stream from input URL

I am trying to play a .WAV in Java using the code from the javasound.info:
import java.net.URL;
import javax.swing.*;
import javax.sound.sampled.*;
public class LoopSound {
public static void main(String[] args) throws Exception {
URL url = new URL(
http://www.mediafire.com/listen/vgtpaigmj3un9ii/Untitled34.wav");
Clip clip = AudioSystem.getClip();
// getAudioInputStream() also accepts a File or InputStream
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(Clip.LOOP_CONTINUOUSLY);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// A GUI element to prevent the Clip's daemon Thread
// from terminating at the end of the main()
JOptionPane.showMessageDialog(null, "Close to exit!");
}
});
}
}
But I am getting the following error:
Exception in thread "main" javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input URL
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1153)
at LoopSound.main(Wanderando.java:13)
I assume that the problem is with the URL itself and not the code, but I cannot for the life of me come across a service to upload and stream a .WAV file so that the program can capture the audio like in the original code with the :
http://pscode.org/media/leftright.wav
I am not sure if the code would have to be tweaked a bit for the to support mediafire's player or if there is another service for upload that support this.
Any help would be very appreciated.

IOException markreset not supported with Java Sound on export

Ok so i made a game in java and i exported it. In Eclipse everything works perfectly but when i export the jar there are some problems. When you collide with another rectangle it should play a sound (In eclipse it works but not exported).
Here is my class for sounds:
package sound;
import java.io.InputStream;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class GameSounds
{
static String hitPath = "/resources/8bit_bomb_explosion.wav";
public static synchronized void hit()
{
try
{
InputStream audioInStream = GameSounds.class.getResourceAsStream(hitPath);
AudioInputStream inputStream = AudioSystem.getAudioInputStream(audioInStream);
Clip clip = AudioSystem.getClip();
clip.open(inputStream);
clip.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
and i used java -jar ProjectZero.jar to open up the console while playing and here is the error i get when it should play a sound:
java.io.IOException markreset not supported
at java.util.zip.InflaterInputStream.reset(Unknown Source)
at java.io.FilterInputStream.reset(Unknown Source)
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unkno
wn Source)
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at sound.GameSounds.hit(GameSounds.java14)
at main.Main.doLogic(Main.java136)
at main.Main.run(Main.java100)
at java.lang.Thread.run(Unknown Source)
I tried exporting the resources into the jar but no success.
I tried putting the resources folder in the same folder with the jar but it doesn't work either.
Java Sound requires a repositionable input stream. Either use getResource(String) for an URL (out of which JS will create such a stream), or wrap the original stream to make it so.
E.G. copied from the Java Sound info. page.
import java.net.URL;
import javax.swing.*;
import javax.sound.sampled.*;
public class LoopSound {
public static void main(String[] args) throws Exception {
URL url = new URL(
"http://pscode.org/media/leftright.wav");
Clip clip = AudioSystem.getClip();
// getAudioInputStream() also accepts a File or InputStream
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(Clip.LOOP_CONTINUOUSLY);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// A GUI element to prevent the Clip's daemon Thread
// from terminating at the end of the main()
JOptionPane.showMessageDialog(null, "Close to exit!");
}
});
}
}
See also the embedded-resource info. page.

Java AudioSystem .wav file discrepancy in behaviour

I have a number of .wav files I play from Java. In this stripped down example, "drip" is audible but "swish" is not even though they run via the same code. There does not seem to be anything unusual about "swish": it plays from the Gnome desktop. I have a similar app, not quite as stripped down that plays "swish" but not "drip" so again it does not seem to be a problem tied to the nature of the data.
Any ideas what is happening here? This bug was noticed after code that was known to be working was "redeployed" on a rebuilt system: reinstalled Ubuntu 10.10 and Eclipse Indigo. This bug happens with both Sun JDK 6 and OpenJDK 6. Edit The "rebuilt" system is actually different hardware as well: Intel E6500 (2 cores, 2.93 GHz) I have only installed Ubuntu, Eclipse, OpenJDK, Sun JDK. The previous system was an AMD 630 (4 cores, 2.8 GHz) with Ubuntu, Eclipse, OpenJDK (I think).
Edit After some experimenting, it seems the first clip loaded will be the one that works. The TestSounder constructor loads them so that is where the order can be reversed. Perhaps the use of the static method AudioSystem.getLine has something to do with it since that is obviously the non-object oriented operation here.
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Clip;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.LineUnavailableException;
public class TestSounder
{
String resourcePathFromBin = "/resources/";
Clip dripClip;
Clip swishClip;
public TestSounder()
{
dripClip = setupClip("drip.wav");
swishClip = setupClip("swish.wav");
}
public void close()
{
dripClip.close();
swishClip.close();
}
private Clip setupClip(String fileName)
{
Clip clip = null;
try
{
AudioInputStream ais =
AudioSystem.getAudioInputStream(this.getClass().getResourceAsStream(resourcePathFromBin +
fileName));
AudioFormat af = ais.getFormat();
DataLine.Info lineInfo = new DataLine.Info(Clip.class, af);
clip = (Clip)AudioSystem.getLine(lineInfo);
clip.open(ais);
}
catch (UnsupportedAudioFileException e)
{
assert false: "bug";
}
catch (IOException e)
{
assert false: "bug";
}
catch (LineUnavailableException e)
{
assert false: "bug";
}
return clip;
}
public void go(UtilityK.Sounds s)
{
Clip clip = null;
if (s == UtilityK.Sounds.drip)
clip = dripClip;
if (s == UtilityK.Sounds.swish)
clip = swishClip;
clip.stop();
clip.setFramePosition(0);
clip.start();
//while (clip.isRunning())
// TestSounder.delay();
}
public static void main(String[] args)
{
TestSounder obj = new TestSounder();
obj.go(UtilityK.Sounds.swish);
TestSounder.delay();
obj.go(UtilityK.Sounds.drip);
TestSounder.delay();
obj.go(UtilityK.Sounds.swish);
TestSounder.delay();
obj.go(UtilityK.Sounds.drip);
TestSounder.delay();
obj.close();
}
private static void delay()
{
Thread.sleep(5000);
}
}
public interface UtilityK
{
enum Sounds { drip, swish };
}
Here is an alternative approach. It seems well suited to short sounds that might need to be played often or in quick succession as user feedback.
link to a way to play two kinds of beeps that come from .wav files

Categories