summaryrefslogtreecommitdiff
path: root/songdbj/org/tritonus/file/AiffAudioFileReader.java
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
commit9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch)
tree4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/org/tritonus/file/AiffAudioFileReader.java
parentdfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff)
downloadrockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip
rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz
rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.bz2
rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.xz
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to '')
-rw-r--r--songdbj/org/tritonus/file/AiffAudioFileReader.java244
1 files changed, 244 insertions, 0 deletions
diff --git a/songdbj/org/tritonus/file/AiffAudioFileReader.java b/songdbj/org/tritonus/file/AiffAudioFileReader.java
new file mode 100644
index 0000000..139ba05
--- /dev/null
+++ b/songdbj/org/tritonus/file/AiffAudioFileReader.java
@@ -0,0 +1,244 @@
+/*
+ * AiffAudioFileReader.java
+ *
+ * This file is part of Tritonus: http://www.tritonus.org/
+ */
+
+/*
+ * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de>
+ * Copyright (c) 1999 by Matthias Pfisterer
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+|<--- this code is formatted to fit into 80 columns --->|
+*/
+
+package org.tritonus.sampled.file;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+import org.tritonus.share.sampled.file.TAudioFileFormat;
+import org.tritonus.share.sampled.file.TAudioFileReader;
+import org.tritonus.share.TDebug;
+
+
+/** Class for reading AIFF and AIFF-C files.
+ *
+ * @author Florian Bomers
+ * @author Matthias Pfisterer
+ */
+public class AiffAudioFileReader extends TAudioFileReader
+{
+ private static final int READ_LIMIT = 1000;
+
+
+
+ public AiffAudioFileReader()
+ {
+ super(READ_LIMIT);
+ }
+
+
+
+ private void skipChunk(DataInputStream dataInputStream, int chunkLength, int chunkRead)
+ throws IOException {
+ chunkLength-=chunkRead;
+ if (chunkLength>0) {
+ dataInputStream.skip(chunkLength + (chunkLength % 2));
+ }
+ }
+
+ private AudioFormat readCommChunk(DataInputStream dataInputStream, int chunkLength)
+ throws IOException, UnsupportedAudioFileException {
+
+ int nNumChannels = dataInputStream.readShort();
+ if (nNumChannels <= 0) {
+ throw new UnsupportedAudioFileException(
+ "not an AIFF file: number of channels must be positive");
+ }
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Found "+nNumChannels+" channels.");
+ }
+ // ignored: frame count
+ dataInputStream.readInt();
+ int nSampleSize = dataInputStream.readShort();
+ float fSampleRate = (float) readIeeeExtended(dataInputStream);
+ if (fSampleRate <= 0.0) {
+ throw new UnsupportedAudioFileException(
+ "not an AIFF file: sample rate must be positive");
+ }
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Found framerate "+fSampleRate);
+ }
+ AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
+ int nRead=18;
+ if (chunkLength>nRead) {
+ int nEncoding=dataInputStream.readInt();
+ nRead+=4;
+ if (nEncoding==AiffTool.AIFF_COMM_PCM) {
+ // PCM - nothing to do
+ }
+ else if (nEncoding==AiffTool.AIFF_COMM_ULAW) {
+ // ULAW
+ encoding=AudioFormat.Encoding.ULAW;
+ nSampleSize=8;
+ }
+ else if (nEncoding==AiffTool.AIFF_COMM_IMA_ADPCM) {
+ encoding = new AudioFormat.Encoding("IMA_ADPCM");
+ nSampleSize=4;
+ }
+ else {
+ throw new UnsupportedAudioFileException(
+ "Encoding 0x"+Integer.toHexString(nEncoding)
+ +" of AIFF file not supported");
+ }
+ }
+ /* In case of IMA ADPCM, frame size is 0.5 bytes (since it is
+ always mono). A value of 1 as frame size would be wrong.
+ Handling of frame size 0 in defined nowhere. So the best
+ solution is to set the frame size to unspecified (-1).
+ */
+ int nFrameSize = (nSampleSize == 4) ?
+ AudioSystem.NOT_SPECIFIED :
+ calculateFrameSize(nSampleSize, nNumChannels);
+ if (TDebug.TraceAudioFileReader) { TDebug.out("calculated frame size: " + nFrameSize); }
+ skipChunk(dataInputStream, chunkLength, nRead);
+ AudioFormat format = new AudioFormat(encoding,
+ fSampleRate,
+ nSampleSize,
+ nNumChannels,
+ nFrameSize,
+ fSampleRate,
+ true);
+ return format;
+ }
+
+ private void readVerChunk(DataInputStream dataInputStream, int chunkLength)
+ throws IOException, UnsupportedAudioFileException {
+ if (chunkLength<4) {
+ throw new UnsupportedAudioFileException(
+ "Corrput AIFF file: FVER chunk too small.");
+ }
+ int nVer=dataInputStream.readInt();
+ if (nVer!=AiffTool.AIFF_FVER_TIME_STAMP) {
+ throw new UnsupportedAudioFileException(
+ "Unsupported AIFF file: version not known.");
+ }
+ skipChunk(dataInputStream, chunkLength, 4);
+ }
+
+
+
+ protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes)
+ throws UnsupportedAudioFileException, IOException
+ {
+ if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): begin"); }
+ DataInputStream dataInputStream = new DataInputStream(inputStream);
+ int nMagic = dataInputStream.readInt();
+ if (nMagic != AiffTool.AIFF_FORM_MAGIC) {
+ throw new UnsupportedAudioFileException(
+ "not an AIFF file: header magic is not FORM");
+ }
+ int nTotalLength = dataInputStream.readInt();
+ nMagic = dataInputStream.readInt();
+ boolean bIsAifc;
+ if (nMagic == AiffTool.AIFF_AIFF_MAGIC) {
+ bIsAifc = false;
+ } else if (nMagic == AiffTool.AIFF_AIFC_MAGIC) {
+ bIsAifc = true;
+ } else {
+ throw new UnsupportedAudioFileException(
+ "unsupported IFF file: header magic neither AIFF nor AIFC");
+ }
+ boolean bFVerFound=!bIsAifc;
+ boolean bCommFound=false;
+ boolean bSSndFound=false;
+ AudioFormat format=null;
+ int nDataChunkLength=0;
+
+ // walk through the chunks
+ // chunks may be in any order. However, in this implementation, SSND must be last
+ while (!bFVerFound || !bCommFound || !bSSndFound) {
+ nMagic = dataInputStream.readInt();
+ int nChunkLength = dataInputStream.readInt();
+ switch (nMagic) {
+ case AiffTool.AIFF_COMM_MAGIC:
+ format=readCommChunk(dataInputStream, nChunkLength);
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Read COMM chunk with length "+nChunkLength);
+ }
+ bCommFound=true;
+ break;
+ case AiffTool.AIFF_FVER_MAGIC:
+ if (!bFVerFound) {
+ readVerChunk(dataInputStream, nChunkLength);
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Read FVER chunk with length "+nChunkLength);
+ }
+ bFVerFound=true;
+ } else {
+ skipChunk(dataInputStream, nChunkLength, 0);
+ }
+ break;
+ case AiffTool.AIFF_SSND_MAGIC:
+ if (!bCommFound || !bFVerFound) {
+ throw new UnsupportedAudioFileException(
+ "cannot handle AIFF file: SSND not last chunk");
+ }
+ bSSndFound=true;
+ nDataChunkLength=nChunkLength-8;
+ // 8 information bytes of no interest
+ dataInputStream.skip(8);
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Found SSND chunk with length "+nChunkLength);
+ }
+ break;
+ default:
+ if (TDebug.TraceAudioFileReader) {
+ TDebug.out("Skipping unknown chunk: "
+ +Integer.toHexString(nMagic));
+ }
+ skipChunk(dataInputStream, nChunkLength, 0);
+ break;
+ }
+ }
+
+ // TODO: length argument has to be in frames
+ AudioFileFormat audioFileFormat = new TAudioFileFormat(
+ bIsAifc ? AudioFileFormat.Type.AIFC : AudioFileFormat.Type.AIFF,
+ format,
+ nDataChunkLength / format.getFrameSize(),
+ nTotalLength + 8);
+ if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): end"); }
+ return audioFileFormat;
+ }
+}
+
+
+
+/*** AiffAudioFileReader.java ***/