1 package de.jos.game.music;
2
3 import ibxm.FastTracker2;
4 import ibxm.IBXM;
5 import ibxm.Module;
6 import ibxm.ProTracker;
7 import ibxm.ScreamTracker3;
8
9 import java.io.DataInputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12
13 import javax.sound.sampled.AudioFormat;
14 import javax.sound.sampled.AudioSystem;
15 import javax.sound.sampled.LineEvent;
16 import javax.sound.sampled.LineListener;
17 import javax.sound.sampled.LineUnavailableException;
18 import javax.sound.sampled.SourceDataLine;
19
20 /***
21 *
22 * @author root
23 *
24 */
25 public class Player implements LineListener {
26
27 private Module module = null;
28
29 private BackgroundMusicThread thread = null;
30
31 public void initPlayer(String fileName) {
32 ClassLoader cl = Player.class.getClassLoader();
33 InputStream inputStream = cl.getResourceAsStream(fileName);
34 DataInputStream dataInputStream = new DataInputStream(inputStream);
35
36 byte[] s3m_header, mod_header;
37 byte[] xm_header = new byte[60];
38
39 try {
40 dataInputStream.readFully(xm_header);
41 if (FastTracker2.is_xm(xm_header)) {
42 module = FastTracker2.load_xm(xm_header, dataInputStream);
43 } else {
44 s3m_header = new byte[96];
45 System.arraycopy(xm_header, 0, s3m_header, 0, 60);
46 dataInputStream.readFully(s3m_header, 60, 36);
47 if (ScreamTracker3.is_s3m(s3m_header)) {
48 module = ScreamTracker3.load_s3m(s3m_header, dataInputStream);
49 } else {
50 mod_header = new byte[1084];
51 System.arraycopy(s3m_header, 0, mod_header, 0, 96);
52 dataInputStream.readFully(mod_header, 96, 988);
53 module = ProTracker.load_mod(mod_header, dataInputStream);
54 }
55 }
56 dataInputStream.close();
57 } catch (IOException e) {
58
59 e.printStackTrace();
60 }
61 }
62
63 public void playMusic() {
64 if (thread == null) {
65 thread = new BackgroundMusicThread(module, this);
66 thread.start();
67 }
68 }
69
70 public void stopMusic() {
71 if (thread != null) {
72 System.out.println("Stopping musing in player");
73 thread.setStopThreadFlag(true);
74 }
75 }
76
77 /***
78 * Notify the Player when the tune is over !
79 */
80 public void update(LineEvent event) {
81 System.out.println(event.getType());
82 System.out.println(event.getLine());
83 }
84
85 static final class BackgroundMusicThread extends Thread {
86
87 private Module module = null;
88
89 private boolean stopThreadFlag = false;
90
91 private LineListener listener = null;
92
93 public BackgroundMusicThread(Module module, LineListener listener) {
94 this.module = module;
95 this.listener = listener;
96 }
97
98 public void run() {
99 IBXM ibxm = new IBXM(48000);
100 byte[] outputBuffer = null;
101 ibxm.set_module(module);
102 int songDuration = ibxm.calculate_song_duration();
103 AudioFormat outputFormat = new AudioFormat(48000, 16, 2, true, false);
104 SourceDataLine outputLine = null;
105
106 try {
107 outputLine = AudioSystem.getSourceDataLine(outputFormat);
108 outputBuffer = new byte[1024 * 4];
109 outputLine.open();
110 } catch (LineUnavailableException e) {
111 e.printStackTrace();
112 return;
113 }
114
115 outputLine.start();
116 outputLine.addLineListener(listener);
117
118 int frames = 0;
119 while (songDuration > 0 && stopThreadFlag == false) {
120 frames = 1024;
121 if (frames > songDuration) {
122 frames = songDuration;
123 }
124 ibxm.get_audio(outputBuffer, frames);
125 outputLine.write(outputBuffer, 0, frames * 4);
126 songDuration -= frames;
127 }
128 outputLine.drain();
129 outputLine.close();
130
131 outputLine.removeLineListener(listener);
132 }
133
134 public void setStopThreadFlag(boolean stopThreadFlag) {
135 this.stopThreadFlag = stopThreadFlag;
136 }
137
138 }
139
140 }