diff options
Diffstat (limited to 'songdbj/org/tritonus/file/jorbis/JorbisAudioFileReader.java')
-rw-r--r-- | songdbj/org/tritonus/file/jorbis/JorbisAudioFileReader.java | 231 |
1 files changed, 0 insertions, 231 deletions
diff --git a/songdbj/org/tritonus/file/jorbis/JorbisAudioFileReader.java b/songdbj/org/tritonus/file/jorbis/JorbisAudioFileReader.java deleted file mode 100644 index 5b33534b21..0000000000 --- a/songdbj/org/tritonus/file/jorbis/JorbisAudioFileReader.java +++ /dev/null | |||
@@ -1,231 +0,0 @@ | |||
1 | /* | ||
2 | * JorbisAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2001 by Matthias Pfisterer | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | |<--- this code is formatted to fit into 80 columns --->| | ||
27 | */ | ||
28 | |||
29 | package org.tritonus.sampled.file.jorbis; | ||
30 | |||
31 | import java.io.InputStream; | ||
32 | import java.io.IOException; | ||
33 | |||
34 | import javax.sound.sampled.AudioSystem; | ||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
38 | |||
39 | import org.tritonus.share.TDebug; | ||
40 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
41 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
42 | |||
43 | import com.jcraft.jogg.Buffer; | ||
44 | import com.jcraft.jogg.SyncState; | ||
45 | import com.jcraft.jogg.StreamState; | ||
46 | import com.jcraft.jogg.Page; | ||
47 | import com.jcraft.jogg.Packet; | ||
48 | |||
49 | |||
50 | |||
51 | /** | ||
52 | * @author Matthias Pfisterer | ||
53 | */ | ||
54 | public class JorbisAudioFileReader | ||
55 | extends TAudioFileReader | ||
56 | { | ||
57 | private static final int INITAL_READ_LENGTH = 4096; | ||
58 | private static final int MARK_LIMIT = INITAL_READ_LENGTH + 1; | ||
59 | |||
60 | |||
61 | |||
62 | public JorbisAudioFileReader() | ||
63 | { | ||
64 | super(MARK_LIMIT, true); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes) | ||
70 | throws UnsupportedAudioFileException, IOException | ||
71 | { | ||
72 | // sync and verify incoming physical bitstream | ||
73 | SyncState oggSyncState = new SyncState(); | ||
74 | |||
75 | // take physical pages, weld into a logical stream of packets | ||
76 | StreamState oggStreamState = new StreamState(); | ||
77 | |||
78 | // one Ogg bitstream page. Vorbis packets are inside | ||
79 | Page oggPage = new Page(); | ||
80 | |||
81 | // one raw packet of data for decode | ||
82 | Packet oggPacket = new Packet(); | ||
83 | |||
84 | int bytes = 0; | ||
85 | |||
86 | // Decode setup | ||
87 | |||
88 | oggSyncState.init(); // Now we can read pages | ||
89 | |||
90 | // grab some data at the head of the stream. We want the first page | ||
91 | // (which is guaranteed to be small and only contain the Vorbis | ||
92 | // stream initial header) We need the first page to get the stream | ||
93 | // serialno. | ||
94 | |||
95 | // submit a 4k block to libvorbis' Ogg layer | ||
96 | int index = oggSyncState.buffer(INITAL_READ_LENGTH); | ||
97 | bytes = inputStream.read(oggSyncState.data, index, INITAL_READ_LENGTH); | ||
98 | oggSyncState.wrote(bytes); | ||
99 | |||
100 | // Get the first page. | ||
101 | if (oggSyncState.pageout(oggPage) != 1) | ||
102 | { | ||
103 | // have we simply run out of data? If so, we're done. | ||
104 | if (bytes < 4096) | ||
105 | { | ||
106 | // IDEA: throw EOFException? | ||
107 | throw new UnsupportedAudioFileException("not a Vorbis stream: ended prematurely"); | ||
108 | } | ||
109 | throw new UnsupportedAudioFileException("not a Vorbis stream: not in Ogg bitstream format"); | ||
110 | } | ||
111 | |||
112 | // Get the serial number and set up the rest of decode. | ||
113 | // serialno first; use it to set up a logical stream | ||
114 | oggStreamState.init(oggPage.serialno()); | ||
115 | |||
116 | // extract the initial header from the first page and verify that the | ||
117 | // Ogg bitstream is in fact Vorbis data | ||
118 | |||
119 | // I handle the initial header first instead of just having the code | ||
120 | // read all three Vorbis headers at once because reading the initial | ||
121 | // header is an easy way to identify a Vorbis bitstream and it's | ||
122 | // useful to see that functionality seperated out. | ||
123 | |||
124 | if (oggStreamState.pagein(oggPage) < 0) | ||
125 | { | ||
126 | // error; stream version mismatch perhaps | ||
127 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read first page of Ogg bitstream data"); | ||
128 | } | ||
129 | |||
130 | if (oggStreamState.packetout(oggPacket) != 1) | ||
131 | { | ||
132 | // no page? must not be vorbis | ||
133 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read initial header packet"); | ||
134 | } | ||
135 | |||
136 | Buffer oggPacketBuffer = new Buffer(); | ||
137 | oggPacketBuffer.readinit(oggPacket.packet_base, oggPacket.packet, oggPacket.bytes); | ||
138 | |||
139 | int nPacketType = oggPacketBuffer.read(8); | ||
140 | byte[] buf = new byte[6]; | ||
141 | oggPacketBuffer.read(buf, 6); | ||
142 | if(buf[0]!='v' || buf[1]!='o' || buf[2]!='r' || | ||
143 | buf[3]!='b' || buf[4]!='i' || buf[5]!='s') | ||
144 | { | ||
145 | throw new UnsupportedAudioFileException("not a Vorbis stream: not a vorbis header packet"); | ||
146 | } | ||
147 | if (nPacketType != 1) | ||
148 | { | ||
149 | throw new UnsupportedAudioFileException("not a Vorbis stream: first packet is not the identification header"); | ||
150 | } | ||
151 | if(oggPacket.b_o_s == 0) | ||
152 | { | ||
153 | throw new UnsupportedAudioFileException("not a Vorbis stream: initial packet not marked as beginning of stream"); | ||
154 | } | ||
155 | int nVersion = oggPacketBuffer.read(32); | ||
156 | if (nVersion != 0) | ||
157 | { | ||
158 | throw new UnsupportedAudioFileException("not a Vorbis stream: wrong vorbis version"); | ||
159 | } | ||
160 | int nChannels = oggPacketBuffer.read(8); | ||
161 | float fSampleRate = oggPacketBuffer.read(32); | ||
162 | |||
163 | // These are only used for error checking. | ||
164 | int bitrate_upper = oggPacketBuffer.read(32); | ||
165 | int bitrate_nominal = oggPacketBuffer.read(32); | ||
166 | int bitrate_lower = oggPacketBuffer.read(32); | ||
167 | |||
168 | int[] blocksizes = new int[2]; | ||
169 | blocksizes[0] = 1 << oggPacketBuffer.read(4); | ||
170 | blocksizes[1] = 1 << oggPacketBuffer.read(4); | ||
171 | |||
172 | if (fSampleRate < 1.0F || | ||
173 | nChannels < 1 || | ||
174 | blocksizes[0] < 8|| | ||
175 | blocksizes[1] < blocksizes[0] || | ||
176 | oggPacketBuffer.read(1) != 1) | ||
177 | { | ||
178 | throw new UnsupportedAudioFileException("not a Vorbis stream: illegal values in initial header"); | ||
179 | } | ||
180 | |||
181 | |||
182 | if (TDebug.TraceAudioFileReader) { TDebug.out("JorbisAudioFileReader.getAudioFileFormat(): channels: " + nChannels); } | ||
183 | if (TDebug.TraceAudioFileReader) { TDebug.out("JorbisAudioFileReader.getAudioFileFormat(): rate: " + fSampleRate); } | ||
184 | |||
185 | /* | ||
186 | If the file size is known, we derive the number of frames | ||
187 | ('frame size') from it. | ||
188 | If the values don't fit into integers, we leave them at | ||
189 | NOT_SPECIFIED. 'Unknown' is considered less incorrect than | ||
190 | a wrong value. | ||
191 | */ | ||
192 | // [fb] not specifying it causes Sun's Wave file writer to write rubbish | ||
193 | int nByteSize = AudioSystem.NOT_SPECIFIED; | ||
194 | if (lFileSizeInBytes != AudioSystem.NOT_SPECIFIED | ||
195 | && lFileSizeInBytes <= Integer.MAX_VALUE) | ||
196 | { | ||
197 | nByteSize = (int) lFileSizeInBytes; | ||
198 | } | ||
199 | int nFrameSize = AudioSystem.NOT_SPECIFIED; | ||
200 | /* Can we calculate a useful size? | ||
201 | Peeking into ogginfo gives the insight that the only | ||
202 | way seems to be reading through the file. This is | ||
203 | something we do not want, at least not by default. | ||
204 | */ | ||
205 | // nFrameSize = (int) (lFileSizeInBytes / ...; | ||
206 | |||
207 | AudioFormat format = new AudioFormat( | ||
208 | new AudioFormat.Encoding("VORBIS"), | ||
209 | fSampleRate, | ||
210 | AudioSystem.NOT_SPECIFIED, | ||
211 | nChannels, | ||
212 | AudioSystem.NOT_SPECIFIED, | ||
213 | AudioSystem.NOT_SPECIFIED, | ||
214 | true); // this value is chosen arbitrarily | ||
215 | if (TDebug.TraceAudioFileReader) { TDebug.out("JorbisAudioFileReader.getAudioFileFormat(): AudioFormat: " + format); } | ||
216 | AudioFileFormat.Type type = new AudioFileFormat.Type("Ogg","ogg"); | ||
217 | AudioFileFormat audioFileFormat = | ||
218 | new TAudioFileFormat( | ||
219 | type, | ||
220 | format, | ||
221 | nFrameSize, | ||
222 | nByteSize); | ||
223 | if (TDebug.TraceAudioFileReader) { TDebug.out("JorbisAudioFileReader.getAudioFileFormat(): AudioFileFormat: " + audioFileFormat); } | ||
224 | return audioFileFormat; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | |||
229 | |||
230 | /*** JorbisAudioFileReader.java ***/ | ||
231 | |||