aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/jsyn/util/soundfile/AIFFFileParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/jsyn/util/soundfile/AIFFFileParser.java')
-rw-r--r--src/com/jsyn/util/soundfile/AIFFFileParser.java227
1 files changed, 0 insertions, 227 deletions
diff --git a/src/com/jsyn/util/soundfile/AIFFFileParser.java b/src/com/jsyn/util/soundfile/AIFFFileParser.java
deleted file mode 100644
index 2b09d78..0000000
--- a/src/com/jsyn/util/soundfile/AIFFFileParser.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2009 Phil Burk, Mobileer Inc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.jsyn.util.soundfile;
-
-import java.io.EOFException;
-import java.io.IOException;
-
-import com.jsyn.data.FloatSample;
-import com.jsyn.data.SampleMarker;
-import com.jsyn.util.SampleLoader;
-
-public class AIFFFileParser extends AudioFileParser {
- private static final String SUPPORTED_FORMATS = "Only 16 and 24 bit PCM or 32-bit float AIF files supported.";
- static final int AIFF_ID = ('A' << 24) | ('I' << 16) | ('F' << 8) | 'F';
- static final int AIFC_ID = ('A' << 24) | ('I' << 16) | ('F' << 8) | 'C';
- static final int COMM_ID = ('C' << 24) | ('O' << 16) | ('M' << 8) | 'M';
- static final int SSND_ID = ('S' << 24) | ('S' << 16) | ('N' << 8) | 'D';
- static final int MARK_ID = ('M' << 24) | ('A' << 16) | ('R' << 8) | 'K';
- static final int INST_ID = ('I' << 24) | ('N' << 16) | ('S' << 8) | 'T';
- static final int NONE_ID = ('N' << 24) | ('O' << 16) | ('N' << 8) | 'E';
- static final int FL32_ID = ('F' << 24) | ('L' << 16) | ('3' << 8) | '2';
- static final int FL32_ID_LC = ('f' << 24) | ('l' << 16) | ('3' << 8) | '2';
-
- int sustainBeginID = -1;
- int sustainEndID = -1;
- int releaseBeginID = -1;
- int releaseEndID = -1;
- boolean typeFloat = false;
-
- @Override
- FloatSample finish() throws IOException {
- setLoops();
-
- if ((byteData == null)) {
- throw new IOException("No data found in audio sample.");
- }
- float[] floatData = new float[numFrames * samplesPerFrame];
- if (bitsPerSample == 16) {
- SampleLoader.decodeBigI16ToF32(byteData, 0, byteData.length, floatData, 0);
- } else if (bitsPerSample == 24) {
- SampleLoader.decodeBigI24ToF32(byteData, 0, byteData.length, floatData, 0);
- } else if (bitsPerSample == 32) {
- if (typeFloat) {
- SampleLoader.decodeBigF32ToF32(byteData, 0, byteData.length, floatData, 0);
- } else {
- SampleLoader.decodeBigI32ToF32(byteData, 0, byteData.length, floatData, 0);
- }
- } else {
- throw new IOException(SUPPORTED_FORMATS + " size = " + bitsPerSample);
- }
-
- return makeSample(floatData);
- }
-
- double read80BitFloat() throws IOException {
- /*
- * This is not a full decoding of the 80 bit number but it should suffice for the range we
- * expect.
- */
- byte[] bytes = new byte[10];
- parser.read(bytes);
- int exp = ((bytes[0] & 0x3F) << 8) | (bytes[1] & 0xFF);
- int mant = ((bytes[2] & 0xFF) << 16) | ((bytes[3] & 0xFF) << 8) | (bytes[4] & 0xFF);
- // System.out.println( "exp = " + exp + ", mant = " + mant );
- return mant / (double) (1 << (22 - exp));
- }
-
- void parseCOMMChunk(IFFParser parser, int ckSize) throws IOException {
- samplesPerFrame = parser.readShortBig();
- numFrames = parser.readIntBig();
- bitsPerSample = parser.readShortBig();
- frameRate = read80BitFloat();
- if (ckSize > 18) {
- int format = parser.readIntBig();
- // Validate data format.
- if ((format == FL32_ID) || (format == FL32_ID_LC)) {
- typeFloat = true;
- } else if (format == NONE_ID) {
- typeFloat = false;
- } else {
- throw new IOException(SUPPORTED_FORMATS + " format " + IFFParser.IDToString(format));
- }
- }
-
- bytesPerSample = (bitsPerSample + 7) / 8;
- bytesPerFrame = bytesPerSample * samplesPerFrame;
- }
-
- /* parse tuning and multi-sample info */
- @SuppressWarnings("unused")
- void parseINSTChunk(IFFParser parser, int ckSize) throws IOException {
- int baseNote = parser.readByte();
- int detune = parser.readByte();
- originalPitch = baseNote + (0.01 * detune);
-
- int lowNote = parser.readByte();
- int highNote = parser.readByte();
-
- parser.skip(2); /* lo,hi velocity */
- int gain = parser.readShortBig();
-
- int playMode = parser.readShortBig(); /* sustain */
- sustainBeginID = parser.readShortBig();
- sustainEndID = parser.readShortBig();
-
- playMode = parser.readShortBig(); /* release */
- releaseBeginID = parser.readShortBig();
- releaseEndID = parser.readShortBig();
- }
-
- private void setLoops() {
- SampleMarker cuePoint = cueMap.get(sustainBeginID);
- if (cuePoint != null) {
- sustainBegin = cuePoint.position;
- }
- cuePoint = cueMap.get(sustainEndID);
- if (cuePoint != null) {
- sustainEnd = cuePoint.position;
- }
- }
-
- void parseSSNDChunk(IFFParser parser, int ckSize) throws IOException {
- long numRead;
- // System.out.println("parseSSNDChunk()");
- int offset = parser.readIntBig();
- parser.readIntBig(); /* blocksize */
- parser.skip(offset);
- dataPosition = parser.getOffset();
- int numBytes = ckSize - 8 - offset;
- if (ifLoadData) {
- byteData = new byte[numBytes];
- numRead = parser.read(byteData);
- } else {
- numRead = parser.skip(numBytes);
- }
- if (numRead != numBytes)
- throw new EOFException("AIFF data chunk too short!");
- }
-
- void parseMARKChunk(IFFParser parser, int ckSize) throws IOException {
- long startOffset = parser.getOffset();
- int numCuePoints = parser.readShortBig();
- // System.out.println( "parseCueChunk: numCuePoints = " + numCuePoints
- // );
- for (int i = 0; i < numCuePoints; i++) {
- // Some AIF files have a bogus numCuePoints so check to see if we
- // are at end.
- long numInMark = parser.getOffset() - startOffset;
- if (numInMark >= ckSize) {
- System.out.println("Reached end of MARK chunk with bogus numCuePoints = "
- + numCuePoints);
- break;
- }
-
- int uniqueID = parser.readShortBig();
- int position = parser.readIntBig();
- int len = parser.read();
- String markerName = parseString(parser, len);
- if ((len & 1) == 0) {
- parser.skip(1); /* skip pad byte */
- }
-
- SampleMarker cuePoint = findOrCreateCuePoint(uniqueID);
- cuePoint.position = position;
- cuePoint.name = markerName;
-
- if (IFFParser.debug) {
- System.out.println("AIFF Marker at " + position + ", " + markerName);
- }
- }
- }
-
- /**
- * Called by parse() method to handle FORM chunks in an AIFF specific manner.
- *
- * @param ckID four byte chunk ID such as 'data'
- * @param ckSize size of chunk in bytes
- * @exception IOException If parsing fails, or IO error occurs.
- */
- @Override
- public void handleForm(IFFParser parser, int ckID, int ckSize, int type) throws IOException {
- if ((ckID == IFFParser.FORM_ID) && (type != AIFF_ID) && (type != AIFC_ID))
- throw new IOException("Bad AIFF form type = " + IFFParser.IDToString(type));
- }
-
- /**
- * Called by parse() method to handle chunks in an AIFF specific manner.
- *
- * @param ckID four byte chunk ID such as 'data'
- * @param ckSize size of chunk in bytes
- * @exception IOException If parsing fails, or IO error occurs.
- */
- @Override
- public void handleChunk(IFFParser parser, int ckID, int ckSize) throws IOException {
- switch (ckID) {
- case COMM_ID:
- parseCOMMChunk(parser, ckSize);
- break;
- case SSND_ID:
- parseSSNDChunk(parser, ckSize);
- break;
- case MARK_ID:
- parseMARKChunk(parser, ckSize);
- break;
- case INST_ID:
- parseINSTChunk(parser, ckSize);
- break;
- default:
- break;
- }
- }
-
-}