Computer Science Canada

Background music

Author:  Hendo [ Fri May 23, 2008 2:12 pm ]
Post subject:  Background music

Ok, for my title screen, I need some background music to play and I thought this would do it for me.
code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.sound.midi.*;
import java.net.*;
import java.io.*;
import javax.swing.JOptionPane;
import javax.sound.sampled.*;

public class titleScreen extends Frame implements Runnable, KeyListener
{
    private Image title;
    private Image cursor;
    private MediaTracker tracker;
    private Thread thread;
    private Image offScrImg;
    private int cursorX = 217;
    private int cursorY = 183;
    private int select = 1;


    titleScreen ()
    {
        addKeyListener (this);
        tracker = new MediaTracker (this);
        title = Toolkit.getDefaultToolkit ().getImage ("graphics/titlescreen.png");
        tracker.addImage (title, 0);
        cursor = Toolkit.getDefaultToolkit ().getImage ("graphics/Cursor.png");
        tracker.addImage (cursor, 0);
        try
        {
            tracker.waitForID (0);
        }
        catch (InterruptedException e)
        {
            System.out.println (e);
        }
        int width = title.getWidth (this);
        int height = title.getHeight (this);
        setSize (width, height);
        setVisible (true);
        thread = new Thread (this);
        thread.start ();
        try
        {
            // From file
            AudioInputStream stream = AudioSystem.getAudioInputStream (new File ("music"));

            // From URL
            // stream = AudioSystem.getAudioInputStream(new URL("http://hostname/audiofile"));

            // At present, ALAW and ULAW encodings must be converted
            // to PCM_SIGNED before it can be played
            AudioFormat format = stream.getFormat ();
            if (format.getEncoding () != AudioFormat.Encoding.PCM_SIGNED)
            {
                format = new AudioFormat (
                        AudioFormat.Encoding.PCM_SIGNED,
                        format.getSampleRate (),
                        format.getSampleSizeInBits () * 2,
                        format.getChannels (),
                        format.getFrameSize () * 2,
                        format.getFrameRate (),
                        true);        // big endian
                stream = AudioSystem.getAudioInputStream (format, stream);
            }

            // Create the clip
            DataLine.Info info = new DataLine.Info (
                    Clip.class, stream.getFormat (), ((int) stream.getFrameLength () * format.getFrameSize ()));
            Clip clip = (Clip) AudioSystem.getLine (info);

            // This method does not return until the audio file is completely loaded
            clip.open (stream);

            // Start playing
            clip.start ();
        }
        catch (MalformedURLException e)
        {
        }
        catch (IOException e)
        {
        }
        catch (LineUnavailableException e)
        {
        }
        catch (UnsupportedAudioFileException e)
        {
        }



    }


    public static void delay (int ms)
    {
        try
        {
            Thread.sleep (ms);
        }
        catch (Exception e)
        {
            ;
        }
    }


    public void checkCursor ()
    {
        switch (select)
        {
            case 1:
                cursorY = 183;

                break;
            case 2:
                cursorY = 248;

                break;
            case 3:
                cursorY = 315;

                break;
            case 4:
                cursorY = 381;

                break;

            default:
                cursorY = 183;

                break;
        }
    }


    public void keyPressed (KeyEvent e)
    {
        int c = e.getKeyCode ();
        if (c == e.VK_UP)
        {

            select -= 1;
            checkCursor ();
            if (select < 1)
            {
                select = 4;
                checkCursor ();
            }
        }
        if (c == e.VK_DOWN)
        {

            select += 1;
            checkCursor ();
            if (select > 4)
            {
                select = 1;
                checkCursor ();
            }
        }
        if (c == e.VK_ENTER)
        {
            switch (select)
            {
                case 3:
                    JOptionPane.showMessageDialog (null, "Body Break 1.0" + "\n" + "Copyright 2008, GLC Studios", "About Body Break", JOptionPane.INFORMATION_MESSAGE);
                    break;
                case 4:
                    System.exit (0);
                    break;
            }
        }
    }



    public void keyReleased (KeyEvent e)
    {
    }


    public void keyTyped (KeyEvent e)
    {
    }



    public void drawScene (Graphics g)
    {
        if (offScrImg == null)
            offScrImg = createImage (size ().width, size ().height);

        Graphics og = offScrImg.getGraphics ();
        og.drawImage (title, 0, 0, this);
        og.drawImage (cursor, cursorX, cursorY, this);
        g.drawImage (offScrImg, 0, 0, this);

    }


    public void run ()
    {
        while (true)
        {
            repaint ();
            delay (10);
        }
    }


    public void update (Graphics g)
    {
        drawScene (g);
    }


    public static void main (String[] args)
    {
        new titleScreen ();




    }
}





however no sound plays and it makes me very sad face

Author:  rizzix [ Fri May 23, 2008 3:36 pm ]
Post subject:  RE:Background music

First of all, if you're playing a large music file, do not use clips! That would consume a LOT of memory.

Secondly. You need to run the music in the background concurrently. Your current method will make your application unresponsive.

Looking up the javaalmanac, here the method with streams:

Java:
AudioInputStream stream = AudioSystem.getAudioInputStream(new File("music.wav"));
   
        // From URL
        //stream = AudioSystem.getAudioInputStream(new URL("http://hostname/audiofile"));
   
        // At present, ALAW and ULAW encodings must be converted
        // to PCM_SIGNED before it can be played
        AudioFormat format = stream.getFormat();
        if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
            format = new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED,
                    format.getSampleRate(),
                    format.getSampleSizeInBits()*2,
                    format.getChannels(),
                    format.getFrameSize()*2,
                    format.getFrameRate(),
                    true);        // big endian
            stream = AudioSystem.getAudioInputStream(format, stream);
        }
   
        // Create line
        SourceDataLine.Info info = new DataLine.Info(
            SourceDataLine.class, stream.getFormat(),
            ((int)stream.getFrameLength()*format.getFrameSize()));
        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
        line.open(stream.getFormat());
        line.start();
   
        // Continuously read and play chunks of audio
        int numRead = 0;
        byte[] buf = new byte[line.getBufferSize()];
        while ((numRead = stream.read(buf, 0, buf.length)) >= 0) {
            int offset = 0;
            while (offset < numRead) {
                offset += line.write(buf, offset, numRead-offset);
            }
        }
        line.drain();
        line.stop();


However, you need to encapsulate all that inside a Runnable and run it in a Thread. Like this:
Java:
Runnable background_music = new Runnable() {
        @Override public void run() {
                try {
                        AudioInputStream stream = AudioSystem.getAudioInputStream(new File("music.wav"));
                                    
                        // From URL
                        //stream = AudioSystem.getAudioInputStream(new URL("http://hostname/audiofile"));
                    
                        // At present, ALAW and ULAW encodings must be converted
                        // to PCM_SIGNED before it can be played
                        AudioFormat format = stream.getFormat();
                        if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
                            format = new AudioFormat(
                                    AudioFormat.Encoding.PCM_SIGNED,
                                    format.getSampleRate(),
                                    format.getSampleSizeInBits()*2,
                                    format.getChannels(),
                                    format.getFrameSize()*2,
                                    format.getFrameRate(),
                                    true);        // big endian
                            stream = AudioSystem.getAudioInputStream(format, stream);
                        }
                    
                        // Create line
                        SourceDataLine.Info info = new DataLine.Info(
                            SourceDataLine.class, stream.getFormat(),
                            ((int)stream.getFrameLength()*format.getFrameSize()));
                        SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
                        line.open(stream.getFormat());
                        line.start();
                    
                        // Continuously read and play chunks of audio
                        int numRead = 0;
                        byte[] buf = new byte[line.getBufferSize()];
                        while ((numRead = stream.read(buf, 0, buf.length)) >= 0) {
                            int offset = 0;
                            while (offset < numRead) {
                                offset += line.write(buf, offset, numRead-offset);
                            }
                        }
                        line.drain();
                        line.stop();
                } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(1);
                }
        }
};
       
new Thread(background_music).start();

Author:  Hendo [ Sat May 24, 2008 10:15 am ]
Post subject:  Re: Background music

thanks for the thorough response, i'll test it out, thanks so much Very Happy

Author:  Hendo [ Sat May 24, 2008 10:41 am ]
Post subject:  Re: Background music

Hm, it doesn't like the Override commad
it says illegal token when I try to run
If I'm correct I delete my existing run method and replace it with yours? and then call the thread (new Thread (background_music).start (); ) in the titlescreen() section?

Author:  rizzix [ Sat May 24, 2008 4:32 pm ]
Post subject:  RE:Background music

Delete the @Override annotation (you're using and older version of Java).

what you do here is different. You first remove you "implements Runnable". Delete your run method. And pretty much copy-paste the 2nd half into your constructor.

You might have to change the code a bit. For example you most likely want to make the Thread a daemon thread.

Author:  Hendo [ Sun May 25, 2008 9:56 am ]
Post subject:  RE:Background music

daemon thread? :S
I'm really new to JAVA so I'm not sure what you mean by that Razz
Thanks for all your help so far though Smile

Author:  rizzix [ Sun May 25, 2008 1:35 pm ]
Post subject:  RE:Background music

Yea, using thread.setDaemon(true).

This will ensure that your program will quit when you quit your application. If you don't make the tread a daemon, then your program will continue to run till the music ends.

Author:  Hendo [ Sun May 25, 2008 6:32 pm ]
Post subject:  RE:Background music

oh! ok, thanks so much Very Happy

Author:  Hendo [ Mon May 26, 2008 12:38 pm ]
Post subject:  RE:Background music

Ok, I got it to work, but is there any way to loop DataLines? Or should I go back to trying to use clips? The sound is 13 seconds long and I just need to loop it

Author:  rizzix [ Mon May 26, 2008 3:02 pm ]
Post subject:  RE:Background music

Yea if it's that tiny, it's safe to use clips.

Author:  Hendo [ Mon May 26, 2008 3:26 pm ]
Post subject:  Re: Background music

alrighty cool, will the code i originally posted work fine (except modified so it loops), as long as it uses the runnable and threads that you used?

p.s. rizzix your a god send Very Happy

Author:  rizzix [ Mon May 26, 2008 3:50 pm ]
Post subject:  RE:Background music

Yep.

Author:  Hendo [ Mon May 26, 2008 4:32 pm ]
Post subject:  RE:Background music

sweet deal, thanks so much Very Happy

Author:  Hendo [ Mon May 26, 2008 5:09 pm ]
Post subject:  RE:Background music

Ok, for some reason my graphics don't show up until the song is over...is there something wrong with my threads? They look like this:
code:
Thread thread = new Thread (background_music);
        thread.setDaemon (true);
        thread.start ();

Author:  rizzix [ Mon May 26, 2008 6:42 pm ]
Post subject:  RE:Background music

Can you post the relevant code in its entirety?

Author:  Hendo [ Mon May 26, 2008 7:02 pm ]
Post subject:  Re: Background music

code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import javax.swing.JOptionPane;
import javax.sound.sampled.*;

public class titleScreen extends Frame implements KeyListener
{
    private Image title;
    private Image cursor;
    private MediaTracker tracker;
    private Thread thread;
    private Image offScrImg;
    private int cursorX = 217;
    private int cursorY = 183;
    private int select = 1;


    titleScreen ()
    {
        addKeyListener (this);
        tracker = new MediaTracker (this);
        title = Toolkit.getDefaultToolkit ().getImage ("graphics/titlescreen.png");
        tracker.addImage (title, 0);
        cursor = Toolkit.getDefaultToolkit ().getImage ("graphics/Cursor.png");
        tracker.addImage (cursor, 0);
        try
        {
            tracker.waitForID (0);
        }
        catch (InterruptedException e)
        {
            System.out.println (e);
        }
        int width = title.getWidth (this);
        int height = title.getHeight (this);
        setSize (width, height);
        setVisible (true);

        Runnable background_music = new Runnable ()
        {
            public void run ()
            {
                try
                {
                    AudioInputStream stream = AudioSystem.getAudioInputStream (new File ("ares.wav"));

                    // From URL
                    //stream = AudioSystem.getAudioInputStream(new URL("http://hostname/audiofile"));

                    // At present, ALAW and ULAW encodings must be converted
                    // to PCM_SIGNED before it can be played
                    AudioFormat format = stream.getFormat ();
                    if (format.getEncoding () != AudioFormat.Encoding.PCM_SIGNED)
                    {
                        format = new AudioFormat (
                                AudioFormat.Encoding.PCM_SIGNED,
                                format.getSampleRate (),
                                format.getSampleSizeInBits () * 2,
                                format.getChannels (),
                                format.getFrameSize () * 2,
                                format.getFrameRate (),
                                true);        // big endian
                        stream = AudioSystem.getAudioInputStream (format, stream);
                    }

                    // Create line
                    SourceDataLine.Info info = new DataLine.Info (
                            SourceDataLine.class, stream.getFormat (),
                            ((int) stream.getFrameLength () * format.getFrameSize ()));
                    SourceDataLine line = (SourceDataLine) AudioSystem.getLine (info);
                    line.open (stream.getFormat ());
                    line.start ();

                    // Continuously read and play chunks of audio
                    int numRead = 0;
                    byte[] buf = new byte [line.getBufferSize ()];
                    while ((numRead = stream.read (buf, 0, buf.length)) >= 0)
                    {
                        int offset = 0;
                        while (offset < numRead)
                        {
                            offset += line.write (buf, offset, numRead - offset);
                        }
                    }
                    line.drain ();
                    line.stop ();
                }
                catch (Exception e)
                {
                    e.printStackTrace ();
                    System.exit (1);
                }
                while (true)
                {
                    repaint ();
                    delay (10);
                }
            }

        }
        ;
        Thread thread = new Thread (background_music);
        thread.setDaemon (true);
        thread.start ();


    }


    public static void delay (int ms)
    {
        try
        {
            Thread.sleep (ms);
        }
        catch (Exception e)
        {
            ;
        }
    }

Author:  rizzix [ Mon May 26, 2008 8:53 pm ]
Post subject:  RE:Background music

The problem is with the following snippet
code:
while(true)
    {
         repaint ();
         delay (10);
    }


It blocks execution. In fact it does not let the "Frame" to be constructed, since the constructor never does return.

Now this is interesting, you've got me thinking. I wonder if it's wise to put that as part of the EDT. Hmm. My guess is, no, however you definitely need to call repaint inside the EDT. However I'm not too sure, again.

So, here's what I suggest, you create a Runnable to be executed in the EDT. Like this:
code:
Runnable repaint_in_edt = new Runnable() {
    public void run() {
         repaint ();
    }
};


Now in your main-thread (this is the thread that contains the code which creates the titleScreen object, etc). After the creation of everthing, add a while-loop:
code:
/// initialization / instantiation
while (true) {
    SwingUtilities.invokeAndWait(titleScreen_obejct.repaint_in_edt);
    delay(10);
}


Here the repaint_in_edt is a field of the class titleScreen (Bad naming convention btw, it should be TitleScreen).

Or you can simply create another thread that just runs that loop inside your constructor.

Author:  Hendo [ Tue May 27, 2008 6:42 am ]
Post subject:  RE:Background music

ok, this my sound weird but heres the thing. I'm at home right now, so i have one copy of my program here and another copy at school. The strange thing is my school one works fine without your code above...there must be a small dference in my school file compred to my file here at home. When I gt to school, I'll post the code to maybe explain how I pulled that miracle off, lol.


: