diff options
Diffstat (limited to 'songdbj/org/tritonus/file')
26 files changed, 0 insertions, 3202 deletions
diff --git a/songdbj/org/tritonus/file/AiffAudioFileReader.java b/songdbj/org/tritonus/file/AiffAudioFileReader.java deleted file mode 100644 index 139ba05425..0000000000 --- a/songdbj/org/tritonus/file/AiffAudioFileReader.java +++ /dev/null | |||
@@ -1,244 +0,0 @@ | |||
1 | /* | ||
2 | * AiffAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 1999 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.DataInputStream; | ||
35 | import java.io.File; | ||
36 | import java.io.InputStream; | ||
37 | import java.io.IOException; | ||
38 | |||
39 | import javax.sound.sampled.AudioFormat; | ||
40 | import javax.sound.sampled.AudioFileFormat; | ||
41 | import javax.sound.sampled.AudioInputStream; | ||
42 | import javax.sound.sampled.AudioSystem; | ||
43 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
44 | |||
45 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
46 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
47 | import org.tritonus.share.TDebug; | ||
48 | |||
49 | |||
50 | /** Class for reading AIFF and AIFF-C files. | ||
51 | * | ||
52 | * @author Florian Bomers | ||
53 | * @author Matthias Pfisterer | ||
54 | */ | ||
55 | public class AiffAudioFileReader extends TAudioFileReader | ||
56 | { | ||
57 | private static final int READ_LIMIT = 1000; | ||
58 | |||
59 | |||
60 | |||
61 | public AiffAudioFileReader() | ||
62 | { | ||
63 | super(READ_LIMIT); | ||
64 | } | ||
65 | |||
66 | |||
67 | |||
68 | private void skipChunk(DataInputStream dataInputStream, int chunkLength, int chunkRead) | ||
69 | throws IOException { | ||
70 | chunkLength-=chunkRead; | ||
71 | if (chunkLength>0) { | ||
72 | dataInputStream.skip(chunkLength + (chunkLength % 2)); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | private AudioFormat readCommChunk(DataInputStream dataInputStream, int chunkLength) | ||
77 | throws IOException, UnsupportedAudioFileException { | ||
78 | |||
79 | int nNumChannels = dataInputStream.readShort(); | ||
80 | if (nNumChannels <= 0) { | ||
81 | throw new UnsupportedAudioFileException( | ||
82 | "not an AIFF file: number of channels must be positive"); | ||
83 | } | ||
84 | if (TDebug.TraceAudioFileReader) { | ||
85 | TDebug.out("Found "+nNumChannels+" channels."); | ||
86 | } | ||
87 | // ignored: frame count | ||
88 | dataInputStream.readInt(); | ||
89 | int nSampleSize = dataInputStream.readShort(); | ||
90 | float fSampleRate = (float) readIeeeExtended(dataInputStream); | ||
91 | if (fSampleRate <= 0.0) { | ||
92 | throw new UnsupportedAudioFileException( | ||
93 | "not an AIFF file: sample rate must be positive"); | ||
94 | } | ||
95 | if (TDebug.TraceAudioFileReader) { | ||
96 | TDebug.out("Found framerate "+fSampleRate); | ||
97 | } | ||
98 | AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; | ||
99 | int nRead=18; | ||
100 | if (chunkLength>nRead) { | ||
101 | int nEncoding=dataInputStream.readInt(); | ||
102 | nRead+=4; | ||
103 | if (nEncoding==AiffTool.AIFF_COMM_PCM) { | ||
104 | // PCM - nothing to do | ||
105 | } | ||
106 | else if (nEncoding==AiffTool.AIFF_COMM_ULAW) { | ||
107 | // ULAW | ||
108 | encoding=AudioFormat.Encoding.ULAW; | ||
109 | nSampleSize=8; | ||
110 | } | ||
111 | else if (nEncoding==AiffTool.AIFF_COMM_IMA_ADPCM) { | ||
112 | encoding = new AudioFormat.Encoding("IMA_ADPCM"); | ||
113 | nSampleSize=4; | ||
114 | } | ||
115 | else { | ||
116 | throw new UnsupportedAudioFileException( | ||
117 | "Encoding 0x"+Integer.toHexString(nEncoding) | ||
118 | +" of AIFF file not supported"); | ||
119 | } | ||
120 | } | ||
121 | /* In case of IMA ADPCM, frame size is 0.5 bytes (since it is | ||
122 | always mono). A value of 1 as frame size would be wrong. | ||
123 | Handling of frame size 0 in defined nowhere. So the best | ||
124 | solution is to set the frame size to unspecified (-1). | ||
125 | */ | ||
126 | int nFrameSize = (nSampleSize == 4) ? | ||
127 | AudioSystem.NOT_SPECIFIED : | ||
128 | calculateFrameSize(nSampleSize, nNumChannels); | ||
129 | if (TDebug.TraceAudioFileReader) { TDebug.out("calculated frame size: " + nFrameSize); } | ||
130 | skipChunk(dataInputStream, chunkLength, nRead); | ||
131 | AudioFormat format = new AudioFormat(encoding, | ||
132 | fSampleRate, | ||
133 | nSampleSize, | ||
134 | nNumChannels, | ||
135 | nFrameSize, | ||
136 | fSampleRate, | ||
137 | true); | ||
138 | return format; | ||
139 | } | ||
140 | |||
141 | private void readVerChunk(DataInputStream dataInputStream, int chunkLength) | ||
142 | throws IOException, UnsupportedAudioFileException { | ||
143 | if (chunkLength<4) { | ||
144 | throw new UnsupportedAudioFileException( | ||
145 | "Corrput AIFF file: FVER chunk too small."); | ||
146 | } | ||
147 | int nVer=dataInputStream.readInt(); | ||
148 | if (nVer!=AiffTool.AIFF_FVER_TIME_STAMP) { | ||
149 | throw new UnsupportedAudioFileException( | ||
150 | "Unsupported AIFF file: version not known."); | ||
151 | } | ||
152 | skipChunk(dataInputStream, chunkLength, 4); | ||
153 | } | ||
154 | |||
155 | |||
156 | |||
157 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes) | ||
158 | throws UnsupportedAudioFileException, IOException | ||
159 | { | ||
160 | if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): begin"); } | ||
161 | DataInputStream dataInputStream = new DataInputStream(inputStream); | ||
162 | int nMagic = dataInputStream.readInt(); | ||
163 | if (nMagic != AiffTool.AIFF_FORM_MAGIC) { | ||
164 | throw new UnsupportedAudioFileException( | ||
165 | "not an AIFF file: header magic is not FORM"); | ||
166 | } | ||
167 | int nTotalLength = dataInputStream.readInt(); | ||
168 | nMagic = dataInputStream.readInt(); | ||
169 | boolean bIsAifc; | ||
170 | if (nMagic == AiffTool.AIFF_AIFF_MAGIC) { | ||
171 | bIsAifc = false; | ||
172 | } else if (nMagic == AiffTool.AIFF_AIFC_MAGIC) { | ||
173 | bIsAifc = true; | ||
174 | } else { | ||
175 | throw new UnsupportedAudioFileException( | ||
176 | "unsupported IFF file: header magic neither AIFF nor AIFC"); | ||
177 | } | ||
178 | boolean bFVerFound=!bIsAifc; | ||
179 | boolean bCommFound=false; | ||
180 | boolean bSSndFound=false; | ||
181 | AudioFormat format=null; | ||
182 | int nDataChunkLength=0; | ||
183 | |||
184 | // walk through the chunks | ||
185 | // chunks may be in any order. However, in this implementation, SSND must be last | ||
186 | while (!bFVerFound || !bCommFound || !bSSndFound) { | ||
187 | nMagic = dataInputStream.readInt(); | ||
188 | int nChunkLength = dataInputStream.readInt(); | ||
189 | switch (nMagic) { | ||
190 | case AiffTool.AIFF_COMM_MAGIC: | ||
191 | format=readCommChunk(dataInputStream, nChunkLength); | ||
192 | if (TDebug.TraceAudioFileReader) { | ||
193 | TDebug.out("Read COMM chunk with length "+nChunkLength); | ||
194 | } | ||
195 | bCommFound=true; | ||
196 | break; | ||
197 | case AiffTool.AIFF_FVER_MAGIC: | ||
198 | if (!bFVerFound) { | ||
199 | readVerChunk(dataInputStream, nChunkLength); | ||
200 | if (TDebug.TraceAudioFileReader) { | ||
201 | TDebug.out("Read FVER chunk with length "+nChunkLength); | ||
202 | } | ||
203 | bFVerFound=true; | ||
204 | } else { | ||
205 | skipChunk(dataInputStream, nChunkLength, 0); | ||
206 | } | ||
207 | break; | ||
208 | case AiffTool.AIFF_SSND_MAGIC: | ||
209 | if (!bCommFound || !bFVerFound) { | ||
210 | throw new UnsupportedAudioFileException( | ||
211 | "cannot handle AIFF file: SSND not last chunk"); | ||
212 | } | ||
213 | bSSndFound=true; | ||
214 | nDataChunkLength=nChunkLength-8; | ||
215 | // 8 information bytes of no interest | ||
216 | dataInputStream.skip(8); | ||
217 | if (TDebug.TraceAudioFileReader) { | ||
218 | TDebug.out("Found SSND chunk with length "+nChunkLength); | ||
219 | } | ||
220 | break; | ||
221 | default: | ||
222 | if (TDebug.TraceAudioFileReader) { | ||
223 | TDebug.out("Skipping unknown chunk: " | ||
224 | +Integer.toHexString(nMagic)); | ||
225 | } | ||
226 | skipChunk(dataInputStream, nChunkLength, 0); | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | // TODO: length argument has to be in frames | ||
232 | AudioFileFormat audioFileFormat = new TAudioFileFormat( | ||
233 | bIsAifc ? AudioFileFormat.Type.AIFC : AudioFileFormat.Type.AIFF, | ||
234 | format, | ||
235 | nDataChunkLength / format.getFrameSize(), | ||
236 | nTotalLength + 8); | ||
237 | if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): end"); } | ||
238 | return audioFileFormat; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | |||
243 | |||
244 | /*** AiffAudioFileReader.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AiffAudioFileWriter.java b/songdbj/org/tritonus/file/AiffAudioFileWriter.java deleted file mode 100644 index cfd6996ae9..0000000000 --- a/songdbj/org/tritonus/file/AiffAudioFileWriter.java +++ /dev/null | |||
@@ -1,104 +0,0 @@ | |||
1 | /* | ||
2 | * AiffAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import java.io.IOException; | ||
34 | import java.util.Arrays; | ||
35 | |||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.AudioFormat; | ||
38 | import javax.sound.sampled.AudioInputStream; | ||
39 | import javax.sound.sampled.AudioSystem; | ||
40 | |||
41 | import org.tritonus.share.TDebug; | ||
42 | import org.tritonus.share.sampled.file.AudioOutputStream; | ||
43 | import org.tritonus.share.sampled.file.TAudioFileWriter; | ||
44 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Class for writing AIFF and AIFF-C files. | ||
49 | * | ||
50 | * @author Florian Bomers | ||
51 | */ | ||
52 | |||
53 | public class AiffAudioFileWriter extends TAudioFileWriter { | ||
54 | |||
55 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
56 | { | ||
57 | AudioFileFormat.Type.AIFF, | ||
58 | AudioFileFormat.Type.AIFC | ||
59 | }; | ||
60 | |||
61 | private static final int ALL=AudioSystem.NOT_SPECIFIED; | ||
62 | private static final AudioFormat.Encoding PCM_SIGNED = AudioFormat.Encoding.PCM_SIGNED; | ||
63 | private static final AudioFormat.Encoding ULAW = AudioFormat.Encoding.ULAW; | ||
64 | private static final AudioFormat.Encoding IMA_ADPCM = new AudioFormat.Encoding("IMA_ADPCM"); | ||
65 | |||
66 | // IMPORTANT: this array depends on the AudioFormat.match() algorithm which takes | ||
67 | // AudioSystem.NOT_SPECIFIED into account ! | ||
68 | private static final AudioFormat[] AUDIO_FORMATS = | ||
69 | { | ||
70 | new AudioFormat(PCM_SIGNED, ALL, 8, ALL, ALL, ALL, true), | ||
71 | new AudioFormat(PCM_SIGNED, ALL, 8, ALL, ALL, ALL, false), | ||
72 | new AudioFormat(ULAW, ALL, 8, ALL, ALL, ALL, false), | ||
73 | new AudioFormat(ULAW, ALL, 8, ALL, ALL, ALL, true), | ||
74 | new AudioFormat(PCM_SIGNED, ALL, 16, ALL, ALL, ALL, true), | ||
75 | new AudioFormat(PCM_SIGNED, ALL, 24, ALL, ALL, ALL, true), | ||
76 | new AudioFormat(PCM_SIGNED, ALL, 32, ALL, ALL, ALL, true), | ||
77 | new AudioFormat(IMA_ADPCM, ALL, 4, ALL, ALL, ALL, true), | ||
78 | new AudioFormat(IMA_ADPCM, ALL, 4, ALL, ALL, ALL, false), | ||
79 | }; | ||
80 | |||
81 | public AiffAudioFileWriter() { | ||
82 | super(Arrays.asList(FILE_TYPES), | ||
83 | Arrays.asList(AUDIO_FORMATS)); | ||
84 | } | ||
85 | |||
86 | |||
87 | protected boolean isAudioFormatSupportedImpl(AudioFormat format, | ||
88 | AudioFileFormat.Type fileType) { | ||
89 | return AiffTool.getFormatCode(format)!=AiffTool.AIFF_COMM_UNSPECIFIED; | ||
90 | } | ||
91 | |||
92 | |||
93 | protected AudioOutputStream getAudioOutputStream(AudioFormat audioFormat, | ||
94 | long lLengthInBytes, | ||
95 | AudioFileFormat.Type fileType, | ||
96 | TDataOutputStream dataOutputStream) throws IOException { | ||
97 | return new AiffAudioOutputStream(audioFormat, fileType, | ||
98 | lLengthInBytes, | ||
99 | dataOutputStream); | ||
100 | } | ||
101 | |||
102 | } | ||
103 | |||
104 | /*** AiffAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AiffAudioOutputStream.java b/songdbj/org/tritonus/file/AiffAudioOutputStream.java deleted file mode 100644 index d0006ebfe0..0000000000 --- a/songdbj/org/tritonus/file/AiffAudioOutputStream.java +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /* | ||
2 | * AiffAudioOutputStream.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import java.io.IOException; | ||
34 | import javax.sound.sampled.AudioFormat; | ||
35 | import javax.sound.sampled.AudioFileFormat; | ||
36 | import javax.sound.sampled.AudioSystem; | ||
37 | import org.tritonus.share.TDebug; | ||
38 | import org.tritonus.share.sampled.file.TAudioOutputStream; | ||
39 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
40 | |||
41 | |||
42 | /** | ||
43 | * AudioOutputStream for AIFF and AIFF-C files. | ||
44 | * | ||
45 | * @author Florian Bomers | ||
46 | */ | ||
47 | public class AiffAudioOutputStream extends TAudioOutputStream { | ||
48 | |||
49 | // this constant is used for chunk lengths when the length is not known yet | ||
50 | private static final int LENGTH_NOT_KNOWN=-1; | ||
51 | |||
52 | private AudioFileFormat.Type m_FileType; | ||
53 | |||
54 | public AiffAudioOutputStream(AudioFormat audioFormat, | ||
55 | AudioFileFormat.Type fileType, | ||
56 | long lLength, | ||
57 | TDataOutputStream dataOutputStream) { | ||
58 | super(audioFormat, | ||
59 | lLength, | ||
60 | dataOutputStream, | ||
61 | lLength == AudioSystem.NOT_SPECIFIED | ||
62 | && dataOutputStream.supportsSeek()); | ||
63 | // AIFF files cannot exceed 2GB | ||
64 | if (lLength != AudioSystem.NOT_SPECIFIED && lLength>0x7FFFFFFFl) { | ||
65 | throw new IllegalArgumentException( | ||
66 | "AIFF files cannot be larger than 2GB."); | ||
67 | } | ||
68 | // IDEA: write AIFF file instead of AIFC when encoding=PCM ? | ||
69 | m_FileType=fileType; | ||
70 | if (!audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED) | ||
71 | && !audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)) { | ||
72 | // only AIFC files can handle non-pcm data | ||
73 | m_FileType=AudioFileFormat.Type.AIFC; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | protected void writeHeader() | ||
78 | throws IOException { | ||
79 | if (TDebug.TraceAudioOutputStream) { | ||
80 | TDebug.out("AiffAudioOutputStream.writeHeader(): called."); | ||
81 | } | ||
82 | AudioFormat format = getFormat(); | ||
83 | boolean bIsAifc = m_FileType.equals(AudioFileFormat.Type.AIFC); | ||
84 | long lLength = getLength(); | ||
85 | TDataOutputStream dos = getDataOutputStream(); | ||
86 | int nCommChunkSize=18; | ||
87 | int nFormatCode=AiffTool.getFormatCode(format); | ||
88 | if (bIsAifc) { | ||
89 | // encoding takes 4 bytes | ||
90 | // encoding name takes at minimum 2 bytes | ||
91 | nCommChunkSize+=6; | ||
92 | } | ||
93 | int nHeaderSize=4 // magic | ||
94 | +8+nCommChunkSize // COMM chunk | ||
95 | +8; // header of SSND chunk | ||
96 | if (bIsAifc) { | ||
97 | // add length for FVER chunk | ||
98 | nHeaderSize+=12; | ||
99 | } | ||
100 | // if patching the header, and the length has not been known at first | ||
101 | // writing of the header, just truncate the size fields, don't throw an exception | ||
102 | if (lLength != AudioSystem.NOT_SPECIFIED && lLength+nHeaderSize>0x7FFFFFFFl) { | ||
103 | lLength=0x7FFFFFFFl-nHeaderSize; | ||
104 | } | ||
105 | // chunks must be on word-boundaries | ||
106 | long lSSndChunkSize=(lLength!=AudioSystem.NOT_SPECIFIED)? | ||
107 | (lLength+(lLength%2)+8):AudioSystem.NOT_SPECIFIED; | ||
108 | |||
109 | // write IFF container chunk | ||
110 | dos.writeInt(AiffTool.AIFF_FORM_MAGIC); | ||
111 | dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)? | ||
112 | ((int) (lSSndChunkSize+nHeaderSize)):LENGTH_NOT_KNOWN); | ||
113 | if (bIsAifc) { | ||
114 | dos.writeInt(AiffTool.AIFF_AIFC_MAGIC); | ||
115 | // write FVER chunk | ||
116 | dos.writeInt(AiffTool.AIFF_FVER_MAGIC); | ||
117 | dos.writeInt(4); | ||
118 | dos.writeInt(AiffTool.AIFF_FVER_TIME_STAMP); | ||
119 | } else { | ||
120 | dos.writeInt(AiffTool.AIFF_AIFF_MAGIC); | ||
121 | } | ||
122 | |||
123 | // write COMM chunk | ||
124 | dos.writeInt(AiffTool.AIFF_COMM_MAGIC); | ||
125 | dos.writeInt(nCommChunkSize); | ||
126 | dos.writeShort((short) format.getChannels()); | ||
127 | dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)? | ||
128 | ((int) (lLength / format.getFrameSize())):LENGTH_NOT_KNOWN); | ||
129 | if (nFormatCode==AiffTool.AIFF_COMM_ULAW) { | ||
130 | // AIFF ulaw states 16 bits for ulaw data | ||
131 | dos.writeShort(16); | ||
132 | } else { | ||
133 | dos.writeShort((short) format.getSampleSizeInBits()); | ||
134 | } | ||
135 | writeIeeeExtended(dos, format.getSampleRate()); | ||
136 | if (bIsAifc) { | ||
137 | dos.writeInt(nFormatCode); | ||
138 | dos.writeShort(0); // no encoding name | ||
139 | // TODO: write encoding.toString() ?? | ||
140 | } | ||
141 | |||
142 | // write header of SSND chunk | ||
143 | |||
144 | |||
145 | |||
146 | dos.writeInt(AiffTool.AIFF_SSND_MAGIC); | ||
147 | // don't use lSSndChunkSize here ! | ||
148 | dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED) | ||
149 | ?((int) (lLength+8)):LENGTH_NOT_KNOWN); | ||
150 | // 8 information bytes of no interest | ||
151 | dos.writeInt(0); // offset | ||
152 | dos.writeInt(0); // blocksize | ||
153 | } | ||
154 | |||
155 | |||
156 | |||
157 | |||
158 | protected void patchHeader() | ||
159 | throws IOException { | ||
160 | TDataOutputStream tdos = getDataOutputStream(); | ||
161 | tdos.seek(0); | ||
162 | setLengthFromCalculatedLength(); | ||
163 | writeHeader(); | ||
164 | } | ||
165 | |||
166 | public void close() throws IOException { | ||
167 | long nBytesWritten=getCalculatedLength(); | ||
168 | |||
169 | if ((nBytesWritten % 2)==1) { | ||
170 | if (TDebug.TraceAudioOutputStream) { | ||
171 | TDebug.out("AiffOutputStream.close(): adding padding byte"); | ||
172 | } | ||
173 | // extra byte for to align on word boundaries | ||
174 | TDataOutputStream tdos = getDataOutputStream(); | ||
175 | tdos.writeByte(0); | ||
176 | // DON'T adjust calculated length ! | ||
177 | } | ||
178 | |||
179 | |||
180 | |||
181 | super.close(); | ||
182 | } | ||
183 | |||
184 | public void writeIeeeExtended(TDataOutputStream dos, float sampleRate) throws IOException { | ||
185 | // currently, only integer sample rates are written | ||
186 | // TODO: real conversion | ||
187 | // I don't know exactly how much I have to shift left the mantisse for normalisation | ||
188 | // now I do it so that there are any bits set in the first 5 bits | ||
189 | int nSampleRate=(int) sampleRate; | ||
190 | short ieeeExponent=0; | ||
191 | while ((nSampleRate!=0) && (nSampleRate & 0x80000000)==0) { | ||
192 | ieeeExponent++; | ||
193 | nSampleRate<<=1; | ||
194 | } | ||
195 | dos.writeShort(16414-ieeeExponent); // exponent | ||
196 | dos.writeInt(nSampleRate); // mantisse high double word | ||
197 | dos.writeInt(0); // mantisse low double word | ||
198 | } | ||
199 | |||
200 | |||
201 | |||
202 | |||
203 | } | ||
204 | |||
205 | /*** AiffAudioOutputStream.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AiffTool.java b/songdbj/org/tritonus/file/AiffTool.java deleted file mode 100644 index 39cdbf0878..0000000000 --- a/songdbj/org/tritonus/file/AiffTool.java +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /* | ||
2 | * AiffTool.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import javax.sound.sampled.AudioFormat; | ||
34 | import javax.sound.sampled.AudioFileFormat; | ||
35 | import javax.sound.sampled.AudioSystem; | ||
36 | |||
37 | |||
38 | /** | ||
39 | * Common constants and methods for handling aiff and aiff-c files. | ||
40 | * | ||
41 | * @author Florian Bomers | ||
42 | */ | ||
43 | |||
44 | public class AiffTool { | ||
45 | |||
46 | public static final int AIFF_FORM_MAGIC = 0x464F524D; | ||
47 | public static final int AIFF_AIFF_MAGIC = 0x41494646; | ||
48 | public static final int AIFF_AIFC_MAGIC = 0x41494643; | ||
49 | public static final int AIFF_COMM_MAGIC = 0x434F4D4D; | ||
50 | public static final int AIFF_SSND_MAGIC = 0x53534E44; | ||
51 | public static final int AIFF_FVER_MAGIC = 0x46564552; | ||
52 | public static final int AIFF_COMM_UNSPECIFIED = 0x00000000; // "0000" | ||
53 | public static final int AIFF_COMM_PCM = 0x4E4F4E45; // "NONE" | ||
54 | public static final int AIFF_COMM_ULAW = 0x756C6177; // "ulaw" | ||
55 | public static final int AIFF_COMM_IMA_ADPCM = 0x696D6134; // "ima4" | ||
56 | public static final int AIFF_FVER_TIME_STAMP = 0xA2805140; // May 23, 1990, 2:40pm | ||
57 | |||
58 | public static int getFormatCode(AudioFormat format) { | ||
59 | AudioFormat.Encoding encoding = format.getEncoding(); | ||
60 | int nSampleSize = format.getSampleSizeInBits(); | ||
61 | boolean bigEndian = format.isBigEndian(); | ||
62 | // $$fb 2000-08-16: check the frame size, too. | ||
63 | boolean frameSizeOK=format.getFrameSize()==AudioSystem.NOT_SPECIFIED | ||
64 | || format.getChannels()!=AudioSystem.NOT_SPECIFIED | ||
65 | || format.getFrameSize()==nSampleSize/8*format.getChannels(); | ||
66 | |||
67 | if ((encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) | ||
68 | && ((bigEndian && nSampleSize>=16 && nSampleSize<=32) || (nSampleSize==8)) | ||
69 | && frameSizeOK) { | ||
70 | return AIFF_COMM_PCM; | ||
71 | } else if (encoding.equals(AudioFormat.Encoding.ULAW) && nSampleSize == 8 && frameSizeOK) { | ||
72 | return AIFF_COMM_ULAW; | ||
73 | } else if (encoding.equals(new AudioFormat.Encoding("IMA_ADPCM")) && nSampleSize == 4) { | ||
74 | return AIFF_COMM_IMA_ADPCM; | ||
75 | } else { | ||
76 | return AIFF_COMM_UNSPECIFIED; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | } | ||
81 | |||
82 | /*** AiffTool.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AuAudioFileReader.java b/songdbj/org/tritonus/file/AuAudioFileReader.java deleted file mode 100644 index b527920118..0000000000 --- a/songdbj/org/tritonus/file/AuAudioFileReader.java +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | * AuAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999,2000,2001 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 1999 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.DataInputStream; | ||
35 | import java.io.File; | ||
36 | import java.io.InputStream; | ||
37 | import java.io.IOException; | ||
38 | |||
39 | import javax.sound.sampled.AudioFormat; | ||
40 | import javax.sound.sampled.AudioFileFormat; | ||
41 | import javax.sound.sampled.AudioInputStream; | ||
42 | import javax.sound.sampled.AudioSystem; | ||
43 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
44 | import javax.sound.sampled.spi.AudioFileReader; | ||
45 | |||
46 | import org.tritonus.share.TDebug; | ||
47 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
48 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
49 | |||
50 | |||
51 | /** Class for reading Sun/Next AU files. | ||
52 | * | ||
53 | * @author Florian Bomers | ||
54 | * @author Matthias Pfisterer | ||
55 | */ | ||
56 | public class AuAudioFileReader extends TAudioFileReader | ||
57 | { | ||
58 | private static final int READ_LIMIT = 1000; | ||
59 | |||
60 | |||
61 | |||
62 | public AuAudioFileReader() | ||
63 | { | ||
64 | super(READ_LIMIT); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | private static String readDescription(DataInputStream dis, int len) throws IOException { | ||
70 | byte c=-1; | ||
71 | String ret=""; | ||
72 | while (len>0 && (c=dis.readByte())!=0) { | ||
73 | ret=ret+(char) c; | ||
74 | len--; | ||
75 | } | ||
76 | if (len>1 && c==0) { | ||
77 | dis.skip(len-1); | ||
78 | } | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | |||
83 | |||
84 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes) | ||
85 | throws UnsupportedAudioFileException, IOException | ||
86 | { | ||
87 | if (TDebug.TraceAudioFileReader) {TDebug.out("AuAudioFileReader.getAudioFileFormat(InputStream, long): begin"); } | ||
88 | DataInputStream dataInputStream = new DataInputStream(inputStream); | ||
89 | int nMagic = dataInputStream.readInt(); | ||
90 | if (nMagic != AuTool.AU_HEADER_MAGIC) { | ||
91 | throw new UnsupportedAudioFileException( | ||
92 | "not an AU file: wrong header magic"); | ||
93 | } | ||
94 | int nDataOffset = dataInputStream.readInt(); | ||
95 | if (TDebug.TraceAudioFileReader) { | ||
96 | TDebug.out("AuAudioFileReader.getAudioFileFormat(): data offset: " + nDataOffset); | ||
97 | } | ||
98 | if (nDataOffset < AuTool.DATA_OFFSET) { | ||
99 | throw new UnsupportedAudioFileException( | ||
100 | "not an AU file: data offset must be 24 or greater"); | ||
101 | } | ||
102 | int nDataLength = dataInputStream.readInt(); | ||
103 | if (TDebug.TraceAudioFileReader) { | ||
104 | TDebug.out("AuAudioFileReader.getAudioFileFormat(): data length: " + nDataLength); | ||
105 | } | ||
106 | if (nDataLength < 0 && nDataLength!=AuTool.AUDIO_UNKNOWN_SIZE) { | ||
107 | throw new UnsupportedAudioFileException( | ||
108 | "not an AU file: data length must be positive, 0 or -1 for unknown"); | ||
109 | } | ||
110 | AudioFormat.Encoding encoding = null; | ||
111 | int nSampleSize = 0; | ||
112 | int nEncoding = dataInputStream.readInt(); | ||
113 | switch (nEncoding) { | ||
114 | case AuTool.SND_FORMAT_MULAW_8: // 8-bit uLaw G.711 | ||
115 | encoding = AudioFormat.Encoding.ULAW; | ||
116 | nSampleSize = 8; | ||
117 | break; | ||
118 | |||
119 | case AuTool.SND_FORMAT_LINEAR_8: | ||
120 | encoding = AudioFormat.Encoding.PCM_SIGNED; | ||
121 | nSampleSize = 8; | ||
122 | break; | ||
123 | |||
124 | case AuTool.SND_FORMAT_LINEAR_16: | ||
125 | encoding = AudioFormat.Encoding.PCM_SIGNED; | ||
126 | nSampleSize = 16; | ||
127 | break; | ||
128 | |||
129 | case AuTool.SND_FORMAT_LINEAR_24: | ||
130 | encoding = AudioFormat.Encoding.PCM_SIGNED; | ||
131 | nSampleSize = 24; | ||
132 | break; | ||
133 | |||
134 | case AuTool.SND_FORMAT_LINEAR_32: | ||
135 | encoding = AudioFormat.Encoding.PCM_SIGNED; | ||
136 | nSampleSize = 32; | ||
137 | break; | ||
138 | |||
139 | case AuTool.SND_FORMAT_ALAW_8: // 8-bit aLaw G.711 | ||
140 | encoding = AudioFormat.Encoding.ALAW; | ||
141 | nSampleSize = 8; | ||
142 | break; | ||
143 | } | ||
144 | if (nSampleSize == 0) { | ||
145 | throw new UnsupportedAudioFileException( | ||
146 | "unsupported AU file: unknown encoding " + nEncoding); | ||
147 | } | ||
148 | int nSampleRate = dataInputStream.readInt(); | ||
149 | if (nSampleRate <= 0) { | ||
150 | throw new UnsupportedAudioFileException( | ||
151 | "corrupt AU file: sample rate must be positive"); | ||
152 | } | ||
153 | int nNumChannels = dataInputStream.readInt(); | ||
154 | if (nNumChannels <= 0) { | ||
155 | throw new UnsupportedAudioFileException( | ||
156 | "corrupt AU file: number of channels must be positive"); | ||
157 | } | ||
158 | // skip header information field | ||
159 | inputStream.skip(nDataOffset - AuTool.DATA_OFFSET); | ||
160 | // read header info field | ||
161 | //String desc=readDescription(dataInputStream, nDataOffset - AuTool.DATA_OFFSET); | ||
162 | |||
163 | AudioFormat format = new AudioFormat(encoding, | ||
164 | (float) nSampleRate, | ||
165 | nSampleSize, | ||
166 | nNumChannels, | ||
167 | calculateFrameSize(nSampleSize, nNumChannels), | ||
168 | (float) nSampleRate, | ||
169 | true); | ||
170 | AudioFileFormat audioFileFormat = new TAudioFileFormat( | ||
171 | AudioFileFormat.Type.AU, | ||
172 | format, | ||
173 | (nDataLength==AuTool.AUDIO_UNKNOWN_SIZE)? | ||
174 | AudioSystem.NOT_SPECIFIED:(nDataLength / format.getFrameSize()), | ||
175 | (nDataLength==AuTool.AUDIO_UNKNOWN_SIZE)? | ||
176 | AudioSystem.NOT_SPECIFIED:(nDataLength + nDataOffset)); | ||
177 | if (TDebug.TraceAudioFileReader) { TDebug.out("AuAudioFileReader.getAudioFileFormat(InputStream, long): begin"); } | ||
178 | return audioFileFormat; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
184 | /*** AuAudioFileReader.java ***/ | ||
185 | |||
diff --git a/songdbj/org/tritonus/file/AuAudioFileWriter.java b/songdbj/org/tritonus/file/AuAudioFileWriter.java deleted file mode 100644 index 5ac80a8c8a..0000000000 --- a/songdbj/org/tritonus/file/AuAudioFileWriter.java +++ /dev/null | |||
@@ -1,104 +0,0 @@ | |||
1 | /* | ||
2 | * AuAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999,2000,2001 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 1999 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.IOException; | ||
35 | import java.util.Arrays; | ||
36 | |||
37 | import javax.sound.sampled.AudioFileFormat; | ||
38 | import javax.sound.sampled.AudioFormat; | ||
39 | import javax.sound.sampled.AudioInputStream; | ||
40 | import javax.sound.sampled.AudioSystem; | ||
41 | |||
42 | import org.tritonus.share.TDebug; | ||
43 | import org.tritonus.share.sampled.file.AudioOutputStream; | ||
44 | import org.tritonus.share.sampled.file.TAudioFileWriter; | ||
45 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
46 | |||
47 | |||
48 | /** | ||
49 | * AudioFileWriter for Sun/Next AU files. | ||
50 | * | ||
51 | * @author Florian Bomers | ||
52 | * @author Matthias Pfisterer | ||
53 | */ | ||
54 | public class AuAudioFileWriter extends TAudioFileWriter { | ||
55 | |||
56 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
57 | { | ||
58 | AudioFileFormat.Type.AU | ||
59 | }; | ||
60 | |||
61 | private static final int ALL=AudioSystem.NOT_SPECIFIED; | ||
62 | |||
63 | // IMPORTANT: this array depends on the AudioFormat.match() algorithm which takes | ||
64 | // AudioSystem.NOT_SPECIFIED into account ! | ||
65 | private static final AudioFormat[] AUDIO_FORMATS = | ||
66 | { | ||
67 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 8, ALL, ALL, ALL, true), | ||
68 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 8, ALL, ALL, ALL, false), | ||
69 | |||
70 | new AudioFormat(AudioFormat.Encoding.ULAW, ALL, 8, ALL, ALL, ALL, false), | ||
71 | new AudioFormat(AudioFormat.Encoding.ULAW, ALL, 8, ALL, ALL, ALL, true), | ||
72 | |||
73 | new AudioFormat(AudioFormat.Encoding.ALAW, ALL, 8, ALL, ALL, ALL, false), | ||
74 | new AudioFormat(AudioFormat.Encoding.ALAW, ALL, 8, ALL, ALL, ALL, true), | ||
75 | |||
76 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 16, ALL, ALL, ALL, true), | ||
77 | |||
78 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 24, ALL, ALL, ALL, true), | ||
79 | |||
80 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 32, ALL, ALL, ALL, true), | ||
81 | }; | ||
82 | |||
83 | public AuAudioFileWriter() { | ||
84 | super(Arrays.asList(FILE_TYPES), | ||
85 | Arrays.asList(AUDIO_FORMATS)); | ||
86 | } | ||
87 | |||
88 | |||
89 | protected boolean isAudioFormatSupportedImpl(AudioFormat format, | ||
90 | AudioFileFormat.Type fileType) { | ||
91 | return AuTool.getFormatCode(format)!=AuTool.SND_FORMAT_UNSPECIFIED; | ||
92 | } | ||
93 | protected AudioOutputStream getAudioOutputStream(AudioFormat audioFormat, | ||
94 | long lLengthInBytes, | ||
95 | AudioFileFormat.Type fileType, | ||
96 | TDataOutputStream dataOutputStream) throws IOException { | ||
97 | return new AuAudioOutputStream(audioFormat, | ||
98 | lLengthInBytes, | ||
99 | dataOutputStream); | ||
100 | } | ||
101 | |||
102 | } | ||
103 | |||
104 | /*** AuAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AuAudioOutputStream.java b/songdbj/org/tritonus/file/AuAudioOutputStream.java deleted file mode 100644 index 9f33e7a2aa..0000000000 --- a/songdbj/org/tritonus/file/AuAudioOutputStream.java +++ /dev/null | |||
@@ -1,121 +0,0 @@ | |||
1 | /* | ||
2 | * AuAudioOutputStream.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000,2001 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 1999 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.IOException; | ||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.AudioSystem; | ||
38 | import org.tritonus.share.TDebug; | ||
39 | import org.tritonus.share.sampled.file.TAudioOutputStream; | ||
40 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
41 | |||
42 | |||
43 | |||
44 | /** | ||
45 | * AudioOutputStream for AU files. | ||
46 | * | ||
47 | * @author Florian Bomers | ||
48 | * @author Matthias Pfisterer | ||
49 | */ | ||
50 | |||
51 | public class AuAudioOutputStream extends TAudioOutputStream { | ||
52 | |||
53 | private static String description="Created by Tritonus"; | ||
54 | |||
55 | /** | ||
56 | * Writes a null-terminated ascii string s to f. | ||
57 | * The total number of bytes written is aligned on a 2byte boundary. | ||
58 | * @exception IOException Write error. | ||
59 | */ | ||
60 | protected static void writeText(TDataOutputStream dos, String s) throws IOException { | ||
61 | if (s.length()>0) { | ||
62 | dos.writeBytes(s); | ||
63 | dos.writeByte(0); // pour terminer le texte | ||
64 | if ((s.length() % 2)==0) { | ||
65 | // ajout d'un zero pour faire la longeur pair | ||
66 | dos.writeByte(0); | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Returns number of bytes that have to written for string s (with alignment) | ||
73 | */ | ||
74 | protected static int getTextLength(String s) { | ||
75 | if (s.length()==0) { | ||
76 | return 0; | ||
77 | } else { | ||
78 | return (s.length()+2) & 0xFFFFFFFE; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | public AuAudioOutputStream(AudioFormat audioFormat, | ||
83 | long lLength, | ||
84 | TDataOutputStream dataOutputStream) { | ||
85 | // if length exceeds 2GB, set the length field to NOT_SPECIFIED | ||
86 | super(audioFormat, | ||
87 | lLength>0x7FFFFFFFl?AudioSystem.NOT_SPECIFIED:lLength, | ||
88 | dataOutputStream, | ||
89 | lLength == AudioSystem.NOT_SPECIFIED && dataOutputStream.supportsSeek()); | ||
90 | } | ||
91 | |||
92 | protected void writeHeader() throws IOException { | ||
93 | if (TDebug.TraceAudioOutputStream) { | ||
94 | TDebug.out("AuAudioOutputStream.writeHeader(): called."); | ||
95 | } | ||
96 | AudioFormat format = getFormat(); | ||
97 | long lLength = getLength(); | ||
98 | TDataOutputStream dos = getDataOutputStream(); | ||
99 | if (TDebug.TraceAudioOutputStream) { | ||
100 | TDebug.out("AuAudioOutputStream.writeHeader(): AudioFormat: " + format); | ||
101 | TDebug.out("AuAudioOutputStream.writeHeader(): length: " + lLength); | ||
102 | } | ||
103 | |||
104 | dos.writeInt(AuTool.AU_HEADER_MAGIC); | ||
105 | dos.writeInt(AuTool.DATA_OFFSET+getTextLength(description)); | ||
106 | dos.writeInt((lLength!=AudioSystem.NOT_SPECIFIED)?((int) lLength):AuTool.AUDIO_UNKNOWN_SIZE); | ||
107 | dos.writeInt(AuTool.getFormatCode(format)); | ||
108 | dos.writeInt((int) format.getSampleRate()); | ||
109 | dos.writeInt(format.getChannels()); | ||
110 | writeText(dos, description); | ||
111 | } | ||
112 | |||
113 | protected void patchHeader() throws IOException { | ||
114 | TDataOutputStream tdos = getDataOutputStream(); | ||
115 | tdos.seek(0); | ||
116 | setLengthFromCalculatedLength(); | ||
117 | writeHeader(); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /*** AuAudioOutputStream.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/AuTool.java b/songdbj/org/tritonus/file/AuTool.java deleted file mode 100644 index bcdc62f86c..0000000000 --- a/songdbj/org/tritonus/file/AuTool.java +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * AuTool.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000,2001 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import javax.sound.sampled.AudioFormat; | ||
34 | import javax.sound.sampled.AudioFileFormat; | ||
35 | import javax.sound.sampled.AudioSystem; | ||
36 | |||
37 | |||
38 | /** Common constants and methods for handling au files. | ||
39 | * | ||
40 | * @author Florian Bomers | ||
41 | */ | ||
42 | |||
43 | public class AuTool { | ||
44 | |||
45 | public static final int AU_HEADER_MAGIC = 0x2e736e64; | ||
46 | public static final int AUDIO_UNKNOWN_SIZE = -1; | ||
47 | |||
48 | // length of header in bytes | ||
49 | public static final int DATA_OFFSET = 24; | ||
50 | |||
51 | public static final int SND_FORMAT_UNSPECIFIED = 0; | ||
52 | public static final int SND_FORMAT_MULAW_8 = 1; | ||
53 | public static final int SND_FORMAT_LINEAR_8 = 2; | ||
54 | public static final int SND_FORMAT_LINEAR_16 = 3; | ||
55 | public static final int SND_FORMAT_LINEAR_24 = 4; | ||
56 | public static final int SND_FORMAT_LINEAR_32 = 5; | ||
57 | public static final int SND_FORMAT_FLOAT = 6; | ||
58 | public static final int SND_FORMAT_DOUBLE = 7; | ||
59 | public static final int SND_FORMAT_ADPCM_G721 = 23; | ||
60 | public static final int SND_FORMAT_ADPCM_G722 = 24; | ||
61 | public static final int SND_FORMAT_ADPCM_G723_3 = 25; | ||
62 | public static final int SND_FORMAT_ADPCM_G723_5 = 26; | ||
63 | public static final int SND_FORMAT_ALAW_8 = 27; | ||
64 | |||
65 | public static int getFormatCode(AudioFormat format) { | ||
66 | AudioFormat.Encoding encoding = format.getEncoding(); | ||
67 | int nSampleSize = format.getSampleSizeInBits(); | ||
68 | // must be big endian for >8 bit formats | ||
69 | boolean bigEndian = format.isBigEndian(); | ||
70 | // $$fb 2000-08-16: check the frame size, too. | ||
71 | boolean frameSizeOK=( | ||
72 | format.getFrameSize()==AudioSystem.NOT_SPECIFIED | ||
73 | || format.getChannels()!=AudioSystem.NOT_SPECIFIED | ||
74 | || format.getFrameSize()==nSampleSize/8*format.getChannels()); | ||
75 | |||
76 | if (encoding.equals(AudioFormat.Encoding.ULAW) && nSampleSize == 8 && frameSizeOK) { | ||
77 | return SND_FORMAT_MULAW_8; | ||
78 | } else if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) && frameSizeOK) { | ||
79 | if (nSampleSize == 8) { | ||
80 | return SND_FORMAT_LINEAR_8; | ||
81 | } else if (nSampleSize == 16 && bigEndian) { | ||
82 | return SND_FORMAT_LINEAR_16; | ||
83 | } else if (nSampleSize == 24 && bigEndian) { | ||
84 | return SND_FORMAT_LINEAR_24; | ||
85 | } else if (nSampleSize == 32 && bigEndian) { | ||
86 | return SND_FORMAT_LINEAR_32; | ||
87 | } | ||
88 | } else if (encoding.equals(AudioFormat.Encoding.ALAW) && nSampleSize == 8 && frameSizeOK) { | ||
89 | return SND_FORMAT_ALAW_8; | ||
90 | } | ||
91 | return SND_FORMAT_UNSPECIFIED; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /*** AuTool.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/WaveAudioFileReader.java b/songdbj/org/tritonus/file/WaveAudioFileReader.java deleted file mode 100644 index 62d3f1a9ea..0000000000 --- a/songdbj/org/tritonus/file/WaveAudioFileReader.java +++ /dev/null | |||
@@ -1,300 +0,0 @@ | |||
1 | /* | ||
2 | * WaveAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999,2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 1999 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.DataInputStream; | ||
35 | import java.io.File; | ||
36 | import java.io.InputStream; | ||
37 | import java.io.IOException; | ||
38 | |||
39 | import javax.sound.sampled.AudioSystem; | ||
40 | import javax.sound.sampled.AudioFormat; | ||
41 | import javax.sound.sampled.AudioFileFormat; | ||
42 | import javax.sound.sampled.AudioInputStream; | ||
43 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
44 | import javax.sound.sampled.spi.AudioFileReader; | ||
45 | |||
46 | import org.tritonus.share.TDebug; | ||
47 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
48 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Class for reading wave files. | ||
53 | * | ||
54 | * @author Florian Bomers | ||
55 | * @author Matthias Pfisterer | ||
56 | */ | ||
57 | |||
58 | public class WaveAudioFileReader extends TAudioFileReader | ||
59 | { | ||
60 | private static final int READ_LIMIT = 1000; | ||
61 | |||
62 | |||
63 | |||
64 | public WaveAudioFileReader() | ||
65 | { | ||
66 | super(READ_LIMIT); | ||
67 | } | ||
68 | |||
69 | |||
70 | |||
71 | protected void advanceChunk(DataInputStream dis, long prevLength, long prevRead) | ||
72 | throws IOException { | ||
73 | if (prevLength>0) { | ||
74 | dis.skip(((prevLength+1) & 0xFFFFFFFE)-prevRead); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | |||
79 | protected long findChunk(DataInputStream dis, int key) | ||
80 | throws UnsupportedAudioFileException, IOException { | ||
81 | // $$fb 1999-12-18: we should take care that we don't exceed | ||
82 | // the mark of this stream. When we exceeded the mark and | ||
83 | // we notice that we don't support this wave file, | ||
84 | // other potential wave file readers have no chance. | ||
85 | int thisKey; | ||
86 | long chunkLength=0; | ||
87 | do { | ||
88 | advanceChunk(dis, chunkLength, 0); | ||
89 | try { | ||
90 | thisKey = dis.readInt(); | ||
91 | } catch (IOException e) | ||
92 | { | ||
93 | if (TDebug.TraceAllExceptions) | ||
94 | { | ||
95 | TDebug.out(e); | ||
96 | } | ||
97 | // $$fb: when we come here, we skipped past the end of the wave file | ||
98 | // without finding the chunk. | ||
99 | // IMHO, this is not an IOException, as there are incarnations | ||
100 | // of WAVE files which store data in different chunks. | ||
101 | // maybe we can find a nice description of the "required chunk" ? | ||
102 | throw new UnsupportedAudioFileException( | ||
103 | "unsupported WAVE file: required chunk not found."); | ||
104 | } | ||
105 | chunkLength = readLittleEndianInt(dis) & 0xFFFFFFFF; // unsigned | ||
106 | } | ||
107 | while (thisKey != key); | ||
108 | return chunkLength; | ||
109 | } | ||
110 | |||
111 | protected AudioFormat readFormatChunk(DataInputStream dis, | ||
112 | long chunkLength) throws UnsupportedAudioFileException, IOException { | ||
113 | String debugAdd=""; | ||
114 | |||
115 | int read=WaveTool.MIN_FMT_CHUNK_LENGTH; | ||
116 | |||
117 | if (chunkLength<WaveTool.MIN_FMT_CHUNK_LENGTH) { | ||
118 | throw new UnsupportedAudioFileException( | ||
119 | "corrupt WAVE file: format chunk is too small"); | ||
120 | } | ||
121 | |||
122 | short formatCode=readLittleEndianShort(dis); | ||
123 | short channelCount = readLittleEndianShort(dis); | ||
124 | if (channelCount <= 0) { | ||
125 | throw new UnsupportedAudioFileException( | ||
126 | "corrupt WAVE file: number of channels must be positive"); | ||
127 | } | ||
128 | |||
129 | int sampleRate = readLittleEndianInt(dis); | ||
130 | if (sampleRate <= 0) { | ||
131 | throw new UnsupportedAudioFileException( | ||
132 | "corrupt WAVE file: sample rate must be positive"); | ||
133 | } | ||
134 | |||
135 | int avgBytesPerSecond=readLittleEndianInt(dis); | ||
136 | int blockAlign=readLittleEndianShort(dis); | ||
137 | |||
138 | AudioFormat.Encoding encoding; | ||
139 | int sampleSizeInBits; | ||
140 | int frameSize=0; | ||
141 | float frameRate=(float) sampleRate; | ||
142 | |||
143 | int cbSize = 0; | ||
144 | switch (formatCode) { | ||
145 | case WaveTool.WAVE_FORMAT_PCM: | ||
146 | if (chunkLength<WaveTool.MIN_FMT_CHUNK_LENGTH+2) { | ||
147 | throw new UnsupportedAudioFileException( | ||
148 | "corrupt WAVE file: format chunk is too small"); | ||
149 | } | ||
150 | sampleSizeInBits = readLittleEndianShort(dis); | ||
151 | if (sampleSizeInBits <= 0) { | ||
152 | throw new UnsupportedAudioFileException( | ||
153 | "corrupt WAVE file: sample size must be positive"); | ||
154 | } | ||
155 | encoding = (sampleSizeInBits <= 8) ? | ||
156 | AudioFormat.Encoding.PCM_UNSIGNED : AudioFormat.Encoding.PCM_SIGNED; | ||
157 | if (TDebug.TraceAudioFileReader) { | ||
158 | debugAdd+=", wBitsPerSample="+sampleSizeInBits; | ||
159 | } | ||
160 | read+=2; | ||
161 | break; | ||
162 | case WaveTool.WAVE_FORMAT_ALAW: | ||
163 | sampleSizeInBits = 8; | ||
164 | encoding = AudioFormat.Encoding.ALAW; | ||
165 | break; | ||
166 | case WaveTool.WAVE_FORMAT_ULAW: | ||
167 | sampleSizeInBits = 8; | ||
168 | encoding = AudioFormat.Encoding.ULAW; | ||
169 | break; | ||
170 | case WaveTool.WAVE_FORMAT_GSM610: | ||
171 | if (chunkLength<WaveTool.MIN_FMT_CHUNK_LENGTH+6) { | ||
172 | throw new UnsupportedAudioFileException( | ||
173 | "corrupt WAVE file: extra GSM bytes are missing"); | ||
174 | } | ||
175 | sampleSizeInBits = readLittleEndianShort(dis); // sample Size (is 0 for GSM) | ||
176 | cbSize=readLittleEndianShort(dis); | ||
177 | if (cbSize < 2) { | ||
178 | throw new UnsupportedAudioFileException( | ||
179 | "corrupt WAVE file: extra GSM bytes are corrupt"); | ||
180 | } | ||
181 | int decodedSamplesPerBlock=readLittleEndianShort(dis) & 0xFFFF; // unsigned | ||
182 | if (TDebug.TraceAudioFileReader) { | ||
183 | debugAdd+=", wBitsPerSample="+sampleSizeInBits | ||
184 | +", cbSize="+cbSize | ||
185 | +", wSamplesPerBlock="+decodedSamplesPerBlock; | ||
186 | } | ||
187 | sampleSizeInBits = AudioSystem.NOT_SPECIFIED; | ||
188 | encoding = WaveTool.GSM0610; | ||
189 | frameSize=blockAlign; | ||
190 | frameRate=((float) sampleRate)/((float) decodedSamplesPerBlock); | ||
191 | read+=6; | ||
192 | break; | ||
193 | |||
194 | case WaveTool.WAVE_FORMAT_IMA_ADPCM: | ||
195 | if (chunkLength < WaveTool.MIN_FMT_CHUNK_LENGTH + 2) | ||
196 | { | ||
197 | throw new UnsupportedAudioFileException( | ||
198 | "corrupt WAVE file: extra GSM bytes are missing"); | ||
199 | } | ||
200 | sampleSizeInBits = readLittleEndianShort(dis); | ||
201 | cbSize = readLittleEndianShort(dis); | ||
202 | if (cbSize < 2) | ||
203 | { | ||
204 | throw new UnsupportedAudioFileException( | ||
205 | "corrupt WAVE file: extra IMA ADPCM bytes are corrupt"); | ||
206 | } | ||
207 | int samplesPerBlock = readLittleEndianShort(dis) & 0xFFFF; // unsigned | ||
208 | if (TDebug.TraceAudioFileReader) { | ||
209 | debugAdd+=", wBitsPerSample="+sampleSizeInBits | ||
210 | +", cbSize="+cbSize | ||
211 | +", wSamplesPerBlock=" + samplesPerBlock; | ||
212 | } | ||
213 | sampleSizeInBits = AudioSystem.NOT_SPECIFIED; | ||
214 | encoding = WaveTool.GSM0610; | ||
215 | frameSize = blockAlign; | ||
216 | frameRate = ((float) sampleRate)/((float) samplesPerBlock); | ||
217 | read += 6; | ||
218 | break; | ||
219 | |||
220 | default: | ||
221 | throw new UnsupportedAudioFileException( | ||
222 | "unsupported WAVE file: unknown format code "+formatCode); | ||
223 | } | ||
224 | // if frameSize isn't set, calculate it (the default) | ||
225 | if (frameSize==0) { | ||
226 | frameSize = calculateFrameSize(sampleSizeInBits, channelCount); | ||
227 | } | ||
228 | |||
229 | if (TDebug.TraceAudioFileReader) { | ||
230 | TDebug.out("WaveAudioFileReader.readFormatChunk():"); | ||
231 | TDebug.out(" read values: wFormatTag="+formatCode | ||
232 | +", nChannels="+channelCount | ||
233 | +", nSamplesPerSec="+sampleRate | ||
234 | +", nAvgBytesPerSec="+avgBytesPerSecond | ||
235 | +", nBlockAlign=="+blockAlign | ||
236 | +debugAdd); | ||
237 | TDebug.out(" constructed values: " | ||
238 | +"encoding="+encoding | ||
239 | +", sampleRate="+((float) sampleRate) | ||
240 | +", sampleSizeInBits="+sampleSizeInBits | ||
241 | +", channels="+channelCount | ||
242 | +", frameSize="+frameSize | ||
243 | +", frameRate="+frameRate); | ||
244 | } | ||
245 | |||
246 | // go to next chunk | ||
247 | advanceChunk(dis, chunkLength, read); | ||
248 | return new AudioFormat( | ||
249 | encoding, | ||
250 | (float) sampleRate, | ||
251 | sampleSizeInBits, | ||
252 | channelCount, | ||
253 | frameSize, | ||
254 | frameRate, | ||
255 | false); | ||
256 | } | ||
257 | |||
258 | |||
259 | |||
260 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileLengthInBytes) | ||
261 | throws UnsupportedAudioFileException, IOException { | ||
262 | DataInputStream dataInputStream = new DataInputStream(inputStream); | ||
263 | int magic = dataInputStream.readInt(); | ||
264 | if (magic != WaveTool.WAVE_RIFF_MAGIC) { | ||
265 | throw new UnsupportedAudioFileException( | ||
266 | "not a WAVE file: wrong header magic"); | ||
267 | } | ||
268 | long totalLength = readLittleEndianInt(dataInputStream) & 0xFFFFFFFF; // unsigned | ||
269 | magic = dataInputStream.readInt(); | ||
270 | if (magic != WaveTool.WAVE_WAVE_MAGIC) { | ||
271 | throw new UnsupportedAudioFileException("not a WAVE file: wrong header magic"); | ||
272 | } | ||
273 | // search for "fmt " chunk | ||
274 | long chunkLength = findChunk(dataInputStream, WaveTool.WAVE_FMT_MAGIC); | ||
275 | AudioFormat format = readFormatChunk(dataInputStream, chunkLength); | ||
276 | |||
277 | // search for "data" chunk | ||
278 | long dataChunkLength = findChunk(dataInputStream, WaveTool.WAVE_DATA_MAGIC); | ||
279 | |||
280 | long frameLength = dataChunkLength / format.getFrameSize(); | ||
281 | if (format.getEncoding().equals(WaveTool.GSM0610)) { | ||
282 | // TODO: should not be necessary | ||
283 | frameLength = dataChunkLength; | ||
284 | } | ||
285 | |||
286 | if (TDebug.TraceAudioFileReader) { | ||
287 | TDebug.out("WaveAudioFileReader.getAudioFileFormat(): total length: " | ||
288 | +totalLength+", frame length = "+frameLength); | ||
289 | } | ||
290 | return new TAudioFileFormat(AudioFileFormat.Type.WAVE, | ||
291 | format, | ||
292 | (int) frameLength, | ||
293 | (int) (totalLength + WaveTool.CHUNK_HEADER_SIZE)); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | |||
298 | |||
299 | /*** WaveAudioFileReader.java ***/ | ||
300 | |||
diff --git a/songdbj/org/tritonus/file/WaveAudioFileWriter.java b/songdbj/org/tritonus/file/WaveAudioFileWriter.java deleted file mode 100644 index d501b5b2b1..0000000000 --- a/songdbj/org/tritonus/file/WaveAudioFileWriter.java +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /* | ||
2 | * WaveAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999,2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import java.io.IOException; | ||
34 | import java.util.Arrays; | ||
35 | |||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.AudioFormat; | ||
38 | import javax.sound.sampled.AudioInputStream; | ||
39 | import javax.sound.sampled.AudioSystem; | ||
40 | |||
41 | import org.tritonus.share.TDebug; | ||
42 | import org.tritonus.share.sampled.file.AudioOutputStream; | ||
43 | import org.tritonus.share.sampled.file.TAudioFileWriter; | ||
44 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Class for writing Microsoft(tm) WAVE files | ||
49 | * | ||
50 | * @author Florian Bomers | ||
51 | */ | ||
52 | public class WaveAudioFileWriter | ||
53 | extends TAudioFileWriter { | ||
54 | |||
55 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
56 | { | ||
57 | AudioFileFormat.Type.WAVE | ||
58 | }; | ||
59 | |||
60 | private static final int ALL=AudioSystem.NOT_SPECIFIED; | ||
61 | |||
62 | // IMPORTANT: this array depends on the AudioFormat.match() algorithm which takes | ||
63 | // AudioSystem.NOT_SPECIFIED into account ! | ||
64 | private static final AudioFormat[] AUDIO_FORMATS = | ||
65 | { | ||
66 | // Encoding, SampleRate, sampleSizeInBits, channels, frameSize, frameRate, bigEndian | ||
67 | new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, ALL, 8, ALL, ALL, ALL, true), | ||
68 | new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, ALL, 8, ALL, ALL, ALL, false), | ||
69 | new AudioFormat(AudioFormat.Encoding.ULAW, ALL, 8, ALL, ALL, ALL, false), | ||
70 | new AudioFormat(AudioFormat.Encoding.ULAW, ALL, 8, ALL, ALL, ALL, true), | ||
71 | new AudioFormat(AudioFormat.Encoding.ALAW, ALL, 8, ALL, ALL, ALL, false), | ||
72 | new AudioFormat(AudioFormat.Encoding.ALAW, ALL, 8, ALL, ALL, ALL, true), | ||
73 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 16, ALL, ALL, ALL, false), | ||
74 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 24, ALL, ALL, ALL, false), | ||
75 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, ALL, 32, ALL, ALL, ALL, false), | ||
76 | new AudioFormat(WaveTool.GSM0610, ALL, ALL, ALL, ALL, ALL, false), | ||
77 | new AudioFormat(WaveTool.GSM0610, ALL, ALL, ALL, ALL, ALL, true), | ||
78 | }; | ||
79 | |||
80 | public WaveAudioFileWriter() { | ||
81 | super(Arrays.asList(FILE_TYPES), | ||
82 | Arrays.asList(AUDIO_FORMATS)); | ||
83 | } | ||
84 | |||
85 | // overwritten for quicker and more accurate check | ||
86 | protected boolean isAudioFormatSupportedImpl(AudioFormat format, | ||
87 | AudioFileFormat.Type fileType) { | ||
88 | return WaveTool.getFormatCode(format) != WaveTool.WAVE_FORMAT_UNSPECIFIED; | ||
89 | } | ||
90 | |||
91 | |||
92 | protected AudioOutputStream getAudioOutputStream(AudioFormat audioFormat, | ||
93 | long lLengthInBytes, | ||
94 | AudioFileFormat.Type fileType, | ||
95 | TDataOutputStream dataOutputStream) throws IOException { | ||
96 | return new WaveAudioOutputStream(audioFormat, | ||
97 | lLengthInBytes, | ||
98 | dataOutputStream); | ||
99 | } | ||
100 | |||
101 | } | ||
102 | |||
103 | /*** WaveAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/WaveAudioOutputStream.java b/songdbj/org/tritonus/file/WaveAudioOutputStream.java deleted file mode 100644 index 9054c3c4e1..0000000000 --- a/songdbj/org/tritonus/file/WaveAudioOutputStream.java +++ /dev/null | |||
@@ -1,201 +0,0 @@ | |||
1 | /* | ||
2 | * WaveAudioOutputStream.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import java.io.IOException; | ||
34 | |||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.AudioSystem; | ||
38 | |||
39 | import org.tritonus.share.TDebug; | ||
40 | import org.tritonus.share.sampled.file.TAudioOutputStream; | ||
41 | import org.tritonus.share.sampled.file.TDataOutputStream; | ||
42 | |||
43 | |||
44 | /** | ||
45 | * AudioOutputStream for Wave files. | ||
46 | * | ||
47 | * @author Florian Bomers | ||
48 | */ | ||
49 | |||
50 | public class WaveAudioOutputStream extends TAudioOutputStream { | ||
51 | |||
52 | // this constant is used for chunk lengths when the length is not known yet | ||
53 | private static final int LENGTH_NOT_KNOWN=-1; | ||
54 | private int formatCode; | ||
55 | |||
56 | public WaveAudioOutputStream(AudioFormat audioFormat, | ||
57 | long lLength, | ||
58 | TDataOutputStream dataOutputStream) { | ||
59 | super(audioFormat, | ||
60 | lLength, | ||
61 | dataOutputStream, | ||
62 | lLength == AudioSystem.NOT_SPECIFIED && dataOutputStream.supportsSeek()); | ||
63 | // wave cannot store more than 4GB | ||
64 | if (lLength != AudioSystem.NOT_SPECIFIED | ||
65 | && (lLength+WaveTool.DATA_OFFSET)>0xFFFFFFFFl) { | ||
66 | if (TDebug.TraceAudioOutputStream) { | ||
67 | TDebug.out("WaveAudioOutputStream: Length exceeds 4GB: " | ||
68 | +lLength+"=0x"+Long.toHexString(lLength) | ||
69 | +" with header="+(lLength+WaveTool.DATA_OFFSET) | ||
70 | +"=0x"+Long.toHexString(lLength+WaveTool.DATA_OFFSET)); | ||
71 | } | ||
72 | throw new IllegalArgumentException("Wave files cannot be larger than 4GB."); | ||
73 | } | ||
74 | formatCode = WaveTool.getFormatCode(getFormat()); | ||
75 | if (formatCode == WaveTool.WAVE_FORMAT_UNSPECIFIED) { | ||
76 | throw new IllegalArgumentException("Unknown encoding/format for this wave file."); | ||
77 | } | ||
78 | |||
79 | } | ||
80 | |||
81 | protected void writeHeader() | ||
82 | throws IOException { | ||
83 | if (TDebug.TraceAudioOutputStream) { | ||
84 | TDebug.out("WaveAudioOutputStream.writeHeader()"); | ||
85 | } | ||
86 | AudioFormat format = getFormat(); | ||
87 | long lLength = getLength(); | ||
88 | int formatChunkAdd=0; | ||
89 | if (formatCode==WaveTool.WAVE_FORMAT_GSM610) { | ||
90 | // space for extra fields | ||
91 | formatChunkAdd+=2; | ||
92 | } | ||
93 | int dataOffset=WaveTool.DATA_OFFSET+formatChunkAdd; | ||
94 | if (formatCode!=WaveTool.WAVE_FORMAT_PCM) { | ||
95 | // space for fact chunk | ||
96 | dataOffset+=4+WaveTool.CHUNK_HEADER_SIZE; | ||
97 | } | ||
98 | |||
99 | // if patching the header, and the length has not been known at first | ||
100 | // writing of the header, just truncate the size fields, don't throw an exception | ||
101 | if (lLength != AudioSystem.NOT_SPECIFIED | ||
102 | && lLength+dataOffset>0xFFFFFFFFl) { | ||
103 | lLength=0xFFFFFFFFl-dataOffset; | ||
104 | } | ||
105 | |||
106 | // chunks must be on word-boundaries | ||
107 | long lDataChunkSize=lLength+(lLength%2); | ||
108 | TDataOutputStream dos = getDataOutputStream(); | ||
109 | |||
110 | // write RIFF container chunk | ||
111 | dos.writeInt(WaveTool.WAVE_RIFF_MAGIC); | ||
112 | dos.writeLittleEndian32((int) ((lDataChunkSize+dataOffset-WaveTool.CHUNK_HEADER_SIZE) | ||
113 | & 0xFFFFFFFF)); | ||
114 | dos.writeInt(WaveTool.WAVE_WAVE_MAGIC); | ||
115 | |||
116 | // write fmt_ chunk | ||
117 | int formatChunkSize=WaveTool.FMT_CHUNK_SIZE+formatChunkAdd; | ||
118 | short sampleSizeInBits=(short) format.getSampleSizeInBits(); | ||
119 | int decodedSamplesPerBlock=1; | ||
120 | |||
121 | if (formatCode==WaveTool.WAVE_FORMAT_GSM610) { | ||
122 | if (format.getFrameSize()==33) { | ||
123 | decodedSamplesPerBlock=320; | ||
124 | } else if (format.getFrameSize()==65) { | ||
125 | decodedSamplesPerBlock=320; | ||
126 | } else { | ||
127 | // how to retrieve this value here ? | ||
128 | decodedSamplesPerBlock=(int) (format.getFrameSize()*(320.0f/65.0f)); | ||
129 | } | ||
130 | sampleSizeInBits=0; // MS standard | ||
131 | } | ||
132 | |||
133 | |||
134 | int avgBytesPerSec=((int) format.getSampleRate())/decodedSamplesPerBlock*format.getFrameSize(); | ||
135 | dos.writeInt(WaveTool.WAVE_FMT_MAGIC); | ||
136 | dos.writeLittleEndian32(formatChunkSize); | ||
137 | dos.writeLittleEndian16((short) formatCode); // wFormatTag | ||
138 | dos.writeLittleEndian16((short) format.getChannels()); // nChannels | ||
139 | dos.writeLittleEndian32((int) format.getSampleRate()); // nSamplesPerSec | ||
140 | dos.writeLittleEndian32(avgBytesPerSec); // nAvgBytesPerSec | ||
141 | dos.writeLittleEndian16((short) format.getFrameSize()); // nBlockalign | ||
142 | dos.writeLittleEndian16(sampleSizeInBits); // wBitsPerSample | ||
143 | dos.writeLittleEndian16((short) formatChunkAdd); // cbSize | ||
144 | |||
145 | if (formatCode==WaveTool.WAVE_FORMAT_GSM610) { | ||
146 | dos.writeLittleEndian16((short) decodedSamplesPerBlock); // wSamplesPerBlock | ||
147 | } | ||
148 | |||
149 | // write fact chunk | ||
150 | |||
151 | |||
152 | if (formatCode!=WaveTool.WAVE_FORMAT_PCM) { | ||
153 | // write "fact" chunk: number of samples | ||
154 | // todo: add this as an attribute or property | ||
155 | // in AudioOutputStream or AudioInputStream | ||
156 | long samples=0; | ||
157 | if (lLength!=AudioSystem.NOT_SPECIFIED) { | ||
158 | samples=lLength/format.getFrameSize()*decodedSamplesPerBlock; | ||
159 | } | ||
160 | // saturate sample count | ||
161 | if (samples>0xFFFFFFFFl) { | ||
162 | samples=(0xFFFFFFFFl/decodedSamplesPerBlock)*decodedSamplesPerBlock; | ||
163 | } | ||
164 | dos.writeInt(WaveTool.WAVE_FACT_MAGIC); | ||
165 | dos.writeLittleEndian32(4); | ||
166 | dos.writeLittleEndian32((int) (samples & 0xFFFFFFFF)); | ||
167 | } | ||
168 | |||
169 | // write header of data chunk | ||
170 | dos.writeInt(WaveTool.WAVE_DATA_MAGIC); | ||
171 | dos.writeLittleEndian32((lLength!=AudioSystem.NOT_SPECIFIED)?((int) lLength):LENGTH_NOT_KNOWN); | ||
172 | } | ||
173 | |||
174 | protected void patchHeader() | ||
175 | throws IOException { | ||
176 | TDataOutputStream tdos = getDataOutputStream(); | ||
177 | tdos.seek(0); | ||
178 | setLengthFromCalculatedLength(); | ||
179 | writeHeader(); | ||
180 | } | ||
181 | |||
182 | public void close() throws IOException { | ||
183 | long nBytesWritten=getCalculatedLength(); | ||
184 | |||
185 | if ((nBytesWritten % 2)==1) { | ||
186 | if (TDebug.TraceAudioOutputStream) { | ||
187 | TDebug.out("WaveOutputStream.close(): adding padding byte"); | ||
188 | } | ||
189 | // extra byte for to align on word boundaries | ||
190 | TDataOutputStream tdos = getDataOutputStream(); | ||
191 | tdos.writeByte(0); | ||
192 | // DON'T adjust calculated length ! | ||
193 | } | ||
194 | |||
195 | |||
196 | super.close(); | ||
197 | } | ||
198 | |||
199 | } | ||
200 | |||
201 | /*** WaveAudioOutputStream.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/WaveTool.java b/songdbj/org/tritonus/file/WaveTool.java deleted file mode 100644 index 3487557088..0000000000 --- a/songdbj/org/tritonus/file/WaveTool.java +++ /dev/null | |||
@@ -1,115 +0,0 @@ | |||
1 | /* | ||
2 | * WaveTool.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file; | ||
32 | |||
33 | import javax.sound.sampled.AudioSystem; | ||
34 | import javax.sound.sampled.AudioFormat; | ||
35 | import javax.sound.sampled.AudioFileFormat; | ||
36 | |||
37 | |||
38 | /** | ||
39 | * Common constants and methods for handling wave files. | ||
40 | * | ||
41 | * @author Florian Bomers | ||
42 | */ | ||
43 | |||
44 | public class WaveTool { | ||
45 | |||
46 | public static final int WAVE_RIFF_MAGIC = 0x52494646; // "RIFF" | ||
47 | public static final int WAVE_WAVE_MAGIC = 0x57415645; // "WAVE" | ||
48 | public static final int WAVE_FMT_MAGIC = 0x666D7420; // "fmt " | ||
49 | public static final int WAVE_DATA_MAGIC = 0x64617461; // "DATA" | ||
50 | public static final int WAVE_FACT_MAGIC = 0x66616374; // "fact" | ||
51 | |||
52 | public static final short WAVE_FORMAT_UNSPECIFIED = 0; | ||
53 | public static final short WAVE_FORMAT_PCM = 1; | ||
54 | public static final short WAVE_FORMAT_MS_ADPCM = 2; | ||
55 | public static final short WAVE_FORMAT_ALAW = 6; | ||
56 | public static final short WAVE_FORMAT_ULAW = 7; | ||
57 | public static final short WAVE_FORMAT_IMA_ADPCM = 17; // same as DVI_ADPCM | ||
58 | public static final short WAVE_FORMAT_G723_ADPCM = 20; | ||
59 | public static final short WAVE_FORMAT_GSM610 = 49; | ||
60 | public static final short WAVE_FORMAT_G721_ADPCM = 64; | ||
61 | public static final short WAVE_FORMAT_MPEG = 80; | ||
62 | |||
63 | public static final int MIN_FMT_CHUNK_LENGTH=14; | ||
64 | public static final int MIN_DATA_OFFSET=12+8+MIN_FMT_CHUNK_LENGTH+8; | ||
65 | public static final int MIN_FACT_CHUNK_LENGTH = 4; | ||
66 | |||
67 | // we always write the sample size in bits and the length of extra bytes. | ||
68 | // There are programs (CoolEdit) that rely on the | ||
69 | // additional entry for sample size in bits. | ||
70 | public static final int FMT_CHUNK_SIZE=18; | ||
71 | public static final int RIFF_CONTAINER_CHUNK_SIZE=12; | ||
72 | public static final int CHUNK_HEADER_SIZE=8; | ||
73 | public static final int DATA_OFFSET=RIFF_CONTAINER_CHUNK_SIZE | ||
74 | +CHUNK_HEADER_SIZE+FMT_CHUNK_SIZE+CHUNK_HEADER_SIZE; | ||
75 | |||
76 | public static AudioFormat.Encoding GSM0610 = new AudioFormat.Encoding("GSM0610"); | ||
77 | public static AudioFormat.Encoding IMA_ADPCM = new AudioFormat.Encoding("IMA_ADPCM"); | ||
78 | |||
79 | public static short getFormatCode(AudioFormat format) { | ||
80 | AudioFormat.Encoding encoding = format.getEncoding(); | ||
81 | int nSampleSize = format.getSampleSizeInBits(); | ||
82 | boolean littleEndian = !format.isBigEndian(); | ||
83 | boolean frameSizeOK=format.getFrameSize()==AudioSystem.NOT_SPECIFIED | ||
84 | || format.getChannels()!=AudioSystem.NOT_SPECIFIED | ||
85 | || format.getFrameSize()==nSampleSize/8*format.getChannels(); | ||
86 | |||
87 | if (nSampleSize==8 && frameSizeOK | ||
88 | && (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) | ||
89 | || encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED))) { | ||
90 | return WAVE_FORMAT_PCM; | ||
91 | } else if (nSampleSize>8 && frameSizeOK && littleEndian | ||
92 | && encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) { | ||
93 | return WAVE_FORMAT_PCM; | ||
94 | } else if (encoding.equals(AudioFormat.Encoding.ULAW) | ||
95 | && (nSampleSize==AudioSystem.NOT_SPECIFIED || nSampleSize == 8) | ||
96 | && frameSizeOK) { | ||
97 | return WAVE_FORMAT_ULAW; | ||
98 | } else if (encoding.equals(AudioFormat.Encoding.ALAW) | ||
99 | && (nSampleSize==AudioSystem.NOT_SPECIFIED || nSampleSize == 8) | ||
100 | && frameSizeOK) { | ||
101 | return WAVE_FORMAT_ALAW; | ||
102 | } else if (encoding.equals(new AudioFormat.Encoding("IMA_ADPCM")) | ||
103 | && nSampleSize == 4) | ||
104 | { | ||
105 | return WAVE_FORMAT_IMA_ADPCM; | ||
106 | } | ||
107 | else if (encoding.equals(GSM0610)) { | ||
108 | return WAVE_FORMAT_GSM610; | ||
109 | } | ||
110 | return WAVE_FORMAT_UNSPECIFIED; | ||
111 | } | ||
112 | |||
113 | } | ||
114 | |||
115 | /*** WaveTool.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/gsm/GSMAudioFileReader.java b/songdbj/org/tritonus/file/gsm/GSMAudioFileReader.java deleted file mode 100644 index 26859ddf24..0000000000 --- a/songdbj/org/tritonus/file/gsm/GSMAudioFileReader.java +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * GSMAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 1999 - 2004 by Matthias Pfisterer | ||
9 | * Copyright (c) 2001 by Florian Bomers <http://www.bomers.de> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |<--- this code is formatted to fit into 80 columns --->| | ||
28 | */ | ||
29 | |||
30 | package org.tritonus.sampled.file.gsm; | ||
31 | |||
32 | import java.io.InputStream; | ||
33 | import java.io.IOException; | ||
34 | import java.io.EOFException; | ||
35 | |||
36 | import java.util.HashMap; | ||
37 | import java.util.Map; | ||
38 | |||
39 | import javax.sound.sampled.AudioSystem; | ||
40 | import javax.sound.sampled.AudioFormat; | ||
41 | import javax.sound.sampled.AudioFileFormat; | ||
42 | import javax.sound.sampled.AudioInputStream; | ||
43 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
44 | import javax.sound.sampled.spi.AudioFileReader; | ||
45 | |||
46 | import org.tritonus.share.TDebug; | ||
47 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
48 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
49 | |||
50 | |||
51 | |||
52 | /** AudioFileReader class for GSM 06.10 data. | ||
53 | @author Matthias Pfisterer | ||
54 | */ | ||
55 | public class GSMAudioFileReader | ||
56 | extends TAudioFileReader | ||
57 | { | ||
58 | private static final int GSM_MAGIC = 0xD0; | ||
59 | private static final int GSM_MAGIC_MASK = 0xF0; | ||
60 | |||
61 | private static final int MARK_LIMIT = 1; | ||
62 | |||
63 | |||
64 | |||
65 | public GSMAudioFileReader() | ||
66 | { | ||
67 | super(MARK_LIMIT, true); | ||
68 | } | ||
69 | |||
70 | |||
71 | |||
72 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes) | ||
73 | throws UnsupportedAudioFileException, IOException | ||
74 | { | ||
75 | if (TDebug.TraceAudioFileReader) { TDebug.out("GSMAudioFileReader.getAudioFileFormat(): begin"); } | ||
76 | int b0 = inputStream.read(); | ||
77 | if (b0 < 0) | ||
78 | { | ||
79 | throw new EOFException(); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Check for magic number. | ||
84 | */ | ||
85 | if ((b0 & GSM_MAGIC_MASK) != GSM_MAGIC) | ||
86 | { | ||
87 | throw new UnsupportedAudioFileException("not a GSM stream: wrong magic number"); | ||
88 | } | ||
89 | |||
90 | |||
91 | /* | ||
92 | If the file size is known, we derive the number of frames | ||
93 | ('frame size') from it. | ||
94 | If the values don't fit into integers, we leave them at | ||
95 | NOT_SPECIFIED. 'Unknown' is considered less incorrect than | ||
96 | a wrong value. | ||
97 | */ | ||
98 | // [fb] not specifying it causes Sun's Wave file writer to write rubbish | ||
99 | int nByteSize = AudioSystem.NOT_SPECIFIED; | ||
100 | int nFrameSize = AudioSystem.NOT_SPECIFIED; | ||
101 | Map<String, Object> properties = new HashMap<String, Object>(); | ||
102 | if (lFileSizeInBytes != AudioSystem.NOT_SPECIFIED) | ||
103 | { | ||
104 | // the number of GSM frames | ||
105 | long lFrameSize = lFileSizeInBytes / 33; | ||
106 | // duration in microseconds | ||
107 | long lDuration = lFrameSize * 20000; | ||
108 | properties.put("duration", lDuration); | ||
109 | if (lFileSizeInBytes <= Integer.MAX_VALUE) | ||
110 | { | ||
111 | nByteSize = (int) lFileSizeInBytes; | ||
112 | nFrameSize = (int) (lFileSizeInBytes / 33); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | Map<String, Object> afProperties = new HashMap<String, Object>(); | ||
117 | afProperties.put("bitrate", 13200L); | ||
118 | AudioFormat format = new AudioFormat( | ||
119 | new AudioFormat.Encoding("GSM0610"), | ||
120 | 8000.0F, | ||
121 | AudioSystem.NOT_SPECIFIED /* ??? [sample size in bits] */, | ||
122 | 1, | ||
123 | 33, | ||
124 | 50.0F, | ||
125 | true, // this value is chosen arbitrarily | ||
126 | afProperties); | ||
127 | AudioFileFormat audioFileFormat = | ||
128 | new TAudioFileFormat( | ||
129 | new AudioFileFormat.Type("GSM","gsm"), | ||
130 | format, | ||
131 | nFrameSize, | ||
132 | nByteSize, | ||
133 | properties); | ||
134 | if (TDebug.TraceAudioFileReader) { TDebug.out("GSMAudioFileReader.getAudioFileFormat(): end"); } | ||
135 | return audioFileFormat; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | |||
140 | |||
141 | /*** GSMAudioFileReader.java ***/ | ||
142 | |||
diff --git a/songdbj/org/tritonus/file/gsm/GSMAudioFileWriter.java b/songdbj/org/tritonus/file/gsm/GSMAudioFileWriter.java deleted file mode 100644 index eb3d1f3f16..0000000000 --- a/songdbj/org/tritonus/file/gsm/GSMAudioFileWriter.java +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * GSMAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 2000 by Matthias Pfisterer | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |<--- this code is formatted to fit into 80 columns --->| | ||
30 | */ | ||
31 | |||
32 | package org.tritonus.sampled.file.gsm; | ||
33 | |||
34 | import java.util.Arrays; | ||
35 | |||
36 | import javax.sound.sampled.AudioFileFormat; | ||
37 | import javax.sound.sampled.AudioFormat; | ||
38 | import javax.sound.sampled.AudioSystem; | ||
39 | |||
40 | import org.tritonus.share.TDebug; | ||
41 | import org.tritonus.share.sampled.file.THeaderlessAudioFileWriter; | ||
42 | |||
43 | |||
44 | |||
45 | /** Class for writing GSM streams | ||
46 | * | ||
47 | * @author Florian Bomers | ||
48 | * @author Matthias Pfisterer | ||
49 | */ | ||
50 | public class GSMAudioFileWriter | ||
51 | extends THeaderlessAudioFileWriter | ||
52 | { | ||
53 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
54 | { | ||
55 | new AudioFileFormat.Type("GSM", "gsm") | ||
56 | }; | ||
57 | |||
58 | private static final AudioFormat[] AUDIO_FORMATS = | ||
59 | { | ||
60 | new AudioFormat(new AudioFormat.Encoding("GSM0610"), 8000.0F, ALL, 1, 33, 50.0F, false), | ||
61 | new AudioFormat(new AudioFormat.Encoding("GSM0610"), 8000.0F, ALL, 1, 33, 50.0F, true), | ||
62 | }; | ||
63 | |||
64 | |||
65 | |||
66 | public GSMAudioFileWriter() | ||
67 | { | ||
68 | super(Arrays.asList(FILE_TYPES), | ||
69 | Arrays.asList(AUDIO_FORMATS)); | ||
70 | if (TDebug.TraceAudioFileWriter) { TDebug.out("GSMAudioFileWriter.<init>(): begin"); } | ||
71 | if (TDebug.TraceAudioFileWriter) { TDebug.out("GSMAudioFileWriter.<init>(): end"); } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | |||
76 | |||
77 | /*** GSMAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/gsm/package.html b/songdbj/org/tritonus/file/gsm/package.html deleted file mode 100644 index 763851dda0..0000000000 --- a/songdbj/org/tritonus/file/gsm/package.html +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>GSM 06.10 audio file reader and writer. | ||
8 | The classes provided here .</p> | ||
9 | </body> | ||
10 | </html> | ||
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 | |||
diff --git a/songdbj/org/tritonus/file/jorbis/package.html b/songdbj/org/tritonus/file/jorbis/package.html deleted file mode 100644 index e5b5599d8c..0000000000 --- a/songdbj/org/tritonus/file/jorbis/package.html +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>Ogg vorbis audio file reader based on the jorbis library. | ||
8 | The classes provided here .</p> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/songdbj/org/tritonus/file/mpeg/MpegAudioFileWriter.java b/songdbj/org/tritonus/file/mpeg/MpegAudioFileWriter.java deleted file mode 100644 index d958fecf0d..0000000000 --- a/songdbj/org/tritonus/file/mpeg/MpegAudioFileWriter.java +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * MpegAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | |<--- this code is formatted to fit into 80 columns --->| | ||
29 | */ | ||
30 | |||
31 | package org.tritonus.sampled.file.mpeg; | ||
32 | |||
33 | import java.util.Arrays; | ||
34 | |||
35 | import javax.sound.sampled.AudioFileFormat; | ||
36 | import javax.sound.sampled.AudioFormat; | ||
37 | |||
38 | import org.tritonus.share.TDebug; | ||
39 | import org.tritonus.share.sampled.file.THeaderlessAudioFileWriter; | ||
40 | |||
41 | |||
42 | |||
43 | /** Class for writing mpeg files | ||
44 | * | ||
45 | * @author Florian Bomers | ||
46 | */ | ||
47 | public class MpegAudioFileWriter extends THeaderlessAudioFileWriter { | ||
48 | |||
49 | private static final AudioFileFormat.Type[] FILE_TYPES = { | ||
50 | //new AudioFileFormat.Type("MPEG", "mpeg"), | ||
51 | // workaround for the fixed extension problem in AudioFileFormat.Type | ||
52 | // see org.tritonus.share.sampled.AudioFileTypes.java | ||
53 | new AudioFileFormat.Type("MP3", "mp3") | ||
54 | }; | ||
55 | |||
56 | public static AudioFormat.Encoding MPEG1L3=new AudioFormat.Encoding("MPEG1L3"); | ||
57 | |||
58 | private static final AudioFormat[] AUDIO_FORMATS = { | ||
59 | new AudioFormat(MPEG1L3, ALL, ALL, 1, ALL, ALL, false), | ||
60 | new AudioFormat(MPEG1L3, ALL, ALL, 1, ALL, ALL, true), | ||
61 | new AudioFormat(MPEG1L3, ALL, ALL, 2, ALL, ALL, false), | ||
62 | new AudioFormat(MPEG1L3, ALL, ALL, 2, ALL, ALL, true), | ||
63 | }; | ||
64 | |||
65 | public MpegAudioFileWriter() | ||
66 | { | ||
67 | super(Arrays.asList(FILE_TYPES), | ||
68 | Arrays.asList(AUDIO_FORMATS)); | ||
69 | if (TDebug.TraceAudioFileWriter) { TDebug.out("MpegAudioFileWriter.<init>(): begin"); } | ||
70 | if (TDebug.TraceAudioFileWriter) { TDebug.out("MpegAudioFileWriter.<init>(): end"); } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | |||
75 | /*** MpegAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/mpeg/package.html b/songdbj/org/tritonus/file/mpeg/package.html deleted file mode 100644 index f24ded00ec..0000000000 --- a/songdbj/org/tritonus/file/mpeg/package.html +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>Mp3 audio file reader and writer. | ||
8 | The classes provided here .</p> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/songdbj/org/tritonus/file/package.html b/songdbj/org/tritonus/file/package.html deleted file mode 100644 index a3ba1632a8..0000000000 --- a/songdbj/org/tritonus/file/package.html +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>Standard audio file readers and writers (.aiff, .au, .wav). | ||
8 | The classes provided here .</p> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileReader.java b/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileReader.java deleted file mode 100644 index a882f11c3a..0000000000 --- a/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileReader.java +++ /dev/null | |||
@@ -1,302 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileReader.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2001 - 2004 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.pvorbis; | ||
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 org.tritonus.lowlevel.pogg.Buffer; | ||
44 | import org.tritonus.lowlevel.pogg.Page; | ||
45 | import org.tritonus.lowlevel.pogg.Packet; | ||
46 | import org.tritonus.lowlevel.pogg.SyncState; | ||
47 | import org.tritonus.lowlevel.pogg.StreamState; | ||
48 | |||
49 | |||
50 | |||
51 | /** | ||
52 | * @author Matthias Pfisterer | ||
53 | */ | ||
54 | public class VorbisAudioFileReader | ||
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 VorbisAudioFileReader() | ||
63 | { | ||
64 | super(MARK_LIMIT, true); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, | ||
70 | long lFileSizeInBytes) | ||
71 | throws UnsupportedAudioFileException, IOException | ||
72 | { | ||
73 | if (TDebug.TraceAudioFileReader) { TDebug.out(">VorbisAudioFileReader.getAudioFileFormat(): begin"); } | ||
74 | SyncState oggSyncState = new SyncState(); | ||
75 | StreamState oggStreamState = new StreamState(); | ||
76 | Page oggPage = new Page(); | ||
77 | Packet oggPacket = new Packet(); | ||
78 | |||
79 | int bytes = 0; | ||
80 | |||
81 | // Decode setup | ||
82 | |||
83 | oggSyncState.init(); // Now we can read pages | ||
84 | |||
85 | // grab some data at the head of the stream. We want the first page | ||
86 | // (which is guaranteed to be small and only contain the Vorbis | ||
87 | // stream initial header) We need the first page to get the stream | ||
88 | // serialno. | ||
89 | |||
90 | // submit a 4k block to libvorbis' Ogg layer | ||
91 | byte[] abBuffer = new byte[INITAL_READ_LENGTH]; | ||
92 | bytes = inputStream.read(abBuffer); | ||
93 | if (TDebug.TraceAudioFileReader) { TDebug.out("read bytes from input stream: " + bytes); } | ||
94 | int nResult = oggSyncState.write(abBuffer, bytes); | ||
95 | if (TDebug.TraceAudioFileReader) { TDebug.out("SyncState.write() returned " + nResult); } | ||
96 | |||
97 | // Get the first page. | ||
98 | if (oggSyncState.pageOut(oggPage) != 1) | ||
99 | { | ||
100 | // have we simply run out of data? If so, we're done. | ||
101 | if (bytes < INITAL_READ_LENGTH) | ||
102 | { | ||
103 | if (TDebug.TraceAudioFileReader) { TDebug.out("stream ended prematurely"); } | ||
104 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
105 | // IDEA: throw EOFException? | ||
106 | oggSyncState.free(); | ||
107 | oggStreamState.free(); | ||
108 | oggPage.free(); | ||
109 | oggPacket.free(); | ||
110 | throw new UnsupportedAudioFileException("not a Vorbis stream: ended prematurely"); | ||
111 | } | ||
112 | if (TDebug.TraceAudioFileReader) { TDebug.out("not in Ogg bitstream format"); } | ||
113 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
114 | oggSyncState.free(); | ||
115 | oggStreamState.free(); | ||
116 | oggPage.free(); | ||
117 | oggPacket.free(); | ||
118 | throw new UnsupportedAudioFileException("not a Vorbis stream: not in Ogg bitstream format"); | ||
119 | } | ||
120 | |||
121 | // Get the serial number and set up the rest of decode. | ||
122 | // serialno first; use it to set up a logical stream | ||
123 | int nSerialNo = oggPage.getSerialNo(); | ||
124 | if (TDebug.TraceAudioFileReader) TDebug.out("serial no.: " + nSerialNo); | ||
125 | oggStreamState.init(nSerialNo); | ||
126 | |||
127 | // extract the initial header from the first page and verify that the | ||
128 | // Ogg bitstream is in fact Vorbis data | ||
129 | |||
130 | // I handle the initial header first instead of just having the code | ||
131 | // read all three Vorbis headers at once because reading the initial | ||
132 | // header is an easy way to identify a Vorbis bitstream and it's | ||
133 | // useful to see that functionality seperated out. | ||
134 | |||
135 | if (oggStreamState.pageIn(oggPage) < 0) | ||
136 | { | ||
137 | if (TDebug.TraceAudioFileReader) { TDebug.out("can't read first page of Ogg bitstream data"); } | ||
138 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
139 | // error; stream version mismatch perhaps | ||
140 | oggSyncState.free(); | ||
141 | oggStreamState.free(); | ||
142 | oggPage.free(); | ||
143 | oggPacket.free(); | ||
144 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read first page of Ogg bitstream data"); | ||
145 | } | ||
146 | |||
147 | if (oggStreamState.packetOut(oggPacket) != 1) | ||
148 | { | ||
149 | if (TDebug.TraceAudioFileReader) { TDebug.out("can't read initial header packet"); } | ||
150 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
151 | // no page? must not be vorbis | ||
152 | oggSyncState.free(); | ||
153 | oggStreamState.free(); | ||
154 | oggPage.free(); | ||
155 | oggPacket.free(); | ||
156 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read initial header packet"); | ||
157 | } | ||
158 | |||
159 | byte[] abData = oggPacket.getData(); | ||
160 | if (TDebug.TraceAudioFileReader) | ||
161 | { | ||
162 | String strData = ""; | ||
163 | for (int i = 0; i < abData.length; i++) | ||
164 | { | ||
165 | strData += " " + abData[i]; | ||
166 | } | ||
167 | TDebug.out("packet data: " + strData); | ||
168 | } | ||
169 | |||
170 | int nPacketType = abData[0]; | ||
171 | if (TDebug.TraceAudioFileReader) { TDebug.out("packet type: " + nPacketType); } | ||
172 | if (nPacketType != 1) | ||
173 | { | ||
174 | if (TDebug.TraceAudioFileReader) { TDebug.out("first packet is not the identification header"); } | ||
175 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
176 | oggSyncState.free(); | ||
177 | oggStreamState.free(); | ||
178 | oggPage.free(); | ||
179 | oggPacket.free(); | ||
180 | throw new UnsupportedAudioFileException("not a Vorbis stream: first packet is not the identification header"); | ||
181 | } | ||
182 | if(abData[1] != 'v' || | ||
183 | abData[2] != 'o' || | ||
184 | abData[3] != 'r' || | ||
185 | abData[4] != 'b' || | ||
186 | abData[5] != 'i' || | ||
187 | abData[6] != 's') | ||
188 | { | ||
189 | if (TDebug.TraceAudioFileReader) { TDebug.out("not a vorbis header packet"); } | ||
190 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
191 | oggSyncState.free(); | ||
192 | oggStreamState.free(); | ||
193 | oggPage.free(); | ||
194 | oggPacket.free(); | ||
195 | throw new UnsupportedAudioFileException("not a Vorbis stream: not a vorbis header packet"); | ||
196 | } | ||
197 | if (! oggPacket.isBos()) | ||
198 | { | ||
199 | if (TDebug.TraceAudioFileReader) { TDebug.out("initial packet not marked as beginning of stream"); } | ||
200 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
201 | oggSyncState.free(); | ||
202 | oggStreamState.free(); | ||
203 | oggPage.free(); | ||
204 | oggPacket.free(); | ||
205 | throw new UnsupportedAudioFileException("not a Vorbis stream: initial packet not marked as beginning of stream"); | ||
206 | } | ||
207 | int nVersion = (abData[7] & 0xFF) + 256 * (abData[8] & 0xFF) + 65536 * (abData[9] & 0xFF) + 16777216 * (abData[10] & 0xFF); | ||
208 | if (TDebug.TraceAudioFileReader) { TDebug.out("version: " + nVersion); } | ||
209 | if (nVersion != 0) | ||
210 | { | ||
211 | if (TDebug.TraceAudioFileReader) { TDebug.out("wrong vorbis version"); } | ||
212 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
213 | oggSyncState.free(); | ||
214 | oggStreamState.free(); | ||
215 | oggPage.free(); | ||
216 | oggPacket.free(); | ||
217 | throw new UnsupportedAudioFileException("not a Vorbis stream: wrong vorbis version"); | ||
218 | } | ||
219 | int nChannels = (abData[11] & 0xFF); | ||
220 | float fSampleRate = (abData[12] & 0xFF) + 256 * (abData[13] & 0xFF) + 65536 * (abData[14] & 0xFF) + 16777216 * (abData[15] & 0xFF); | ||
221 | if (TDebug.TraceAudioFileReader) { TDebug.out("channels: " + nChannels); } | ||
222 | if (TDebug.TraceAudioFileReader) { TDebug.out("rate: " + fSampleRate); } | ||
223 | |||
224 | // These are only used for error checking. | ||
225 | int bitrate_upper = abData[16] + 256 * abData[17] + 65536 * abData[18] + 16777216 * abData[19]; | ||
226 | int bitrate_nominal = abData[20] + 256 * abData[21] + 65536 * abData[22] + 16777216 * abData[23]; | ||
227 | int bitrate_lower = abData[24] + 256 * abData[25] + 65536 * abData[26] + 16777216 * abData[27]; | ||
228 | |||
229 | int[] blocksizes = new int[2]; | ||
230 | blocksizes[0] = 1 << (abData[28] & 0xF); | ||
231 | blocksizes[1] = 1 << ((abData[28] >>> 4) & 0xF); | ||
232 | if (TDebug.TraceAudioFileReader) { TDebug.out("blocksizes[0]: " + blocksizes[0]); } | ||
233 | if (TDebug.TraceAudioFileReader) { TDebug.out("blocksizes[1]: " + blocksizes[1]); } | ||
234 | |||
235 | if (fSampleRate < 1.0F || | ||
236 | nChannels < 1 || | ||
237 | blocksizes[0] < 8|| | ||
238 | blocksizes[1] < blocksizes[0] || | ||
239 | (abData[29] & 0x1) != 1) | ||
240 | { | ||
241 | if (TDebug.TraceAudioFileReader) { TDebug.out("illegal values in initial header"); } | ||
242 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
243 | oggSyncState.free(); | ||
244 | oggStreamState.free(); | ||
245 | oggPage.free(); | ||
246 | oggPacket.free(); | ||
247 | throw new UnsupportedAudioFileException("not a Vorbis stream: illegal values in initial header"); | ||
248 | } | ||
249 | |||
250 | oggSyncState.free(); | ||
251 | oggStreamState.free(); | ||
252 | oggPage.free(); | ||
253 | oggPacket.free(); | ||
254 | |||
255 | /* | ||
256 | If the file size is known, we derive the number of frames | ||
257 | ('frame size') from it. | ||
258 | If the values don't fit into integers, we leave them at | ||
259 | NOT_SPECIFIED. 'Unknown' is considered less incorrect than | ||
260 | a wrong value. | ||
261 | */ | ||
262 | // [fb] not specifying it causes Sun's Wave file writer to write rubbish | ||
263 | int nByteSize = AudioSystem.NOT_SPECIFIED; | ||
264 | if (lFileSizeInBytes != AudioSystem.NOT_SPECIFIED | ||
265 | && lFileSizeInBytes <= Integer.MAX_VALUE) | ||
266 | { | ||
267 | nByteSize = (int) lFileSizeInBytes; | ||
268 | } | ||
269 | int nFrameSize = AudioSystem.NOT_SPECIFIED; | ||
270 | /* Can we calculate a useful size? | ||
271 | Peeking into ogginfo gives the insight that the only | ||
272 | way seems to be reading through the file. This is | ||
273 | something we do not want, at least not by default. | ||
274 | */ | ||
275 | // nFrameSize = (int) (lFileSizeInBytes / ...; | ||
276 | |||
277 | AudioFormat format = new AudioFormat( | ||
278 | new AudioFormat.Encoding("VORBIS"), | ||
279 | fSampleRate, | ||
280 | AudioSystem.NOT_SPECIFIED, | ||
281 | nChannels, | ||
282 | AudioSystem.NOT_SPECIFIED, | ||
283 | AudioSystem.NOT_SPECIFIED, | ||
284 | true); // this value is chosen arbitrarily | ||
285 | if (TDebug.TraceAudioFileReader) { TDebug.out("AudioFormat: " + format); } | ||
286 | AudioFileFormat.Type type = new AudioFileFormat.Type("Ogg","ogg"); | ||
287 | AudioFileFormat audioFileFormat = | ||
288 | new TAudioFileFormat( | ||
289 | type, | ||
290 | format, | ||
291 | nFrameSize, | ||
292 | nByteSize); | ||
293 | if (TDebug.TraceAudioFileReader) { TDebug.out("AudioFileFormat: " + audioFileFormat); } | ||
294 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): end"); } | ||
295 | return audioFileFormat; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | |||
300 | |||
301 | /*** VorbisAudioFileReader.java ***/ | ||
302 | |||
diff --git a/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileWriter.java b/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileWriter.java deleted file mode 100644 index 5fc9c0663d..0000000000 --- a/songdbj/org/tritonus/file/pvorbis/VorbisAudioFileWriter.java +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 2000 -2004 by Matthias Pfisterer | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |<--- this code is formatted to fit into 80 columns --->| | ||
28 | */ | ||
29 | |||
30 | package org.tritonus.sampled.file.pvorbis; | ||
31 | |||
32 | import java.util.Arrays; | ||
33 | |||
34 | import javax.sound.sampled.AudioFileFormat; | ||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioSystem; | ||
37 | |||
38 | import org.tritonus.share.TDebug; | ||
39 | import org.tritonus.share.sampled.file.THeaderlessAudioFileWriter; | ||
40 | |||
41 | |||
42 | |||
43 | /** Class for writing Vorbis streams | ||
44 | * | ||
45 | * @author Florian Bomers | ||
46 | * @author Matthias Pfisterer | ||
47 | */ | ||
48 | public class VorbisAudioFileWriter | ||
49 | extends THeaderlessAudioFileWriter | ||
50 | { | ||
51 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
52 | { | ||
53 | new AudioFileFormat.Type("Vorbis", "ogg") | ||
54 | }; | ||
55 | |||
56 | private static final AudioFormat[] AUDIO_FORMATS = | ||
57 | { | ||
58 | new AudioFormat(new AudioFormat.Encoding("VORBIS"), ALL, ALL, ALL, ALL, ALL, false), | ||
59 | new AudioFormat(new AudioFormat.Encoding("VORBIS"), ALL, ALL, ALL, ALL, ALL, true), | ||
60 | }; | ||
61 | |||
62 | |||
63 | |||
64 | public VorbisAudioFileWriter() | ||
65 | { | ||
66 | super(Arrays.asList(FILE_TYPES), | ||
67 | Arrays.asList(AUDIO_FORMATS)); | ||
68 | if (TDebug.TraceAudioFileWriter) { TDebug.out("VorbisAudioFileWriter.<init>(): begin"); } | ||
69 | if (TDebug.TraceAudioFileWriter) { TDebug.out("VorbisAudioFileWriter.<init>(): end"); } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
75 | /*** VorbisAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/pvorbis/package.html b/songdbj/org/tritonus/file/pvorbis/package.html deleted file mode 100644 index a5238aaca0..0000000000 --- a/songdbj/org/tritonus/file/pvorbis/package.html +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>Ogg vorbis audio file reader and writer based on the pure java libraries. | ||
8 | The classes provided here .</p> | ||
9 | |||
10 | @see org.tritonus.lowlevel.ogg | ||
11 | </body> | ||
12 | </html> | ||
diff --git a/songdbj/org/tritonus/file/vorbis/VorbisAudioFileReader.java b/songdbj/org/tritonus/file/vorbis/VorbisAudioFileReader.java deleted file mode 100644 index f8b34d5411..0000000000 --- a/songdbj/org/tritonus/file/vorbis/VorbisAudioFileReader.java +++ /dev/null | |||
@@ -1,302 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileReader.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.vorbis; | ||
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 org.tritonus.lowlevel.ogg.Buffer; | ||
44 | import org.tritonus.lowlevel.ogg.Page; | ||
45 | import org.tritonus.lowlevel.ogg.Packet; | ||
46 | import org.tritonus.lowlevel.ogg.SyncState; | ||
47 | import org.tritonus.lowlevel.ogg.StreamState; | ||
48 | |||
49 | |||
50 | |||
51 | /** | ||
52 | * @author Matthias Pfisterer | ||
53 | */ | ||
54 | public class VorbisAudioFileReader | ||
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 VorbisAudioFileReader() | ||
63 | { | ||
64 | super(MARK_LIMIT, true); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | protected AudioFileFormat getAudioFileFormat(InputStream inputStream, | ||
70 | long lFileSizeInBytes) | ||
71 | throws UnsupportedAudioFileException, IOException | ||
72 | { | ||
73 | if (TDebug.TraceAudioFileReader) { TDebug.out(">VorbisAudioFileReader.getAudioFileFormat(): begin"); } | ||
74 | SyncState oggSyncState = new SyncState(); | ||
75 | StreamState oggStreamState = new StreamState(); | ||
76 | Page oggPage = new Page(); | ||
77 | Packet oggPacket = new Packet(); | ||
78 | |||
79 | int bytes = 0; | ||
80 | |||
81 | // Decode setup | ||
82 | |||
83 | oggSyncState.init(); // Now we can read pages | ||
84 | |||
85 | // grab some data at the head of the stream. We want the first page | ||
86 | // (which is guaranteed to be small and only contain the Vorbis | ||
87 | // stream initial header) We need the first page to get the stream | ||
88 | // serialno. | ||
89 | |||
90 | // submit a 4k block to libvorbis' Ogg layer | ||
91 | byte[] abBuffer = new byte[INITAL_READ_LENGTH]; | ||
92 | bytes = inputStream.read(abBuffer); | ||
93 | if (TDebug.TraceAudioFileReader) { TDebug.out("read bytes from input stream: " + bytes); } | ||
94 | int nResult = oggSyncState.write(abBuffer, bytes); | ||
95 | if (TDebug.TraceAudioFileReader) { TDebug.out("SyncState.write() returned " + nResult); } | ||
96 | |||
97 | // Get the first page. | ||
98 | if (oggSyncState.pageOut(oggPage) != 1) | ||
99 | { | ||
100 | // have we simply run out of data? If so, we're done. | ||
101 | if (bytes < INITAL_READ_LENGTH) | ||
102 | { | ||
103 | if (TDebug.TraceAudioFileReader) { TDebug.out("stream ended prematurely"); } | ||
104 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
105 | // IDEA: throw EOFException? | ||
106 | oggSyncState.free(); | ||
107 | oggStreamState.free(); | ||
108 | oggPage.free(); | ||
109 | oggPacket.free(); | ||
110 | throw new UnsupportedAudioFileException("not a Vorbis stream: ended prematurely"); | ||
111 | } | ||
112 | if (TDebug.TraceAudioFileReader) { TDebug.out("not in Ogg bitstream format"); } | ||
113 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
114 | oggSyncState.free(); | ||
115 | oggStreamState.free(); | ||
116 | oggPage.free(); | ||
117 | oggPacket.free(); | ||
118 | throw new UnsupportedAudioFileException("not a Vorbis stream: not in Ogg bitstream format"); | ||
119 | } | ||
120 | |||
121 | // Get the serial number and set up the rest of decode. | ||
122 | // serialno first; use it to set up a logical stream | ||
123 | int nSerialNo = oggPage.getSerialNo(); | ||
124 | TDebug.out("serial no.: " + nSerialNo); | ||
125 | oggStreamState.init(nSerialNo); | ||
126 | |||
127 | // extract the initial header from the first page and verify that the | ||
128 | // Ogg bitstream is in fact Vorbis data | ||
129 | |||
130 | // I handle the initial header first instead of just having the code | ||
131 | // read all three Vorbis headers at once because reading the initial | ||
132 | // header is an easy way to identify a Vorbis bitstream and it's | ||
133 | // useful to see that functionality seperated out. | ||
134 | |||
135 | if (oggStreamState.pageIn(oggPage) < 0) | ||
136 | { | ||
137 | if (TDebug.TraceAudioFileReader) { TDebug.out("can't read first page of Ogg bitstream data"); } | ||
138 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
139 | // error; stream version mismatch perhaps | ||
140 | oggSyncState.free(); | ||
141 | oggStreamState.free(); | ||
142 | oggPage.free(); | ||
143 | oggPacket.free(); | ||
144 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read first page of Ogg bitstream data"); | ||
145 | } | ||
146 | |||
147 | if (oggStreamState.packetOut(oggPacket) != 1) | ||
148 | { | ||
149 | if (TDebug.TraceAudioFileReader) { TDebug.out("can't read initial header packet"); } | ||
150 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
151 | // no page? must not be vorbis | ||
152 | oggSyncState.free(); | ||
153 | oggStreamState.free(); | ||
154 | oggPage.free(); | ||
155 | oggPacket.free(); | ||
156 | throw new UnsupportedAudioFileException("not a Vorbis stream: can't read initial header packet"); | ||
157 | } | ||
158 | |||
159 | byte[] abData = oggPacket.getData(); | ||
160 | if (TDebug.TraceAudioFileReader) | ||
161 | { | ||
162 | String strData = ""; | ||
163 | for (int i = 0; i < abData.length; i++) | ||
164 | { | ||
165 | strData += " " + abData[i]; | ||
166 | } | ||
167 | TDebug.out("packet data: " + strData); | ||
168 | } | ||
169 | |||
170 | int nPacketType = abData[0]; | ||
171 | if (TDebug.TraceAudioFileReader) { TDebug.out("packet type: " + nPacketType); } | ||
172 | if (nPacketType != 1) | ||
173 | { | ||
174 | if (TDebug.TraceAudioFileReader) { TDebug.out("first packet is not the identification header"); } | ||
175 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
176 | oggSyncState.free(); | ||
177 | oggStreamState.free(); | ||
178 | oggPage.free(); | ||
179 | oggPacket.free(); | ||
180 | throw new UnsupportedAudioFileException("not a Vorbis stream: first packet is not the identification header"); | ||
181 | } | ||
182 | if(abData[1] != 'v' || | ||
183 | abData[2] != 'o' || | ||
184 | abData[3] != 'r' || | ||
185 | abData[4] != 'b' || | ||
186 | abData[5] != 'i' || | ||
187 | abData[6] != 's') | ||
188 | { | ||
189 | if (TDebug.TraceAudioFileReader) { TDebug.out("not a vorbis header packet"); } | ||
190 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
191 | oggSyncState.free(); | ||
192 | oggStreamState.free(); | ||
193 | oggPage.free(); | ||
194 | oggPacket.free(); | ||
195 | throw new UnsupportedAudioFileException("not a Vorbis stream: not a vorbis header packet"); | ||
196 | } | ||
197 | if (! oggPacket.isBos()) | ||
198 | { | ||
199 | if (TDebug.TraceAudioFileReader) { TDebug.out("initial packet not marked as beginning of stream"); } | ||
200 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
201 | oggSyncState.free(); | ||
202 | oggStreamState.free(); | ||
203 | oggPage.free(); | ||
204 | oggPacket.free(); | ||
205 | throw new UnsupportedAudioFileException("not a Vorbis stream: initial packet not marked as beginning of stream"); | ||
206 | } | ||
207 | int nVersion = (abData[7] & 0xFF) + 256 * (abData[8] & 0xFF) + 65536 * (abData[9] & 0xFF) + 16777216 * (abData[10] & 0xFF); | ||
208 | if (TDebug.TraceAudioFileReader) { TDebug.out("version: " + nVersion); } | ||
209 | if (nVersion != 0) | ||
210 | { | ||
211 | if (TDebug.TraceAudioFileReader) { TDebug.out("wrong vorbis version"); } | ||
212 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
213 | oggSyncState.free(); | ||
214 | oggStreamState.free(); | ||
215 | oggPage.free(); | ||
216 | oggPacket.free(); | ||
217 | throw new UnsupportedAudioFileException("not a Vorbis stream: wrong vorbis version"); | ||
218 | } | ||
219 | int nChannels = (abData[11] & 0xFF); | ||
220 | float fSampleRate = (abData[12] & 0xFF) + 256 * (abData[13] & 0xFF) + 65536 * (abData[14] & 0xFF) + 16777216 * (abData[15] & 0xFF); | ||
221 | if (TDebug.TraceAudioFileReader) { TDebug.out("channels: " + nChannels); } | ||
222 | if (TDebug.TraceAudioFileReader) { TDebug.out("rate: " + fSampleRate); } | ||
223 | |||
224 | // These are only used for error checking. | ||
225 | int bitrate_upper = abData[16] + 256 * abData[17] + 65536 * abData[18] + 16777216 * abData[19]; | ||
226 | int bitrate_nominal = abData[20] + 256 * abData[21] + 65536 * abData[22] + 16777216 * abData[23]; | ||
227 | int bitrate_lower = abData[24] + 256 * abData[25] + 65536 * abData[26] + 16777216 * abData[27]; | ||
228 | |||
229 | int[] blocksizes = new int[2]; | ||
230 | blocksizes[0] = 1 << (abData[28] & 0xF); | ||
231 | blocksizes[1] = 1 << ((abData[28] >>> 4) & 0xF); | ||
232 | if (TDebug.TraceAudioFileReader) { TDebug.out("blocksizes[0]: " + blocksizes[0]); } | ||
233 | if (TDebug.TraceAudioFileReader) { TDebug.out("blocksizes[1]: " + blocksizes[1]); } | ||
234 | |||
235 | if (fSampleRate < 1.0F || | ||
236 | nChannels < 1 || | ||
237 | blocksizes[0] < 8|| | ||
238 | blocksizes[1] < blocksizes[0] || | ||
239 | (abData[29] & 0x1) != 1) | ||
240 | { | ||
241 | if (TDebug.TraceAudioFileReader) { TDebug.out("illegal values in initial header"); } | ||
242 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): throwing exception"); } | ||
243 | oggSyncState.free(); | ||
244 | oggStreamState.free(); | ||
245 | oggPage.free(); | ||
246 | oggPacket.free(); | ||
247 | throw new UnsupportedAudioFileException("not a Vorbis stream: illegal values in initial header"); | ||
248 | } | ||
249 | |||
250 | oggSyncState.free(); | ||
251 | oggStreamState.free(); | ||
252 | oggPage.free(); | ||
253 | oggPacket.free(); | ||
254 | |||
255 | /* | ||
256 | If the file size is known, we derive the number of frames | ||
257 | ('frame size') from it. | ||
258 | If the values don't fit into integers, we leave them at | ||
259 | NOT_SPECIFIED. 'Unknown' is considered less incorrect than | ||
260 | a wrong value. | ||
261 | */ | ||
262 | // [fb] not specifying it causes Sun's Wave file writer to write rubbish | ||
263 | int nByteSize = AudioSystem.NOT_SPECIFIED; | ||
264 | if (lFileSizeInBytes != AudioSystem.NOT_SPECIFIED | ||
265 | && lFileSizeInBytes <= Integer.MAX_VALUE) | ||
266 | { | ||
267 | nByteSize = (int) lFileSizeInBytes; | ||
268 | } | ||
269 | int nFrameSize = AudioSystem.NOT_SPECIFIED; | ||
270 | /* Can we calculate a useful size? | ||
271 | Peeking into ogginfo gives the insight that the only | ||
272 | way seems to be reading through the file. This is | ||
273 | something we do not want, at least not by default. | ||
274 | */ | ||
275 | // nFrameSize = (int) (lFileSizeInBytes / ...; | ||
276 | |||
277 | AudioFormat format = new AudioFormat( | ||
278 | new AudioFormat.Encoding("VORBIS"), | ||
279 | fSampleRate, | ||
280 | AudioSystem.NOT_SPECIFIED, | ||
281 | nChannels, | ||
282 | AudioSystem.NOT_SPECIFIED, | ||
283 | AudioSystem.NOT_SPECIFIED, | ||
284 | true); // this value is chosen arbitrarily | ||
285 | if (TDebug.TraceAudioFileReader) { TDebug.out("AudioFormat: " + format); } | ||
286 | AudioFileFormat.Type type = new AudioFileFormat.Type("Ogg","ogg"); | ||
287 | AudioFileFormat audioFileFormat = | ||
288 | new TAudioFileFormat( | ||
289 | type, | ||
290 | format, | ||
291 | nFrameSize, | ||
292 | nByteSize); | ||
293 | if (TDebug.TraceAudioFileReader) { TDebug.out("AudioFileFormat: " + audioFileFormat); } | ||
294 | if (TDebug.TraceAudioFileReader) { TDebug.out("<VorbisAudioFileReader.getAudioFileFormat(): end"); } | ||
295 | return audioFileFormat; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | |||
300 | |||
301 | /*** VorbisAudioFileReader.java ***/ | ||
302 | |||
diff --git a/songdbj/org/tritonus/file/vorbis/VorbisAudioFileWriter.java b/songdbj/org/tritonus/file/vorbis/VorbisAudioFileWriter.java deleted file mode 100644 index ee7e310e48..0000000000 --- a/songdbj/org/tritonus/file/vorbis/VorbisAudioFileWriter.java +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileWriter.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de> | ||
9 | * Copyright (c) 2000 by Matthias Pfisterer | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Library General Public License as published | ||
13 | * by the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU Library General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Library General Public | ||
22 | * License along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | |<--- this code is formatted to fit into 80 columns --->| | ||
28 | */ | ||
29 | |||
30 | package org.tritonus.sampled.file.vorbis; | ||
31 | |||
32 | import java.util.Arrays; | ||
33 | |||
34 | import javax.sound.sampled.AudioFileFormat; | ||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioSystem; | ||
37 | |||
38 | import org.tritonus.share.TDebug; | ||
39 | import org.tritonus.share.sampled.file.THeaderlessAudioFileWriter; | ||
40 | |||
41 | |||
42 | |||
43 | /** Class for writing Vorbis streams | ||
44 | * | ||
45 | * @author Florian Bomers | ||
46 | * @author Matthias Pfisterer | ||
47 | */ | ||
48 | public class VorbisAudioFileWriter | ||
49 | extends THeaderlessAudioFileWriter | ||
50 | { | ||
51 | private static final AudioFileFormat.Type[] FILE_TYPES = | ||
52 | { | ||
53 | new AudioFileFormat.Type("Vorbis", "ogg") | ||
54 | }; | ||
55 | |||
56 | private static final AudioFormat[] AUDIO_FORMATS = | ||
57 | { | ||
58 | new AudioFormat(new AudioFormat.Encoding("VORBIS"), ALL, ALL, ALL, ALL, ALL, false), | ||
59 | new AudioFormat(new AudioFormat.Encoding("VORBIS"), ALL, ALL, ALL, ALL, ALL, true), | ||
60 | }; | ||
61 | |||
62 | |||
63 | |||
64 | public VorbisAudioFileWriter() | ||
65 | { | ||
66 | super(Arrays.asList(FILE_TYPES), | ||
67 | Arrays.asList(AUDIO_FORMATS)); | ||
68 | if (TDebug.TraceAudioFileWriter) { TDebug.out("VorbisAudioFileWriter.<init>(): begin"); } | ||
69 | if (TDebug.TraceAudioFileWriter) { TDebug.out("VorbisAudioFileWriter.<init>(): end"); } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
75 | /*** VorbisAudioFileWriter.java ***/ | ||
diff --git a/songdbj/org/tritonus/file/vorbis/package.html b/songdbj/org/tritonus/file/vorbis/package.html deleted file mode 100644 index 5d6c328b7d..0000000000 --- a/songdbj/org/tritonus/file/vorbis/package.html +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||
2 | <html> | ||
3 | <head> | ||
4 | </head> | ||
5 | |||
6 | <body> | ||
7 | <p>Ogg vorbis audio file reader and writer based on native libraries. | ||
8 | The classes provided here .</p> | ||
9 | |||
10 | @see org.tritonus.lowlevel.ogg | ||
11 | </body> | ||
12 | </html> | ||