summaryrefslogtreecommitdiff
path: root/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-01-08 23:53:00 +0000
commit7039a05147b8bbfc829babea1c65bd436450b505 (patch)
tree4ba555eb84ed97b72b0575034d5b0530a393713e /songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java
parent6d4c19707ef95942e323cbdc89fbbfdbe45e7cc5 (diff)
downloadrockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.gz
rockbox-7039a05147b8bbfc829babea1c65bd436450b505.zip
Splitting out songdbj
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java')
-rw-r--r--songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java334
1 files changed, 0 insertions, 334 deletions
diff --git a/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java b/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java
deleted file mode 100644
index e4e6fed00a..0000000000
--- a/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java
+++ /dev/null
@@ -1,334 +0,0 @@
1/*
2 * DecodedMpegAudioInputStream.
3 *
4 * JavaZOOM : mp3spi@javazoom.net
5 * http://www.javazoom.net
6 *
7 *-----------------------------------------------------------------------------
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Library General Public License as published
10 * by the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *------------------------------------------------------------------------
22 */
23
24package javazoom.spi.mpeg.sampled.convert;
25import java.io.IOException;
26import java.io.InputStream;
27import java.util.HashMap;
28import java.util.Map;
29
30import javax.sound.sampled.AudioFormat;
31import javax.sound.sampled.AudioInputStream;
32
33import javazoom.jl.decoder.Bitstream;
34import javazoom.jl.decoder.BitstreamException;
35import javazoom.jl.decoder.Decoder;
36import javazoom.jl.decoder.DecoderException;
37import javazoom.jl.decoder.Equalizer;
38import javazoom.jl.decoder.Header;
39import javazoom.jl.decoder.Obuffer;
40import javazoom.spi.PropertiesContainer;
41import javazoom.spi.mpeg.sampled.file.IcyListener;
42import javazoom.spi.mpeg.sampled.file.tag.TagParseEvent;
43import javazoom.spi.mpeg.sampled.file.tag.TagParseListener;
44
45import org.tritonus.share.TDebug;
46import org.tritonus.share.sampled.convert.TAsynchronousFilteredAudioInputStream;
47
48/**
49 * Main decoder.
50 */
51public class DecodedMpegAudioInputStream extends TAsynchronousFilteredAudioInputStream implements PropertiesContainer, TagParseListener
52{
53 private InputStream m_encodedStream;
54 private Bitstream m_bitstream;
55 private Decoder m_decoder;
56 private Equalizer m_equalizer;
57 private float[] m_equalizer_values;
58 private Header m_header;
59 private DMAISObuffer m_oBuffer;
60
61 // Bytes info.
62 private long byteslength = -1;
63 private long currentByte = 0;
64 // Frame info.
65 private int frameslength = -1;
66 private long currentFrame = 0;
67 private int currentFramesize = 0;
68 private int currentBitrate = -1;
69 // Time info.
70 private long currentMicrosecond = 0;
71 // Shoutcast stream info
72 private IcyListener shoutlst = null;
73
74
75 private HashMap properties = null;
76
77 public DecodedMpegAudioInputStream(AudioFormat outputFormat, AudioInputStream inputStream)
78 {
79 super(outputFormat, -1);
80 if (TDebug.TraceAudioConverter)
81 {
82 TDebug.out(">DecodedMpegAudioInputStream(AudioFormat outputFormat, AudioInputStream inputStream)");
83 }
84 try
85 {
86 // Try to find out inputstream length to allow skip.
87 byteslength = inputStream.available();
88 }
89 catch (IOException e)
90 {
91 TDebug.out("DecodedMpegAudioInputStream : Cannot run inputStream.available() : "+e.getMessage());
92 byteslength = -1;
93 }
94 m_encodedStream = inputStream;
95 shoutlst = IcyListener.getInstance();
96 shoutlst.reset();
97 m_bitstream = new Bitstream(inputStream);
98 m_decoder = new Decoder(null);
99 m_equalizer = new Equalizer();
100 m_equalizer_values = new float[32];
101 for (int b=0;b<m_equalizer.getBandCount();b++)
102 {
103 m_equalizer_values[b] = m_equalizer.getBand(b);
104 }
105 m_decoder.setEqualizer(m_equalizer);
106 m_oBuffer = new DMAISObuffer(outputFormat.getChannels());
107 m_decoder.setOutputBuffer(m_oBuffer);
108 try
109 {
110 m_header = m_bitstream.readFrame();
111 if ((m_header != null) && (frameslength == -1) && (byteslength > 0)) frameslength = m_header.max_number_of_frames((int)byteslength);
112 }
113 catch (BitstreamException e)
114 {
115 TDebug.out("DecodedMpegAudioInputStream : Cannot read first frame : "+e.getMessage());
116 byteslength = -1;
117 }
118 properties = new HashMap();
119 }
120
121 /**
122 * Return dynamic properties.
123 *
124 * <ul>
125 * <li><b>mp3.frame</b> [Long], current frame position.
126 * <li><b>mp3.frame.bitrate</b> [Integer], bitrate of the current frame.
127 * <li><b>mp3.frame.size.bytes</b> [Integer], size in bytes of the current frame.
128 * <li><b>mp3.position.byte</b> [Long], current position in bytes in the stream.
129 * <li><b>mp3.position.microseconds</b> [Long], elapsed microseconds.
130 * <li><b>mp3.equalizer</b> float[32], interactive equalizer array, values could be in [-1.0, +1.0].
131 * <li><b>mp3.shoutcast.metadata.key</b> [String], Shoutcast meta key with matching value.
132 * <br>For instance :
133 * <br>mp3.shoutcast.metadata.StreamTitle=Current song playing in stream.
134 * <br>mp3.shoutcast.metadata.StreamUrl=Url info.
135 * </ul>
136 */
137 public Map properties()
138 {
139 properties.put("mp3.frame",new Long(currentFrame));
140 properties.put("mp3.frame.bitrate",new Integer(currentBitrate));
141 properties.put("mp3.frame.size.bytes",new Integer(currentFramesize));
142 properties.put("mp3.position.byte",new Long(currentByte));
143 properties.put("mp3.position.microseconds",new Long(currentMicrosecond));
144 properties.put("mp3.equalizer",m_equalizer_values);
145 // Optionnal shoutcast stream meta-data.
146 if (shoutlst != null)
147 {
148 String surl = shoutlst.getStreamUrl();
149 String stitle = shoutlst.getStreamTitle();
150 if ((stitle != null) && (stitle.trim().length()>0)) properties.put("mp3.shoutcast.metadata.StreamTitle",stitle);
151 if ((surl != null) && (surl.trim().length()>0)) properties.put("mp3.shoutcast.metadata.StreamUrl",surl);
152 }
153 return properties;
154 }
155
156 public void execute()
157 {
158 if (TDebug.TraceAudioConverter) TDebug.out("execute() : begin");
159 try
160 {
161 // Following line hangs when FrameSize is available in AudioFormat.
162 Header header = null;
163 if (m_header == null) header = m_bitstream.readFrame();
164 else header = m_header;
165 if (TDebug.TraceAudioConverter) TDebug.out("execute() : header = "+header);
166 if (header == null)
167 {
168 if (TDebug.TraceAudioConverter)
169 {
170 TDebug.out("header is null (end of mpeg stream)");
171 }
172 getCircularBuffer().close();
173 return;
174 }
175 currentFrame++;
176 currentBitrate = header.bitrate_instant();
177 currentFramesize = header.calculate_framesize();
178 currentByte = currentByte + currentFramesize;
179 currentMicrosecond = (long) (currentFrame* header.ms_per_frame()*1000.0f);
180 for (int b=0;b<m_equalizer_values.length;b++)
181 {
182 m_equalizer.setBand(b,m_equalizer_values[b]);
183 }
184 m_decoder.setEqualizer(m_equalizer);
185 Obuffer decoderOutput = m_decoder.decodeFrame(header, m_bitstream);
186 m_bitstream.closeFrame();
187 getCircularBuffer().write(m_oBuffer.getBuffer(), 0, m_oBuffer.getCurrentBufferSize());
188 m_oBuffer.reset();
189 if (m_header != null) m_header = null;
190 }
191 catch (BitstreamException e)
192 {
193 if (TDebug.TraceAudioConverter)
194 {
195 TDebug.out(e);
196 }
197 }
198 catch (DecoderException e)
199 {
200 if (TDebug.TraceAudioConverter)
201 {
202 TDebug.out(e);
203 }
204 }
205 if (TDebug.TraceAudioConverter) TDebug.out("execute() : end");
206 }
207
208 public long skip(long bytes)
209 {
210 if ((byteslength > 0) && (frameslength > 0))
211 {
212 float ratio = bytes*1.0f/byteslength*1.0f;
213 long bytesread = skipFrames((long) (ratio*frameslength));
214 currentByte = currentByte + bytesread;
215 return bytesread;
216 }
217 else return -1;
218 }
219
220 /**
221 * Skip frames.
222 * You don't need to call it severals times, it will exactly skip given frames number.
223 * @param frames
224 * @return bytes length skipped matching to frames skipped.
225 */
226 public long skipFrames(long frames)
227 {
228 if (TDebug.TraceAudioConverter) TDebug.out("skip(long frames) : begin");
229 int framesRead = 0;
230 int bytesReads = 0;
231 try
232 {
233 for (int i=0;i<frames;i++)
234 {
235 Header header = m_bitstream.readFrame();
236 if (header != null)
237 {
238 int fsize = header.calculate_framesize();
239 bytesReads = bytesReads + fsize;
240 }
241 m_bitstream.closeFrame();
242 framesRead++;
243 }
244 }
245 catch (BitstreamException e)
246 {
247 if (TDebug.TraceAudioConverter) TDebug.out(e);
248 }
249 if (TDebug.TraceAudioConverter) TDebug.out("skip(long frames) : end");
250 currentFrame = currentFrame + framesRead;
251 return bytesReads;
252 }
253
254 private boolean isBigEndian()
255 {
256 return getFormat().isBigEndian();
257 }
258
259 public void close() throws IOException
260 {
261 super.close();
262 m_encodedStream.close();
263 }
264
265 private class DMAISObuffer extends Obuffer
266 {
267 private int m_nChannels;
268 private byte[] m_abBuffer;
269 private int[] m_anBufferPointers;
270 private boolean m_bIsBigEndian;
271 public DMAISObuffer(int nChannels)
272 {
273 m_nChannels = nChannels;
274 m_abBuffer = new byte[OBUFFERSIZE * nChannels];
275 m_anBufferPointers = new int[nChannels];
276 reset();
277 m_bIsBigEndian = DecodedMpegAudioInputStream.this.isBigEndian();
278 }
279 public void append(int nChannel, short sValue)
280 {
281 byte bFirstByte;
282 byte bSecondByte;
283 if (m_bIsBigEndian)
284 {
285 bFirstByte = (byte) ((sValue >>> 8) & 0xFF);
286 bSecondByte = (byte) (sValue & 0xFF);
287 }
288 else // little endian
289 {
290 bFirstByte = (byte) (sValue & 0xFF);
291 bSecondByte = (byte) ((sValue >>> 8) & 0xFF);
292 }
293 m_abBuffer[m_anBufferPointers[nChannel]] = bFirstByte;
294 m_abBuffer[m_anBufferPointers[nChannel] + 1] = bSecondByte;
295 m_anBufferPointers[nChannel] += m_nChannels * 2;
296 }
297 public void set_stop_flag()
298 {
299 }
300 public void close()
301 {
302 }
303 public void write_buffer(int nValue)
304 {
305 }
306 public void clear_buffer()
307 {
308 }
309 public byte[] getBuffer()
310 {
311 return m_abBuffer;
312 }
313 public int getCurrentBufferSize()
314 {
315 return m_anBufferPointers[0];
316 }
317 public void reset()
318 {
319 for (int i = 0; i < m_nChannels; i++)
320 {
321 /* Points to byte location,
322 * implicitely assuming 16 bit
323 * samples.
324 */
325 m_anBufferPointers[i] = i * 2;
326 }
327 }
328 }
329
330 public void tagParsed(TagParseEvent tpe)
331 {
332 System.out.println("TAG:"+tpe.getTag());
333 }
334}