3

Trying to play and audio clip in java, but this error pops up every time. I imported everything I need to so I'm not sure what the issue is.

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream (this.getClass ().getResource ("hopes_and_dreams.wav"));
                Clip clip = AudioSystem.getClip ();
                clip.open (audioInputStream);
                clip.start ();
javax.sound.sampled.LineUnavailableException: Failed to allocate clip data: Requested buffer too large.
    at com.sun.media.sound.MixerClip.implOpen(Unknown Source)
    at com.sun.media.sound.MixerClip.open(Unknown Source)
    at com.sun.media.sound.MixerClip.open(Unknown Source)
    at CA_PeterLang.paint(CA_PeterLang.java:828)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JLayeredPane.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)
    at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    at java.awt.Container.paint(Unknown Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Peter Lang
  • 65
  • 5
  • Can you post the full stack trace? Also, what version of Java? – KevinO Jun 01 '17 at 00:33
  • 1.7.1, the program doesn't compile so I'm not sure how to get stack trace. – Peter Lang Jun 01 '17 at 00:35
  • Ah, sorry, guess I didn't understand it was a compilation issue. Please amend the code with the import statements. The sample you gave compiles w/o issue for me. – KevinO Jun 01 '17 at 00:36
  • Posted the imports – Peter Lang Jun 01 '17 at 00:39
  • Oh by the way I'm programming in Ready to Program since it's mandatory for my class. – Peter Lang Jun 01 '17 at 00:39
  • Unfortunately, I have no knowledge of Ready to Program. It is possible it is using an older version of Java and/or the runtime libraries. The .getClip() was added in 1.5. I'll post an answer with an alternative approach that might work. – KevinO Jun 01 '17 at 00:43
  • Ah sorry, the ready to program version is 1.7, it seems to be using Java 1.4 from the looks of it. – Peter Lang Jun 01 '17 at 00:48
  • Yes, with Java 1.4, the `.getClip()` method is not available. It would be nice if you could use an updated version of Java. If not, see my answer, as I think it uses all original API methods. – KevinO Jun 01 '17 at 00:49
  • It really would be best if you kept the original question, and then opened a new question with the updates. Otherwise answers make no sense in relation to the updated question. I *think* the updated issue has to do with the IDE you are using. – KevinO Jun 01 '17 at 01:05
  • Probably, maybe I just won't use any audio. Is there a way that I can do it using sun.audio to make a looping clip that doesn't interfere with the execution of other code? – Peter Lang Jun 01 '17 at 01:11
  • I edited my answer to show what I believe to be an alternative approach. One part came from a book specifically on Java 1.4, so *perhaps* it will be compatible with your JRE. – KevinO Jun 01 '17 at 01:23

2 Answers2

1

I've never used it but, it seems like you have to do this :

Clip clip = new Clip(); // Think that you can pass the stream as parameter for the builder
clip.open(audioInputStream);

Ref here : https://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/Clip.html#open(javax.sound.sampled.AudioInputStream)

Marcos
  • 9
  • 2
  • `AudioSystem` absolutely has a `.getClip(): https://docs.oracle.com/javase/8/docs/api/javax/sound/sampled/AudioSystem.html#getClip-- – KevinO Jun 01 '17 at 00:22
  • Interface javax.sound.sampled.Clip cannot be used where a class is expected – Peter Lang Jun 01 '17 at 00:23
  • This answer is wrong. One cannot do `new Clip();` as `Clip` is an Interface. See: https://docs.oracle.com/javase/8/docs/api/javax/sound/sampled/Clip.html – KevinO Jun 01 '17 at 00:50
1

The issue of the OP and not being able to find the method is related to the Ready to Program IDE which is apparently running Java 1.4. The .getClip() method in the question was added in Java 1.5 according to the JavaDocs for AudioSystem

However, I have, in the past, had issues where the system would not find my specific speakers, so the following approach has worked for me. Note that I use a URL, but it should be adaptable to a getResource() approach.

private Mixer.Info getSpeakers()
{
    Mixer.Info speakers = null;
    Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
    for (Mixer.Info mi : mixerInfo) {
        // System.out.println(mi.getName() + "\t" +
        // mi.getDescription());

        if (mi.getName().startsWith("Speakers")) {
            speakers = mi;
        }
    }

    System.out.println(
            (speakers != null ? speakers.getName() : "<no speakers>"));

    return speakers;
}    

public void playSound(String soundFile)
{
    AudioInputStream ais = null;        
    try {
        URL url = new File(soundFile).toURI().toURL();

        ais = AudioSystem.getAudioInputStream(url);

        Mixer mixer = AudioSystem.getMixer(getSpeakers());

        DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);

        Clip clip = (Clip)mixer.getLine(dataInfo);

        clip.open(ais);
        clip.start();

        do {
            try {
                Thread.sleep(50);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        while (clip.isActive());            
    }
    catch (UnsupportedAudioFileException | IOException |
            LineUnavailableException e) 
    {
        e.printStackTrace();
    }        
}

When called with playSound("Alarm01.wav"), it properly executes. I think this approach uses slightly older methods.

Edit: please do not follow my names here -- they are hacked for testing.

Edit 2: the foreach loop may be changed to:

for (int i = 0; i < mixerInfo.length; ++i) {
    Mixer.Info mi = mixerInfo[i];
    ...

Edit 3: to use as an InputStream rather than a URL, use

InputStream is = this.getClass().getClassLoader().getResourceAsStream(soundName);
// add a check for null
ais = AudioSystem.getAudioInputStream(is);

Edit 4: This method works with Java 1.4 (to the best of my knowledge). I had to hack around on my local machine settings to get the sound, but that is a different issue.

public void playSoundOldJava(String soundFile)
{
    try {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(soundFile);

        // TODO: add check for null inputsteam
        if (is == null) {
            throw new IOException("did not find " + soundFile);
        }

        AudioInputStream ais = AudioSystem.getAudioInputStream(is);

        DataLine.Info dataInfo = new DataLine.Info(Clip.class, ais.getFormat());

        if (AudioSystem.isLineSupported(dataInfo)) {
            Clip clip = (Clip)AudioSystem.getLine(dataInfo);
            System.out.println("open");
            clip.open(ais);

            clip.start();
            do {
                try {
                    Thread.sleep(50);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            while (clip.isActive());                  

        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}
KevinO
  • 4,303
  • 4
  • 27
  • 36
  • for (Mixer.Info mi : mixerInfo) Confused about this line, I get the error :expected instead of this token at the ). Also, what is the purpose of the getSpeakers method? – Peter Lang Jun 01 '17 at 00:54
  • Ugh. Who teaches with such an outdated version of Java? Anyway, the loop may be modified as I indicated in the *edit2* (using a straight for loop). And the `getSpeakers()` I've needed in the past b/c otherwise the playback tries to go to my virtual machine or other things, which is not all that helpful. – KevinO Jun 01 '17 at 00:58
  • So now I get a error while program is running, I'll post it in the original post. – Peter Lang Jun 01 '17 at 01:02
  • Problem at line 879 might be something else, but it only just started happening after I added the audio stuff. – Peter Lang Jun 01 '17 at 01:06
  • Nevermind 879 is where I execute the playSound method. – Peter Lang Jun 01 '17 at 01:07
  • You need to modify your classpath, sourcepath, bootclasspath, and/or extdirs setup. Package "DataLine" could not be found in: C:\Program Files (x86)\Ready to Program\Support\jre142_01\lib\rt.jar . C:\Program Files (x86)\Ready to Program\Support\Ready Classes C:\Program Files (x86)\Ready to Program\Support\Classes C:\Program Files (x86)\Ready to Program\Support\Ready Classes\tools.jar C:/Users/name/Desktop/VA-11 HALL-A – Peter Lang Jun 01 '17 at 01:30
  • By the way thanks for taking the time to help me with this, really appreciate it. – Peter Lang Jun 01 '17 at 01:30
  • Did you import `javax.sound.sampled.DataLine`? That interface has been present since Java 1.3. – KevinO Jun 01 '17 at 01:33
  • There's still an error, but I can't even copy the stack trace, there's an exception when the debugger attempts to pause the program. I'll assume that it's an issue with the IDE I'm using and I'll figure something else out. Thanks for your help. – Peter Lang Jun 01 '17 at 01:38
  • Sorry the full resolution wasn't available, but if you feel it is appropriate, you might accept the answer since it did directly address the initial question about the method not found error. Good luck! – KevinO Jun 01 '17 at 01:40
  • Actually if you don't mind me continuing to ask questions, the issue seems to be with clip.open (ais). I put the new stack trace in the post as well. – Peter Lang Jun 01 '17 at 01:45
  • @BenDrowned, so the problem is that the file you want to play is too large. There is a [Question/Answer on long audioclip](https://stackoverflow.com/questions/9470148/how-do-you-play-a-long-audioclip). [This answer](https://stackoverflow.com/a/9471455/1277259) might address the issue of a large sound file. – KevinO Jun 01 '17 at 01:53
  • But the file is only like 440 kb and 40 seconds. – Peter Lang Jun 01 '17 at 02:06
  • You could try `InputStream is = new BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(soundFile));`. Don't know if it will be smarter on the allocation. Also, what type of file (e.g., .wav, .mp3 or what) are you trying to play? – KevinO Jun 01 '17 at 02:22
  • wav, mp3, m4a, whatever works, I have the file in all of the formats, I've mostly been testing with wav though. – Peter Lang Jun 01 '17 at 02:31
  • So I downloaded Ready to Program, and did the method as above `playSoundOldJava(...)`. I had to change to use `InputStream is = new BufferedInputStream(new FileInputStream(new File(soundFile)));` and pass it an absolute path, as the "File->Preferences" additional classpath didn't work for me. YMMV. I did see where you might be able to increase the Max Memory for the JVM. Don't know if that will help, but you might try `2048`. Your educational institution should feel bad for making you use this antiquated IDE. (ha, 2048 caused it not to launch; try 1024). – KevinO Jun 01 '17 at 03:16
  • OK, did get the additional classpath to work, so the `.getResource()` approach is possible. – KevinO Jun 01 '17 at 03:20