This discussion is archived
4 Replies Latest reply: Jun 8, 2012 10:36 AM by KevinPas RSS

Playing a sound file more than once in a row?

821613 Newbie
Currently Being Moderated
OK, so I got the PlayWavFile code from the Internet, and I've modified it a bit so that it has a play method, but I'm trying to get it to play 5 times in a row. The thing is, I can't seem to get a for loop to work around it. Also, since I've never messed with sound before, I'm wondering: What is a line in reference to sound? I don't understand the comments.

Here is the code I'm trying to execute (Note: I used skype-ringer.wav as an example, but any wav file will do):

SSCCE Class
package sscce;

public class SSCCE
{
    public static void main(final String args[])
    {
        final PlayWavFile wavFile = new PlayWavFile("skype-ringer.wav");
        for (int p = 0; p < 5; p++)
        {
            wavFile.play();
        }
    }
}
PlayWavFile Class
package flashcards;

import java.io.File;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;

public class PlayWavFile
{
    AudioInputStream audioInputStream = null;
    SourceDataLine auline = null;
    AudioFormat format = null;
    DataLine.Info info = null;
    
    public PlayWavFile(final String soundFileName)
    {
        final File soundFile = new File(soundFileName);
        
        if(!soundFile.exists())
        {
            System.err.println("Wave file not found: " + soundFile);
            return;
        }
        
        try
        {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        }
        catch(final Exception e)
        {
            e.printStackTrace();
            return;
        }
        
        format = audioInputStream.getFormat();
        info = new DataLine.Info(SourceDataLine.class,format);
        // Describe a desired line
    }
    
    public void play()
    {
        for (int i = 0; i < 5; i++)
        {
            final int EXTERNAL_BUFFER_SIZE = 524288;
            final byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
            int nBytesRead = 0;
            
            try
            {
                auline = (SourceDataLine)AudioSystem.getLine(info);
                auline.open(format); // Opens the line with the specified
                                        // format, causing the line to acquire
                                        // any required system resources and
                                        // become operational.
            }
            catch(final Exception e)
            {
                e.printStackTrace();
                return;
            }
            
            auline.start(); // Allows a line to engage in data I/O
            
            try
            {
                while (nBytesRead != -1)
                {
                    nBytesRead = audioInputStream.read(abData,0,abData.length);
                    if(nBytesRead >= 0)
                    {
                        auline.write(abData,0,nBytesRead); // Writes audio data
                                                            // to the mixer (an
                                                            // audio device with
                                                            // one or more
                                                            // lines) via this
                                                            // source data line
                    }
                }
                Thread.sleep(1000);
            }
            catch(final Exception e)
            {
                e.printStackTrace();
                return;
            }
            finally
            {
                auline.drain(); // Drains queued data from the line by
                                // continuing data I/O until the data line's
                                // internal buffer has been emptied
                auline.close(); // Closes the line, indicating that any system
                                // resources in use by the line can be released
            }
        }
    }
}
I've tried putting the for loop around the try block in the PlayWavFile.play method, but nothing works so far. What am I supposed to do if I want the file to play multiple times?
  • 1. Re: Playing a sound file more than once in a row?
    KevinPas Explorer
    Currently Being Moderated
    I don't know if this will help. It's old - I haven't looked at it in at least five years - when I used to use hungarian notation

    What might help is using "m_SourceDataLine.isRunning()" in your for loop.

    private     SourceDataLine      m_SourceDataLine    = null;
    private     boolean             m_bOk;
    private     AudioInputStream    m_AudioInputStream     = null;
    private     int                 m_iBytesRead      = 0;
    private     byte []             m_bytesToWrite;
    
    if ( AudioSystem.isLineSupported( Port.Info.SPEAKER ) )
    {
        String     strFile     = "SOUND528.WAV";
    
        File f = new File ( strFile );
        if ( f != null  &&  f.isFile() == true )
        {
            m_AudioInputStream = AudioSystem    .getAudioInputStream    ( f );
    
            if ( m_AudioInputStream != null )
            {
                //     more than enough to hold the complete file. 
                m_bytesToWrite           = new byte[ 10000 ];
    
                //     Read the file and remember how many bytes were actually read.
                m_iBytesRead          = m_AudioInputStream     .read     ( m_bytesToWrite, 0, m_bytesToWrite.length );
    
                //     Now that you have read the file find out its format.
                AudioFormat          AF     = m_AudioInputStream     .getFormat     ();
    
                //     Clips don't allow pre-loading.  You must load it and play it at the same time.
                //DataLine.Info     info     = new DataLine               .Info           ( Clip.class, AF );
                //m_Clip                    = (Clip) AudioSystem     .getLine     ( info );                                   
                //m_Clip     .open          ( AIS );
    
                //     SourceDataLine's allow you to pre-read and play later.
                DataLine.Info     info     = new DataLine          .Info                ( SourceDataLine.class, AF );
                m_SourceDataLine          = (SourceDataLine)     AudioSystem          .getLine     ( info );
    
                //     The most important improvement is using open with the buffer size to use.
                //     Otherwise, if the buffer is too small the write function will block until
                //     the requested amount of data is written.  This then delays the video.
                m_SourceDataLine          .open     ( AF, m_iBytesRead );
                m_SourceDataLine          .start     ();
    
                //m_SourceDataLine     .write     ( m_bytesToWrite, 0, m_iBytesRead );
    
                //m_SourceDataLine     .isRunning()
            }
        }
    }
  • 2. Re: Playing a sound file more than once in a row?
    KevinPas Explorer
    Currently Being Moderated
    Sorry, I wasn't thinking the "big picture".

    You probably want to run your sound in some kind of thread and when it finishes fire some kind of an event and then restart it...

    Or, after thinking about it, maybe there are some newer sound classes that have an event that you can listen to. Or, an event that I missed.

    Edited by: KevinPas on Jun 6, 2012 7:05 PM
  • 3. Re: Playing a sound file more than once in a row?
    821613 Newbie
    Currently Being Moderated
    OK . . . where should I put this code? I'm pretty new to Java, so I'm not too familiar with code insertion like this. Should I replace anything with it?

    Also, I'm planning to have an event fire to play the sound, but I want to make sure that I fix the sound first.
  • 4. Re: Playing a sound file more than once in a row?
    KevinPas Explorer
    Currently Being Moderated
    Since I don't really know how much you know I can't answer without risking talking down to you or the opposite.

    I'll assume the best and so advice a few internet searches like: "java tutorials".

    I'll bet oracles isn't too bad: http://docs.oracle.com/javase/tutorial/

    Given that here's some ideas off the top of my head (which means I'll probably leave out something important).

    1) Do a few tutorials on java threads and timers. Look at tutorials on "Runnable", "Thread", "SwingWorker", "Timer", "synchronize"
    2) Do a few tutorials on "how to fire a java event".

    Here's my idea which would probably work but might not be what I would end up with:
    1) Make PlayWavFile implements Runnable
    2) Start the thread that refers to PlayWaveFile.
    3) When it is finished running (see tutorials) either fire an event that you create or set a flag that you are done.
    4) If you don't know how to set up an event to fire then the easiest alternative is to start a timer after #3
    5) Every time the timer finishes look at the flag. If the thread has finished then restart the thread.
    6) Repeat all of that until you are done.

    Edited by: KevinPas on Jun 8, 2012 10:35 AM

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points