Path: blob/master/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java
41161 views
/*1* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.media.sound;2627import java.io.DataInputStream;28import java.io.IOException;29import java.io.InputStream;3031import javax.sound.sampled.AudioFileFormat.Type;32import javax.sound.sampled.AudioFormat;33import javax.sound.sampled.AudioSystem;34import javax.sound.sampled.UnsupportedAudioFileException;3536/**37* AIFF file reader and writer.38*39* @author Kara Kytle40* @author Jan Borgersen41* @author Florian Bomers42*/43public final class AiffFileReader extends SunFileReader {4445@Override46StandardFileFormat getAudioFileFormatImpl(final InputStream stream)47throws UnsupportedAudioFileException, IOException {48DataInputStream dis = new DataInputStream(stream);4950AudioFormat format = null;5152// Read the magic number53int magic = dis.readInt();5455// $$fb: fix for 4369044: javax.sound.sampled.AudioSystem.getAudioInputStream() works wrong with Cp03756if (magic != AiffFileFormat.AIFF_MAGIC) {57// not AIFF, throw exception58throw new UnsupportedAudioFileException("not an AIFF file");59}6061long /* unsigned 32bit */ frameLength = 0;62int length = dis.readInt();63int iffType = dis.readInt();6465final long totallength;66if(length <= 0 ) {67length = AudioSystem.NOT_SPECIFIED;68totallength = AudioSystem.NOT_SPECIFIED;69} else {70totallength = length + 8;71}7273// Is this an AIFC or just plain AIFF file.74boolean aifc = false;75// $$fb: fix for 4369044: javax.sound.sampled.AudioSystem.getAudioInputStream() works wrong with Cp03776if (iffType == AiffFileFormat.AIFC_MAGIC) {77aifc = true;78}7980// Loop through the AIFF chunks until81// we get to the SSND chunk.82boolean ssndFound = false;83while (!ssndFound) {84// Read the chunk name85int chunkName = dis.readInt();86int chunkLen = dis.readInt();8788int chunkRead = 0;8990// Switch on the chunk name.91switch (chunkName) {92case AiffFileFormat.FVER_MAGIC:93// Ignore format version for now.94break;9596case AiffFileFormat.COMM_MAGIC:97// AIFF vs. AIFC98// $$fb: fix for 4399551: Repost of bug candidate: cannot replay aif file (Review ID: 108108)99if ((!aifc && chunkLen < 18) || (aifc && chunkLen < 22)) {100throw new UnsupportedAudioFileException("Invalid AIFF/COMM chunksize");101}102// Read header info.103int channels = dis.readUnsignedShort();104if (channels <= 0) {105throw new UnsupportedAudioFileException("Invalid number of channels");106}107frameLength = dis.readInt() & 0xffffffffL; // numSampleFrames108109int sampleSizeInBits = dis.readUnsignedShort();110if (sampleSizeInBits < 1 || sampleSizeInBits > 32) {111throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize");112}113float sampleRate = (float) read_ieee_extended(dis);114chunkRead += (2 + 4 + 2 + 10);115116// If this is not AIFC then we assume it's117// a linearly encoded file.118AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;119120if (aifc) {121int enc = dis.readInt(); chunkRead += 4;122switch (enc) {123case AiffFileFormat.AIFC_PCM:124encoding = AudioFormat.Encoding.PCM_SIGNED;125break;126case AiffFileFormat.AIFC_ULAW:127encoding = AudioFormat.Encoding.ULAW;128sampleSizeInBits = 8; // Java Sound convention129break;130default:131throw new UnsupportedAudioFileException("Invalid AIFF encoding");132}133}134int frameSize = calculatePCMFrameSize(sampleSizeInBits, channels);135//$fb what's that ??136//if (sampleSizeInBits == 8) {137// encoding = AudioFormat.Encoding.PCM_SIGNED;138//}139format = new AudioFormat(encoding, sampleRate,140sampleSizeInBits, channels,141frameSize, sampleRate, true);142break;143case AiffFileFormat.SSND_MAGIC:144// Data chunk.145int dataOffset = dis.readInt(); // for now unused in javasound146int blocksize = dis.readInt(); // for now unused in javasound147chunkRead += 8;148ssndFound = true;149break;150} // switch151// skip the remainder of this chunk152if (!ssndFound) {153int toSkip = chunkLen - chunkRead;154if (toSkip > 0) {155dis.skipBytes(toSkip);156}157}158} // while159160if (format == null) {161throw new UnsupportedAudioFileException("missing COMM chunk");162}163Type type = aifc ? Type.AIFC : Type.AIFF;164165return new AiffFileFormat(type, totallength, format, frameLength);166}167168// HELPER METHODS169/**170* read_ieee_extended171* Extended precision IEEE floating-point conversion routine.172* @argument DataInputStream173* @return double174* @exception IOException175*/176private double read_ieee_extended(DataInputStream dis) throws IOException {177178double f = 0;179int expon = 0;180long hiMant = 0, loMant = 0;181long t1, t2;182double HUGE = 3.40282346638528860e+38;183184185expon = dis.readUnsignedShort();186187t1 = (long)dis.readUnsignedShort();188t2 = (long)dis.readUnsignedShort();189hiMant = t1 << 16 | t2;190191t1 = (long)dis.readUnsignedShort();192t2 = (long)dis.readUnsignedShort();193loMant = t1 << 16 | t2;194195if (expon == 0 && hiMant == 0 && loMant == 0) {196f = 0;197} else {198if (expon == 0x7FFF)199f = HUGE;200else {201expon -= 16383;202expon -= 31;203f = (hiMant * Math.pow(2, expon));204expon -= 32;205f += (loMant * Math.pow(2, expon));206}207}208209return f;210}211}212213214