From 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e Mon Sep 17 00:00:00 2001 From: Michiel Van Der Kolk Date: Mon, 11 Jul 2005 15:42:37 +0000 Subject: Songdb java version, source. only 1.5 compatible git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657 --- songdbj/org/tritonus/file/AiffAudioFileReader.java | 244 +++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 songdbj/org/tritonus/file/AiffAudioFileReader.java (limited to 'songdbj/org/tritonus/file/AiffAudioFileReader.java') diff --git a/songdbj/org/tritonus/file/AiffAudioFileReader.java b/songdbj/org/tritonus/file/AiffAudioFileReader.java new file mode 100644 index 0000000000..139ba05425 --- /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 + * 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 ***/ -- cgit v1.2.3