diff options
author | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
---|---|---|
committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
commit | 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch) | |
tree | 4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/de/jarnbjo/vorbis/VorbisStream.java | |
parent | dfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff) | |
download | rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip |
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/de/jarnbjo/vorbis/VorbisStream.java')
-rw-r--r-- | songdbj/de/jarnbjo/vorbis/VorbisStream.java | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/songdbj/de/jarnbjo/vorbis/VorbisStream.java b/songdbj/de/jarnbjo/vorbis/VorbisStream.java new file mode 100644 index 0000000000..36659c7106 --- /dev/null +++ b/songdbj/de/jarnbjo/vorbis/VorbisStream.java | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * $ProjectName$ | ||
3 | * $ProjectRevision$ | ||
4 | * ----------------------------------------------------------- | ||
5 | * $Id$ | ||
6 | * ----------------------------------------------------------- | ||
7 | * | ||
8 | * $Author$ | ||
9 | * | ||
10 | * Description: | ||
11 | * | ||
12 | * Copyright 2002-2003 Tor-Einar Jarnbjo | ||
13 | * ----------------------------------------------------------- | ||
14 | * | ||
15 | * Change History | ||
16 | * ----------------------------------------------------------- | ||
17 | * $Log$ | ||
18 | * Revision 1.1 2005/07/11 15:42:36 hcl | ||
19 | * Songdb java version, source. only 1.5 compatible | ||
20 | * | ||
21 | * Revision 1.1.1.1 2004/04/04 22:09:12 shred | ||
22 | * First Import | ||
23 | * | ||
24 | * Revision 1.4 2003/04/10 19:49:04 jarnbjo | ||
25 | * no message | ||
26 | * | ||
27 | * Revision 1.3 2003/03/31 00:20:16 jarnbjo | ||
28 | * no message | ||
29 | * | ||
30 | * Revision 1.2 2003/03/16 01:11:12 jarnbjo | ||
31 | * no message | ||
32 | * | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | package de.jarnbjo.vorbis; | ||
37 | |||
38 | import java.io.*; | ||
39 | import java.util.*; | ||
40 | |||
41 | import de.jarnbjo.ogg.*; | ||
42 | import de.jarnbjo.util.io.*; | ||
43 | |||
44 | /** | ||
45 | */ | ||
46 | |||
47 | public class VorbisStream { | ||
48 | |||
49 | private LogicalOggStream oggStream; | ||
50 | private IdentificationHeader identificationHeader; | ||
51 | private CommentHeader commentHeader; | ||
52 | private SetupHeader setupHeader; | ||
53 | |||
54 | private AudioPacket lastAudioPacket, nextAudioPacket; | ||
55 | private LinkedList audioPackets=new LinkedList(); | ||
56 | private byte[] currentPcm; | ||
57 | private int currentPcmIndex; | ||
58 | private int currentPcmLimit; | ||
59 | |||
60 | private static final int IDENTIFICATION_HEADER = 1; | ||
61 | private static final int COMMENT_HEADER = 3; | ||
62 | private static final int SETUP_HEADER = 5; | ||
63 | |||
64 | private int bitIndex=0; | ||
65 | private byte lastByte=(byte)0; | ||
66 | private boolean initialized=false; | ||
67 | |||
68 | private Object streamLock=new Object(); | ||
69 | private int pageCounter=0; | ||
70 | |||
71 | private int currentBitRate=0; | ||
72 | |||
73 | private long currentGranulePosition; | ||
74 | |||
75 | public static final int BIG_ENDIAN = 0; | ||
76 | public static final int LITTLE_ENDIAN = 1; | ||
77 | |||
78 | public VorbisStream() { | ||
79 | } | ||
80 | |||
81 | public VorbisStream(LogicalOggStream oggStream) throws VorbisFormatException, IOException { | ||
82 | this.oggStream=oggStream; | ||
83 | |||
84 | for(int i=0; i<3; i++) { | ||
85 | BitInputStream source=new ByteArrayBitInputStream(oggStream.getNextOggPacket()); | ||
86 | int headerType=source.getInt(8); | ||
87 | switch(headerType) { | ||
88 | case IDENTIFICATION_HEADER: | ||
89 | identificationHeader=new IdentificationHeader(source); | ||
90 | break; | ||
91 | case COMMENT_HEADER: | ||
92 | commentHeader=new CommentHeader(source); | ||
93 | break; | ||
94 | case SETUP_HEADER: | ||
95 | setupHeader=new SetupHeader(this, source); | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | if(identificationHeader==null) { | ||
101 | throw new VorbisFormatException("The file has no identification header."); | ||
102 | } | ||
103 | |||
104 | if(commentHeader==null) { | ||
105 | throw new VorbisFormatException("The file has no commentHeader."); | ||
106 | } | ||
107 | |||
108 | if(setupHeader==null) { | ||
109 | throw new VorbisFormatException("The file has no setup header."); | ||
110 | } | ||
111 | |||
112 | //currentPcm=new int[identificationHeader.getChannels()][16384]; | ||
113 | currentPcm=new byte[identificationHeader.getChannels()*identificationHeader.getBlockSize1()*2]; | ||
114 | //new BufferThread().start(); | ||
115 | } | ||
116 | |||
117 | public IdentificationHeader getIdentificationHeader() { | ||
118 | return identificationHeader; | ||
119 | } | ||
120 | |||
121 | public CommentHeader getCommentHeader() { | ||
122 | return commentHeader; | ||
123 | } | ||
124 | |||
125 | protected SetupHeader getSetupHeader() { | ||
126 | return setupHeader; | ||
127 | } | ||
128 | |||
129 | public boolean isOpen() { | ||
130 | return oggStream.isOpen(); | ||
131 | } | ||
132 | |||
133 | public void close() throws IOException { | ||
134 | oggStream.close(); | ||
135 | } | ||
136 | |||
137 | |||
138 | public int readPcm(byte[] buffer, int offset, int length) throws IOException { | ||
139 | synchronized (streamLock) { | ||
140 | final int channels=identificationHeader.getChannels(); | ||
141 | |||
142 | if(lastAudioPacket==null) { | ||
143 | lastAudioPacket=getNextAudioPacket(); | ||
144 | } | ||
145 | if(currentPcm==null || currentPcmIndex>=currentPcmLimit) { | ||
146 | AudioPacket ap=getNextAudioPacket(); | ||
147 | try { | ||
148 | ap.getPcm(lastAudioPacket, currentPcm); | ||
149 | currentPcmLimit=ap.getNumberOfSamples()*identificationHeader.getChannels()*2; | ||
150 | } | ||
151 | catch(ArrayIndexOutOfBoundsException e) { | ||
152 | return 0; | ||
153 | } | ||
154 | currentPcmIndex=0; | ||
155 | lastAudioPacket=ap; | ||
156 | } | ||
157 | int written=0; | ||
158 | int i=0; | ||
159 | int arrIx=0; | ||
160 | for(i=currentPcmIndex; i<currentPcmLimit && arrIx<length; i++) { | ||
161 | buffer[offset+arrIx++]=currentPcm[i]; | ||
162 | written++; | ||
163 | } | ||
164 | currentPcmIndex=i; | ||
165 | return written; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | |||
170 | private AudioPacket getNextAudioPacket() throws VorbisFormatException, IOException { | ||
171 | pageCounter++; | ||
172 | byte[] data=oggStream.getNextOggPacket(); | ||
173 | AudioPacket res=null; | ||
174 | while(res==null) { | ||
175 | try { | ||
176 | res=new AudioPacket(this, new ByteArrayBitInputStream(data)); | ||
177 | } | ||
178 | catch(ArrayIndexOutOfBoundsException e) { | ||
179 | // ignore and continue with next packet | ||
180 | } | ||
181 | } | ||
182 | currentGranulePosition+=res.getNumberOfSamples(); | ||
183 | currentBitRate=data.length*8*identificationHeader.getSampleRate()/res.getNumberOfSamples(); | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | public long getCurrentGranulePosition() { | ||
188 | return currentGranulePosition; | ||
189 | } | ||
190 | |||
191 | public int getCurrentBitRate() { | ||
192 | return currentBitRate; | ||
193 | } | ||
194 | |||
195 | public byte[] processPacket(byte[] packet) throws VorbisFormatException, IOException { | ||
196 | if(packet.length==0) { | ||
197 | throw new VorbisFormatException("Cannot decode a vorbis packet with length = 0"); | ||
198 | } | ||
199 | if(((int)packet[0]&1)==1) { | ||
200 | // header packet | ||
201 | BitInputStream source=new ByteArrayBitInputStream(packet); | ||
202 | switch(source.getInt(8)) { | ||
203 | case IDENTIFICATION_HEADER: | ||
204 | identificationHeader=new IdentificationHeader(source); | ||
205 | break; | ||
206 | case COMMENT_HEADER: | ||
207 | commentHeader=new CommentHeader(source); | ||
208 | break; | ||
209 | case SETUP_HEADER: | ||
210 | setupHeader=new SetupHeader(this, source); | ||
211 | break; | ||
212 | } | ||
213 | return null; | ||
214 | } | ||
215 | else { | ||
216 | // audio packet | ||
217 | if(identificationHeader==null || | ||
218 | commentHeader==null || | ||
219 | setupHeader==null) { | ||
220 | |||
221 | throw new VorbisFormatException("Cannot decode audio packet before all three header packets have been decoded."); | ||
222 | } | ||
223 | |||
224 | AudioPacket ap=new AudioPacket(this, new ByteArrayBitInputStream(packet)); | ||
225 | currentGranulePosition+=ap.getNumberOfSamples(); | ||
226 | |||
227 | if(lastAudioPacket==null) { | ||
228 | lastAudioPacket=ap; | ||
229 | return null; | ||
230 | } | ||
231 | |||
232 | byte[] res=new byte[identificationHeader.getChannels()*ap.getNumberOfSamples()*2]; | ||
233 | |||
234 | try { | ||
235 | ap.getPcm(lastAudioPacket, res); | ||
236 | } | ||
237 | catch(IndexOutOfBoundsException e) { | ||
238 | java.util.Arrays.fill(res, (byte)0); | ||
239 | } | ||
240 | |||
241 | lastAudioPacket=ap; | ||
242 | |||
243 | return res; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | } \ No newline at end of file | ||