jdk/src/share/classes/com/sun/media/sound/AuFileReader.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/media/sound/AuFileReader.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,398 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.Vector;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.DataOutputStream;
+import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.SequenceInputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+
+/**
+ * AU file reader.
+ *
+ * @author Kara Kytle
+ * @author Jan Borgersen
+ * @author Florian Bomers
+ */
+public class AuFileReader extends SunFileReader {
+
+    /**
+     * AU reader type
+     */
+
+    public static final AudioFileFormat.Type types[] = {
+        AudioFileFormat.Type.AU
+    };
+
+
+    /**
+     * Constructs a new AuFileReader object.
+     */
+    public AuFileReader() {
+    }
+
+
+    // METHODS TO IMPLEMENT AudioFileReader
+
+    /**
+     * Obtains the audio file format of the input stream provided.  The stream must
+     * point to valid audio file data.  In general, audio file providers may
+     * need to read some data from the stream before determining whether they
+     * support it.  These parsers must
+     * be able to mark the stream, read enough data to determine whether they
+     * support the stream, and, if not, reset the stream's read pointer to its original
+     * position.  If the input stream does not support this, this method may fail
+     * with an IOException.
+     * @param stream the input stream from which file format information should be
+     * extracted
+     * @return an <code>AudioFileFormat</code> object describing the audio file format
+     * @throws UnsupportedAudioFileException if the stream does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     * @see InputStream#markSupported
+     * @see InputStream#mark
+     */
+    public AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException {
+
+        AudioFormat format = null;
+        AuFileFormat fileFormat = null;
+        int maxReadLength = 28;
+        boolean bigendian  = false;
+        int magic          = -1;
+        int headerSize     = -1;
+        int dataSize       = -1;
+        int encoding_local = -1;
+        int sampleRate     = -1;
+        int frameRate      = -1;
+        int frameSize      = -1;
+        int channels       = -1;
+        int sampleSizeInBits = 0;
+        int length = 0;
+        int nread = 0;
+        AudioFormat.Encoding encoding = null;
+
+        DataInputStream dis = new DataInputStream( stream );
+
+        dis.mark(maxReadLength);
+
+        magic = dis.readInt();
+
+        if (! (magic == AuFileFormat.AU_SUN_MAGIC) || (magic == AuFileFormat.AU_DEC_MAGIC) ||
+            (magic == AuFileFormat.AU_SUN_INV_MAGIC) || (magic == AuFileFormat.AU_DEC_INV_MAGIC) ) {
+
+            // not AU, reset the stream, place into exception, throw exception
+            dis.reset();
+            throw new UnsupportedAudioFileException("not an AU file");
+        }
+
+        if ((magic == AuFileFormat.AU_SUN_MAGIC) || (magic == AuFileFormat.AU_DEC_MAGIC)) {
+            bigendian = true;        // otherwise little-endian
+        }
+
+        headerSize     = (bigendian==true ? dis.readInt() : rllong(dis) );  nread += 4;
+        dataSize       = (bigendian==true ? dis.readInt() : rllong(dis) );  nread += 4;
+        encoding_local = (bigendian==true ? dis.readInt() : rllong(dis) );  nread += 4;
+        sampleRate     = (bigendian==true ? dis.readInt() : rllong(dis) );  nread += 4;
+        channels       = (bigendian==true ? dis.readInt() : rllong(dis) );  nread += 4;
+
+        frameRate = sampleRate;
+
+        switch (encoding_local) {
+        case AuFileFormat.AU_ULAW_8:
+            encoding = AudioFormat.Encoding.ULAW;
+            sampleSizeInBits = 8;
+            break;
+        case AuFileFormat.AU_ALAW_8:
+            encoding = AudioFormat.Encoding.ALAW;
+            sampleSizeInBits = 8;
+            break;
+        case AuFileFormat.AU_LINEAR_8:
+            // $$jb: 04.29.99: 8bit linear is *signed*, not *unsigned*
+            encoding = AudioFormat.Encoding.PCM_SIGNED;
+            sampleSizeInBits = 8;
+            break;
+        case AuFileFormat.AU_LINEAR_16:
+            encoding = AudioFormat.Encoding.PCM_SIGNED;
+            sampleSizeInBits = 16;
+            break;
+        case AuFileFormat.AU_LINEAR_24:
+            encoding = AudioFormat.Encoding.PCM_SIGNED;
+
+            sampleSizeInBits = 24;
+            break;
+        case AuFileFormat.AU_LINEAR_32:
+            encoding = AudioFormat.Encoding.PCM_SIGNED;
+
+            sampleSizeInBits = 32;
+            break;
+            // $jb: 03.19.99: we don't support these ...
+            /*          case AuFileFormat.AU_FLOAT:
+                        encoding = new AudioFormat.FLOAT;
+                        sampleSizeInBits = 32;
+                        break;
+                        case AuFileFormat.AU_DOUBLE:
+                        encoding = new AudioFormat.DOUBLE;
+                        sampleSizeInBits = 8;
+                        break;
+                        case AuFileFormat.AU_ADPCM_G721:
+                        encoding = new AudioFormat.G721_ADPCM;
+                        sampleSizeInBits = 16;
+                        break;
+                        case AuFileFormat.AU_ADPCM_G723_3:
+                        encoding = new AudioFormat.G723_3;
+                        sampleSize = 24;
+                        SamplePerUnit = 8;
+                        break;
+                        case AuFileFormat.AU_ADPCM_G723_5:
+                        encoding = new AudioFormat.G723_5;
+                        sampleSize = 40;
+                        SamplePerUnit = 8;
+                        break;
+            */
+        default:
+                // unsupported filetype, throw exception
+                dis.reset();
+                throw new UnsupportedAudioFileException("not a valid AU file");
+        }
+
+        frameSize = calculatePCMFrameSize(sampleSizeInBits, channels);
+        //$$fb 2002-11-02: fix for 4629669: AU file reader: problems with empty files
+        if( dataSize < 0 ) {
+            length = AudioSystem.NOT_SPECIFIED;
+        } else {
+            //$$fb 2003-10-20: fix for 4940459: AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED
+            length = dataSize / frameSize;
+        }
+
+        format = new AudioFormat( encoding, (float)sampleRate, sampleSizeInBits,
+                                  channels, frameSize, (float)frameRate, bigendian);
+
+        fileFormat = new AuFileFormat( AudioFileFormat.Type.AU, dataSize+headerSize,
+                                       format, length);
+
+        dis.reset(); // Throws IOException
+        return fileFormat;
+
+    }
+
+
+    /**
+     * Obtains the audio file format of the URL provided.  The URL must
+     * point to valid audio file data.
+     * @param url the URL from which file format information should be
+     * extracted
+     * @return an <code>AudioFileFormat</code> object describing the audio file format
+     * @throws UnsupportedAudioFileException if the URL does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     */
+    public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException {
+
+        InputStream                             urlStream = null;
+        BufferedInputStream             bis = null;
+        AudioFileFormat                 fileFormat = null;
+        AudioFormat                             format = null;
+
+        urlStream = url.openStream();   // throws IOException
+
+        try {
+            bis = new BufferedInputStream( urlStream, bisBufferSize );
+
+            fileFormat = getAudioFileFormat( bis );             // throws UnsupportedAudioFileException
+        } finally {
+            urlStream.close();
+        }
+
+        return fileFormat;
+    }
+
+
+    /**
+     * Obtains the audio file format of the File provided.  The File must
+     * point to valid audio file data.
+     * @param file the File from which file format information should be
+     * extracted
+     * @return an <code>AudioFileFormat</code> object describing the audio file format
+     * @throws UnsupportedAudioFileException if the File does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     */
+    public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException {
+
+        FileInputStream                 fis = null;
+        BufferedInputStream             bis = null;
+        AudioFileFormat                 fileFormat = null;
+        AudioFormat                             format = null;
+
+        fis = new FileInputStream( file );      // throws IOException
+        // part of fix for 4325421
+        try {
+            bis = new BufferedInputStream( fis, bisBufferSize );
+            fileFormat = getAudioFileFormat( bis );             // throws UnsupportedAudioFileException
+        } finally {
+            fis.close();
+        }
+
+        return fileFormat;
+    }
+
+
+    /**
+     * Obtains an audio stream from the input stream provided.  The stream must
+     * point to valid audio file data.  In general, audio file providers may
+     * need to read some data from the stream before determining whether they
+     * support it.  These parsers must
+     * be able to mark the stream, read enough data to determine whether they
+     * support the stream, and, if not, reset the stream's read pointer to its original
+     * position.  If the input stream does not support this, this method may fail
+     * with an IOException.
+     * @param stream the input stream from which the <code>AudioInputStream</code> should be
+     * constructed
+     * @return an <code>AudioInputStream</code> object based on the audio file data contained
+     * in the input stream.
+     * @throws UnsupportedAudioFileException if the stream does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     * @see InputStream#markSupported
+     * @see InputStream#mark
+     */
+    public AudioInputStream getAudioInputStream(InputStream stream) throws UnsupportedAudioFileException, IOException {
+
+        DataInputStream dis = null;
+        int headerSize;
+        AudioFileFormat fileFormat = null;
+        AudioFormat format = null;
+
+
+        fileFormat = getAudioFileFormat( stream ); // throws UnsupportedAudioFileException, IOException
+
+        // if we passed this call, we have an AU file.
+
+        format = fileFormat.getFormat();
+
+        dis = new DataInputStream(stream);
+
+        // now seek past the header
+
+        dis.readInt(); // magic
+        headerSize     = (format.isBigEndian()==true ? dis.readInt() : rllong(dis) );
+        dis.skipBytes( headerSize - 8 );
+
+
+        // we've got everything, and the stream should be at the
+        // beginning of the data chunk, so return an AudioInputStream.
+
+        return new AudioInputStream(dis, format, fileFormat.getFrameLength());
+    }
+
+
+    /**
+     * Obtains an audio stream from the URL provided.  The URL must
+     * point to valid audio file data.
+     * @param url the URL for which the <code>AudioInputStream</code> should be
+     * constructed
+     * @return an <code>AudioInputStream</code> object based on the audio file data pointed
+     * to by the URL
+     * @throws UnsupportedAudioFileException if the URL does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     */
+    public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException {
+
+        InputStream                             urlStream = null;
+        BufferedInputStream             bis = null;
+        AudioFileFormat                 fileFormat = null;
+
+        urlStream = url.openStream();   // throws IOException
+        AudioInputStream result = null;
+        try {
+            bis = new BufferedInputStream( urlStream, bisBufferSize );
+            result = getAudioInputStream( (InputStream)bis );
+        } finally {
+            if (result == null) {
+                urlStream.close();
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Obtains an audio stream from the File provided.  The File must
+     * point to valid audio file data.
+     * @param file the File for which the <code>AudioInputStream</code> should be
+     * constructed
+     * @return an <code>AudioInputStream</code> object based on the audio file data pointed
+     * to by the File
+     * @throws UnsupportedAudioFileException if the File does not point to valid audio
+     * file data recognized by the system
+     * @throws IOException if an I/O exception occurs
+     */
+    public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
+
+        FileInputStream                 fis = null;
+        BufferedInputStream             bis = null;
+        AudioFileFormat                 fileFormat = null;
+
+        fis = new FileInputStream( file );      // throws IOException
+        AudioInputStream result = null;
+        // part of fix for 4325421
+        try {
+            bis = new BufferedInputStream( fis, bisBufferSize );
+            result = getAudioInputStream( (InputStream)bis );
+        } finally {
+            if (result == null) {
+                fis.close();
+            }
+        }
+
+        return result;
+    }
+
+
+
+}