summaryrefslogtreecommitdiff
path: root/songdbj/de/jarnbjo/vorbis/VorbisStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/de/jarnbjo/vorbis/VorbisStream.java')
-rw-r--r--songdbj/de/jarnbjo/vorbis/VorbisStream.java247
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
36package de.jarnbjo.vorbis;
37
38import java.io.*;
39import java.util.*;
40
41import de.jarnbjo.ogg.*;
42import de.jarnbjo.util.io.*;
43
44/**
45 */
46
47public 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