Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Javax.sound.sampled

Options
  • 10-04-2012 1:13pm
    #1
    Closed Accounts Posts: 2,087 ✭✭✭


    Hi all,


    Any help would be much appreciated.



    I'm probably approaching this incorrectly but I need to find out how to stop a looping javax.sound.sampled clip. I have 9 different sounds. I want a different sound to play as a user presses an increase amplitude button. At the moment I'm calling the playSound method each time they click the button and it's working, however it's not stopping sounds that are already playing. The sounds just play over each other.


    Is there a way to close all existing sounds when the user presses the button?
    Here's my playSound code:

    public void playSound(){
            try {
                audio = AudioSystem.getAudioInputStream(soundFile[activeSound]);
                clip = AudioSystem.getClip();
                clip.open(audio);
                clip.start();
                clip.loop(Clip.LOOP_CONTINUOUSLY);           
            }
    
            catch (IOException ex){
                System.out.println("Sorry but there has been a problem reading your file.");
                ex.printStackTrace();
            }
            
            catch (UnsupportedAudioFileException ex1){
                System.out.println("Sorry but the audio file format you are using is not supported.");
                ex1.printStackTrace();
            }
            
            catch (LineUnavailableException ex2){
                System.out.println("Sorry but there are audio line problems.");
                ex2.printStackTrace();
            } 
        }
    
    This is driving me mad at this stage.


Comments

  • Registered Users Posts: 3,945 ✭✭✭Anima


    Just had a quick look at the Java API as I'm not that familiar with it but it looks like you need a mixer and then get that to suck the data from each of your audio input streams. That's generally how it's done so it makes sense.

    This has probably been done a million times by the way, maybe you should look for an example to get you going?


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Thanks for your reply Anima. I've been at it for 2 days now trying to find a solution. I don't really want to start messing with mixers. I just want a method to stop all looping clips that are playing before I start playing a new clip.
    It's driving me nuts. There has to be a method to close all clips. I've looked at numerous sites but they all seem to use the old sun.audio package for playing sounds which I've read should not be used anymore. There seems to be a way to do it using an applet but I've invested so much time in doing it this way that I'd prefer to get it finished this way.

    Thanks again.


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    Can you not keep a reference to the clip you are playing and store it in the class. Like something: Clip activeClip. Then call activeClip.stop() in your action listener.

    I see you have:
    audio = AudioSystem.getAudioInputStream(soundFile[activeSound]);
                clip = AudioSystem.getClip();
    

    So I'm assuming clip is already a member variable. If that's the case, can you not just call stop.
    audio = AudioSystem.getAudioInputStream(soundFile[activeSound]);
    
    if (clip != null && clip.isRunning()) {
     clip.stop();
    }
    clip = AudioSystem.getClip();
    


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Thanks so much Webmonkey. That worked. I was confusing the hell out of myself with this code (only in Semester 2 of prgramming). As you said, I declared Clip as a member variable.

    What's confusing me is, without that line you gave me (below), was the Clip just loading each new sound on top of the last one? So the one Clip was playing numerous sounds?
    if (clip != null && clip.isRunning()) {
     clip.stop();
    }
    


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    Clanket wrote: »
    Thanks so much Webmonkey. That worked. I was confusing the hell out of myself with this code (only in Semester 2 of prgramming). As you said, I declared Clip as a member variable.

    What's confusing me is, without that line you gave me (below), was the Clip just loading each new sound on top of the last one? So the one Clip was playing numerous sounds?
    if (clip != null && clip.isRunning()) {
     clip.stop();
    }
    
    The clip member variable is just a reference to an internal object that still exists. That's why it was still 'alive' and running even after over writing the reference with a new Clip object. getClip returns a reference to the object stored internally. Multiple of these Clips stayed in existence.


  • Advertisement
  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    You're a genius. Thanks again. I was about to throw the whole class in the bin and think up something else.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Having a nightmare now. I had everything working in NetBeans but when I create the jar file the sounds don't play. All help would be much appreciated.

    I had a lot of problems getting the sounds in in the first place. What eventually worked was saving the sounds outside the src folder in NetBeans (i.e saved in the version 4 folder which also contains the src folder).
    Then my code for loading the wav files was:
    private int activeSound = 0;
        File [] soundFile ;
        AudioInputStream audio;
        Clip clip;
        Clip activeClip;
            soundFile = new File [9];
            for (int i = 0; i < 9; i++){
                soundFile [i] = new File (i+"db.wav");
    
    And code to play the sound was
    public void playSound(){
            if ((clip != null) && (clip.isRunning())) {
                clip.stop();
            }
            try {
                audio = AudioSystem.getAudioInputStream(soundFile[activeSound]);
                clip = AudioSystem.getClip();
                clip.open(audio);
                clip.start();
                clip.loop(Clip.LOOP_CONTINUOUSLY);
                activeClip = clip;
            }
    
            catch (IOException ex){
                System.out.println("Sorry but there has been a problem reading your file.");
                ex.printStackTrace();
            }
    
            catch (UnsupportedAudioFileException ex1){
                System.out.println("Sorry but the audio file format you are using is not supported.");
                ex1.printStackTrace();
            }
    
            catch (LineUnavailableException ex2){
                System.out.println("Sorry but there are audio line problems.");
                ex2.printStackTrace();
            }
        }
    
    This worked but was a little buggy (i.e. you might get two sounds playing at the same time and not able to get rid of one of them until close the run. That was acceptable as was working most of the time. Now because the Jar file was not playing the sounds, I've tried to move the wav files into the src folder.

    I first tried leaving the code to load the files as is i.e
    soundFile = new File [9];
            for (int i = 0; i < 9; i++){
                soundFile [i] = new File (i+"db.wav");
            }
    
    However, when I run the project and try to play a sound (drag a slider) my IO exception gets thrown "Sorry but there has been a problem reading your file."

    I'm guessing it's the way I'm trying to load the files. I've tried the following but get the error below from NetBeans.
    soundFile = new File [9];
            for (int i = 0; i < 9; i++){
                soundFile [i] = new File (this.getClass().getResource (i+"db.wav"));
    
    no suitable constructor found for File(java.net.URL)
        constructor java.io.File.File(java.net.URI) is not applicable
          (actual argument java.net.URL cannot be converted to java.net.URI by method invocation conversion)
        constructor java.io.File.File(java.io.File,java.lang.String) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String,java.lang.String) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String) is not applicable
          (actual argument java.net.URL cannot be converted to java.lang.String by method invocation conversion)
        constructor java.io.File.File(java.lang.String,java.io.File) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String,int) is not applicable
          (actual and formal argument lists differ in length)
    
    I'd much appreciate if anyone could help. I'm in over my head.

    Thanks a mil.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    I just checked and the wav files were copied to the build/classes folder in my original build (i.e with wav files outside the project src folder). Very confused.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Really need to get this sorted today. If anyone can point me in the right direction that would be great. How do I change the reference of where the audio files are loaded from i.e. in the loop below.
    soundFile = new File [9];  
              for (int i = 0; i < 9; i++){         
                     soundFile [i] = new File (i+"db.wav");
    

    The above was working fine when I ran the project in NetBeans but when I created the jar file it wasn't working. So I tried to put the audio files in the src folder but now I don't know what I have to change in the for loop above to get the files loaded.


  • Registered Users Posts: 1,931 ✭✭✭Zab


    I'd say you were on the right track with getResource(). If it's returning an URL you could try converting it to a URI with toURI(). Another option would get to use getResourceAsStream() then loading from the resulting stream.


  • Advertisement
  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    I tried putting an absolute path (C:\\......) in on a different computer today and that worked (with the wav files in the src folder). The jar worked aswell. But now I'm back on my home computer and that same jar is not playing the sounds. Melting my brain. I'm gonna have another look now but I'm not too hopeful. The problem with (this.getClass().getResource(i+"db.wav)) is NetBeans keeps giving me an error saying:
    no suitable constructor found for File(java.net.URL)
        constructor java.io.File.File(java.net.URI) is not applicable
          (actual argument java.net.URL cannot be converted to java.net.URI by method invocation conversion)
        constructor java.io.File.File(java.io.File,java.lang.String) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String,java.lang.String) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String) is not applicable
          (actual argument java.net.URL cannot be converted to java.lang.String by method invocation conversion)
        constructor java.io.File.File(java.lang.String,java.io.File) is not applicable
          (actual and formal argument lists differ in length)
        constructor java.io.File.File(java.lang.String,int) is not applicable
          (actual and formal argument lists differ in length)
    


  • Registered Users Posts: 1,931 ✭✭✭Zab


    Did you try the toURI() ?

    You could be using a different java version at home, or you could be accidentily referencing the unjar-ed sound file when you're running the code from the jar (which would just mean it's not actually getting the sound file from the jar at all).

    So, it'd be
    soundFile [i] = new File (this.getClass().getResource (i+"db.wav").toURI());
    


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Tried that and am getting an error on the line in netBeans. Says "unreported exception java.net.URISyntaxException. Must be caught or declared to be thrown". I'll try stick in a try catch and see what happens.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    I'm going to have to give up. I feel like throwing my computer in the bin.

    So here's the two different ways I have it working in NetBeans but not in the jar file.

    1) wav files stored in the Version 4 folder. Here's a screen print. The src folder only contains a folder called rubberduckssoundproject that contains all of our code.

    200782.png
    Then the code to load the image into a file array is:
    for (int i = 0; i < 9; i++){
                soundFile [i] = new File (i+"db.wav");
                System.out.println(soundFile[i].getAbsolutePath());            
            }
    
    2) wav files stored in a new folder called soundfiles inside the src folder in the image above. The src folder also contains a folder called rubberduckssoundproject that contains all the rest of our code.

    The the code to load the wav files into Files is:
    for (int i = 0; i < 9; i++){
                soundFile [i] = new File ("src/soundfiles/"+i+"db.wav");
                System.out.println(soundFile[i].getAbsolutePath());
                
            }
    
    Both of these will have the files playing when you run the project in NetBeans. However, when you create the jar file no sounds will play from it.

    I've hit a brick wall with it. If anyone stumbles accross this thread and can tell me what I'm doing wrong, please do.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Clanket wrote: »
    Tried that and am getting an error on the line in netBeans. Says "unreported exception java.net.URISyntaxException. Must be caught or declared to be thrown". I'll try stick in a try catch and see what happens.

    Update on this: I put in a try catch to throw an Exception. Again this works when I run the project in NetBeans (no exception thrown) . However, now when I clean and build, a jar file gets created but when I go to click this jar nothing happens. Then when I go back into the project folder it will not let me delete the jar file. It keeps saying "The action can't be completed because the file is open in Java (TM) Platform SE binary.

    Aaaaaaaaaaaaaaggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

    fuuu.jpg


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Just tried above again on a different computer and did the same thing. Must be some sort of infinite loop? Anyone any ideas?


  • Registered Users Posts: 3,945 ✭✭✭Anima


    You should try and use the debugger and step through that piece of the code. If it can't find the files then it's not picking up the path directly.

    If the app is freezing now, then you've probably introduced a bigger problem. Should be easy enough to fix when you find it. Again use the debugger!


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Never used a debugger. I'll give it a shot now.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Just had a quick go and Debugger not showing any problems. You'd kind of expect this as everything runs fine in NetBeans. It's just when the jar file gets created, something is going wrong.


  • Registered Users Posts: 1,931 ✭✭✭Zab


    Did you do anything in the catch block? You should report the exception so that you know what's going on.


  • Advertisement
  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Zab wrote: »
    Did you do anything in the catch block? You should report the exception so that you know what's going on.

    Here's my code. There's no Exception been thrown when you run it in NetBeans. It's just that the jar file will not open.
    try{
                    soundFile [i] = new File (this.getClass().getResource (i+"db.wav").toURI());
                }  
                catch (Exception fileError){
                    System.out.println("Sorry but there's a problem loading your files into an array");
                    fileError.printStackTrace();
                }
    


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    Can you not put the wav files in the dist folder or wherever the jar file is created and then use
    soundFile [i] = new File (i+"db.wav");
    

    Can you run the Jar file from a command prompt, you might see more details/exceptions
    cd <pathtojarfile>
    java -jar file.jar


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Webmonkey wrote: »
    Can you not put the wav files in the dist folder or wherever the jar file is created and then use
    soundFile [i] = new File (i+"db.wav");
    
    Can you run the Jar file from a command prompt, you might see more details/exceptions
    cd <pathtojarfile>
    java -jar file.jar

    I'll try both now.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Webmonkey you've saved my ass again. Thank You.

    Putting a copy of the audio files in the dist folder works. I feel like crying.

    It still leaves me a lot of questions:-
    1. Paths etc and how jar files built.
    2. Why NetBeans only loads the files from "......../Version 4" instead of "......./Version 4/src/rubberduckssoundproject.
    3. Why could I not get "this.getClass().getResource(i+"db.wav").toURI()" to work in the jar. In fact, what the hell is this.get............
    Problem Based Learning sucks balls. Especially when you're in a group where people aren't doing feck all.


    Thanks again.


  • Registered Users Posts: 9,579 ✭✭✭Webmonkey


    When referencing a file, it' relative to the paths where the jar file is run from so the best is to keep the sounds with the jar on the same directory level. Using absolute paths would be a no no.

    Netbeans probably set's the PATH environment variable to other paths in the project when you run/debug from Netbeans so I guess that is why it was able to locate the wav files.


  • Closed Accounts Posts: 2,087 ✭✭✭Clanket


    Thanks again.

    I've another question about the original thing you helped me with (clip.stop()). This seems to be very buggy. When I move a JSlider slowly it seems to work ok. But most times when you change the slider it leaves a clip playing and starts playing a new one. So when you put the slider back down to 0 there's still a sound. I've tried changing a few things (use clip.flush(), set clip = null etc) but nothing is fixing it. Is there anything that stands out to you below?


    I have the following method inside my waveAnimation class. It takes an int from the sliderStateChanged code at the very bottom:
    public void changeAmplitude(int amp){        
            
            if ((clip != null) && (clip.isRunning())) {
                System.out.println("The line has detcted that there is an existing line and has stopped and closed it.");
                clip.stop();
                clip.flush();
                clip.close();
                clip = null;            
                audio = null;
    
            }        
            
            if (amp == 0){
                activeImageArray[0] = imageArray[0];
                activeImageArray[1] = imageArray[1];                
                activeSound = 0;            
            }
            
            else if ((amp > 0)&&(amp <= 10 )){
                activeImageArray[0] = imageArray[2];
                activeImageArray[1] = imageArray[3];               
                activeSound = 1;            
            }
            
            else if ((amp > 10)&&(amp <= 20 )){
                activeImageArray[0] = imageArray[4];
                activeImageArray[1] = imageArray[5];                
                activeSound = 2;            
            }
            
            else if ((amp > 20)&&(amp <= 30 )){
                activeImageArray[0] = imageArray[6];
                activeImageArray[1] = imageArray[7];                
                activeSound = 3;            
            }
            
            else if ((amp > 30)&&(amp <= 40 )){
                activeImageArray[0] = imageArray[8];
                activeImageArray[1] = imageArray[9];                
                activeSound = 4;            
            }
            
            else if ((amp > 40)&&(amp <= 50 )){
                activeImageArray[0] = imageArray[10];
                activeImageArray[1] = imageArray[11];                
                activeSound = 5;      
            }        
            
            else if ((amp > 50)&&(amp <= 60 )){
                activeImageArray[0] = imageArray[12];
                activeImageArray[1] = imageArray[13];                
                activeSound = 6;            
            }
            
            else if ((amp > 60)&&(amp <= 70 )){
                activeImageArray[0] = imageArray[14];
                activeImageArray[1] = imageArray[15];                 
                activeSound = 7;            
            }
            
            else {
                activeImageArray[0] = imageArray[16];
                activeImageArray[1] = imageArray[17];                
                activeSound = 8;            
            }
            
            playSound();
        }
    
    playSound method is
    public void playSound(){
       
            try {
                audio = AudioSystem.getAudioInputStream(soundFile[activeSound]);
                clip = AudioSystem.getClip();
                clip.open(audio);
                clip.start();
                clip.loop(Clip.LOOP_CONTINUOUSLY);
            }
    
            catch (IOException ex){
                System.out.println("Sorry but there has been a problem reading your file.");
                ex.printStackTrace();
            }
    
            catch (UnsupportedAudioFileException ex1){
                System.out.println("Sorry but the audio file format you are using is not supported.");
                ex1.printStackTrace();
            }
    
            catch (LineUnavailableException ex2){
                System.out.println("Sorry but there are audio line problems.");
                ex2.printStackTrace();
            }       
        }
    
    So I have a JSlider in another class that has the following listener
    private void sliderStateChanged(javax.swing.event.ChangeEvent evt) {                                    
            // TODO add your handling code here:
            int value = slider.getValue();
            
            waveAnimation1.changeAmplitude(value);        
        }
    


Advertisement