import java.io.IOException;
import java.util.HashMap;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

/*
 * Created on 2006/11/05
 */

public class WaveEngine implements LineListener {
    // o^Å«éWAVEt@CÌÅå
    private int maxClips;
    // WAVEt@Cf[^i¼O->f[^{Ìj
    private HashMap<String, Clip> clipMap;
    // o^³ê½WAVEt@C
    private int counter = 0;

    /**
     * RXgN^
     */
    public WaveEngine() {
        this(256);
    }

    /**
     * RXgN^
     * 
     * @param maxClips
     *            o^Å«éWAVEt@CÌÅå
     */
    public WaveEngine(int maxClips) {
        this.maxClips = maxClips;
        clipMap = new HashMap<String, Clip>(maxClips);
    }

    /**
     * WAVEt@Cð[h
     * @param name o^¼
     * @param filename t@C¼
     */
    public void load(String name, String filename) {
        if (counter == maxClips) {
            System.out.println("G[: ±êÈão^Å«Ü¹ñ");
            return;
        }

        try {
            // I[fBIXg[ðJ­
            AudioInputStream stream = AudioSystem
                    .getAudioInputStream(getClass().getResource(filename));

            // I[fBI`®ðæ¾
            AudioFormat format = stream.getFormat();
            // ULAW/ALAW`®ÌêÍPCM`®ÉÏX
            if ((format.getEncoding() == AudioFormat.Encoding.ULAW)
                    || (format.getEncoding() == AudioFormat.Encoding.ALAW)) {
                AudioFormat newFormat = new AudioFormat(
                        AudioFormat.Encoding.PCM_SIGNED,
                        format.getSampleRate(),
                        format.getSampleSizeInBits() * 2, format.getChannels(),
                        format.getFrameSize() * 2, format.getFrameRate(), true);
                stream = AudioSystem.getAudioInputStream(newFormat, stream);
                format = newFormat;
            }

            // Cîñðæ¾
            DataLine.Info info = new DataLine.Info(Clip.class, format);
            // T|[g³êÄé`®©`FbN
            if (!AudioSystem.isLineSupported(info)) {
                System.out.println("G[: " + filename + "ÍT|[g³êÄ¢È¢`®Å·");
                System.exit(0);
            }

            // óÌNbvðì¬
            Clip clip = (Clip) AudioSystem.getLine(info);
            // NbvÌCxgðÄ
            clip.addLineListener(this);
            // I[fBIXg[ðNbvÆµÄJ­
            clip.open(stream);
            // Nbvðo^
            clipMap.put(name, clip);
            // Xg[ðÂ¶é
            stream.close();
        } catch (UnsupportedAudioFileException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }
    }

    /**
     * Ä¶
     * @param name o^¼
     */
    public void play(String name) {
        // ¼OÉÎ·éNbvðæ¾
        Clip clip = clipMap.get(name);
        if (clip != null) {
            clip.start();
        }
    }

    public void update(LineEvent event) {
        // Xgbv©ÅãÜÅÄ¶³ê½ê
        if (event.getType() == LineEvent.Type.STOP) {
            Clip clip = (Clip) event.getSource();
            clip.stop();
            clip.setFramePosition(0); // Ä¶ÊuðÅÉß·
        }
    }
}
