view game/SoundElement.java @ 22:afde253ec705

More work.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 31 Jan 2011 21:28:59 +0200
parents
children 0741dc117808
line wrap: on
line source

/*
 * Ristipolku Game Engine
 * (C) Copyright 2011 Matti 'ccr' Hämäläinen <ccr@tnsp.org>
 */
package game;

import java.util.*;
import java.io.*;
import game.*;
import javax.sound.sampled.*;


class SoundElement implements Runnable
{
    private final String name;

    private AudioInputStream stream;
    private AudioFormat format;
    private SourceDataLine line;
    private Thread playThread;
    private int loopCount;
    private boolean playing, streaming;
    private int volume = 100;

    byte[] buffer;
    int length;
    
    
    SoundElement(String filename, boolean streaming) throws IOException
    {
        this.name = filename;
        this.streaming = streaming;

        ResourceLoader res = new ResourceLoader(name);
        if (res == null || res.getStream() == null)
        {
            throw new IOException("Could not load audio resource '"+name+"'.\n");
        }


        try {
            stream = AudioSystem.getAudioInputStream(res.getStream());
            format = stream.getFormat();
        }
        catch (UnsupportedAudioFileException e) {
            throw new IOException("Unsupported audio file format for '"+name+"'.\n");
        }
        catch (IOException e)
        {
            throw new IOException("Could not load audio resource '"+name+"'.\n");
        }


        if (streaming) {
            System.out.print("Loading '"+name+"' as a clip\n");
            try {
                clip = AudioSystem.getClip();
                clip.open(stream);
            }
            catch (LineUnavailableException e)
            {
                throw new IOException("Line unavailable for '"+name+"'.\n");
            }
            finally {
                stream.close();
            }
        }
        else
        {
            clip = null;
            System.out.print("Loading '"+name+"' as stream\n");
            
            try {
                SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
                System.out.print("info: "+stream.getFrameLength() + ", " + format.getFrameSize() + "\n");
                line = (SourceDataLine) AudioSystem.getLine(info);
                line.open(format);
            }
            catch (LineUnavailableException e) {
                throw new IOException("Line unavailable for '"+name+"'.\n");
            }
        }
    }

    public void play()
    {
        System.out.print("Sound("+name+").play()\n");
        if (streaming)
        {
            clip.setFramePosition(0);
            clip.start();
        }
        else
        {
            if (playThread == null)
            {
                doPlay = true;
                loopCount = 1;
                playThread = new Thread(this);
                playThread.start();
            }
        }
    }
    
    public void loop(int n)
    {
        System.out.print("Sound("+name+").loop("+n+")\n");
        if (isClip())
        {
            clip.setFramePosition(0);
            if (n < 0)
                clip.loop(Clip.LOOP_CONTINUOUSLY);
            else
                clip.loop(n);
        }
        else
        {
            if (playThread == null)
            {
                doPlay = true;
                loopCount = n;
                playThread = new Thread(this);
                playThread.start();
            }
        }
    }
    
    public void stop()
    {
        if (isClip())
        {
            if (clip.isRunning())
                clip.stop();
        }
        else
        {
            if (playThread != null)
            {
                playThread.interrupt();
                doPlay = false;
                playThread = null;
            }
        }
    }
    
    public boolean isPlaying()
    {
        if (isClip())
            return clip.isRunning();
        else
            return (playThread != null && line.isRunning());
    }

    public void run()
    {
        line.start();
        byte[] buf = new byte[line.getBufferSize()];

        while (doPlay && (loopCount > 0 || loopCount == -1))
        {
            try {
                int numRead = 0;
                while ((numRead = stream.read(buf, 0, buf.length)) >= 0 && doPlay)
                {
                    int offset = 0;
                    while (offset < numRead)
                    {
                        System.out.print("audioThread: offs="+offset+", numread="+numRead+"\n");
                        offset += line.write(buf, offset, numRead - offset);
                    }
                }
                line.drain();

                System.out.print("audioThread: stream.reset()\n");
                stream.reset();
            }
            catch (IOException e) {
            }

            if (loopCount > 0)
                loopCount--;
        }
        
        line.stop();
        doPlay = false;
    }
}