6729836: JavaSound treats large file sizes as negative and cannot read or skip
Reviewed-by: prr
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileFormat.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileFormat.java Wed May 04 01:03:46 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. 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
@@ -25,17 +25,14 @@
package com.sun.media.sound;
-import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
-
/**
* AIFF file format.
*
* @author Jan Borgersen
*/
-
-final class AiffFileFormat extends AudioFileFormat {
+final class AiffFileFormat extends StandardFileFormat {
static final int AIFF_MAGIC = 1179603533;
@@ -70,11 +67,8 @@
/** FVER chunk size in bytes, inclusive magic and length field */
private final int fverChunkSize=0;
- AiffFileFormat( AudioFileFormat aff ) {
- this( aff.getType(), aff.getByteLength(), aff.getFormat(), aff.getFrameLength() );
- }
-
- AiffFileFormat(Type type, int byteLength, AudioFormat format, int frameLength) {
+ AiffFileFormat(final Type type, final long byteLength,
+ final AudioFormat format, final long frameLength) {
super(type, byteLength, format, frameLength);
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -45,7 +45,7 @@
public final class AiffFileReader extends SunFileReader {
@Override
- AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
DataInputStream dis = new DataInputStream(stream);
@@ -60,11 +60,11 @@
throw new UnsupportedAudioFileException("not an AIFF file");
}
- int frameLength = 0;
+ long /* unsigned 32bit */ frameLength = 0;
int length = dis.readInt();
int iffType = dis.readInt();
- int totallength;
+ final long totallength;
if(length <= 0 ) {
length = AudioSystem.NOT_SPECIFIED;
totallength = AudioSystem.NOT_SPECIFIED;
@@ -106,12 +106,7 @@
if (channels <= 0) {
throw new UnsupportedAudioFileException("Invalid number of channels");
}
- frameLength = dis.readInt(); // numSampleFrames
- if (frameLength < 0) {
- // AiffFileFormat uses int, unlike AIS which uses long
- //TODO this (negative) value should be passed as long to AIS
- frameLength = AudioSystem.NOT_SPECIFIED;
- }
+ frameLength = dis.readInt() & 0xffffffffL; // numSampleFrames
int sampleSizeInBits = dis.readUnsignedShort();
if (sampleSizeInBits < 1 || sampleSizeInBits > 32) {
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java Wed May 04 01:03:46 2016 +0300
@@ -33,7 +33,7 @@
*
* @author Jan Borgersen
*/
-final class AuFileFormat extends AudioFileFormat {
+final class AuFileFormat extends StandardFileFormat {
// magic numbers
static final int AU_SUN_MAGIC = 0x2e736e64; // ".snd"
@@ -55,11 +55,18 @@
static final int AU_HEADERSIZE = 24;
+ /**
+ * According the specification of AU file format this is the value for
+ * length field if length is not known. This is a maximum possible value for
+ * the unsigned int.
+ */
+ static final long /*unsigned int */ UNKNOWN_SIZE = 0xffffffffL;
+
private int auType;
- AuFileFormat(AudioFileFormat.Type type, int lengthInBytes, AudioFormat format, int lengthInFrames) {
-
- super(type,lengthInBytes,format,lengthInFrames);
+ AuFileFormat(final AudioFileFormat.Type type, final long byteLength,
+ final AudioFormat format, final long frameLength) {
+ super(type, byteLength, format, frameLength);
AudioFormat.Encoding encoding = format.getEncoding();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -29,7 +29,6 @@
import java.io.IOException;
import java.io.InputStream;
-import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFileFormat.Type;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
@@ -45,7 +44,7 @@
public final class AuFileReader extends SunFileReader {
@Override
- public AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ public StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
final DataInputStream dis = new DataInputStream(stream);
final int magic = dis.readInt();
@@ -56,7 +55,7 @@
}
final int headerSize = dis.readInt();
- final int dataSize = dis.readInt();
+ final long /* unsigned int */ dataSize = dis.readInt() & 0xffffffffL;
final int auType = dis.readInt();
final int sampleRate = dis.readInt();
final int channels = dis.readInt();
@@ -120,21 +119,21 @@
// unsupported filetype, throw exception
throw new UnsupportedAudioFileException("not a valid AU file");
}
+ // now seek past the header
+ dis.skipBytes(headerSize - AuFileFormat.AU_HEADERSIZE);
final int frameSize = calculatePCMFrameSize(sampleSizeInBits, channels);
//$$fb 2002-11-02: fix for 4629669: AU file reader: problems with empty files
- final int length;
- 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;
+ //$$fb 2003-10-20: fix for 4940459: AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED
+ long frameLength = AudioSystem.NOT_SPECIFIED;
+ long byteLength = AudioSystem.NOT_SPECIFIED;
+ if (dataSize != AuFileFormat.UNKNOWN_SIZE) {
+ frameLength = dataSize / frameSize;
+ byteLength = dataSize + headerSize;
}
- // now seek past the header
- dis.skipBytes(headerSize - AuFileFormat.AU_HEADERSIZE);
final AudioFormat format = new AudioFormat(encoding, sampleRate,
sampleSizeInBits, channels,
frameSize, sampleRate, true);
- return new AuFileFormat(Type.AU, dataSize + headerSize, format, length);
+ return new AuFileFormat(Type.AU, byteLength, format, frameLength);
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. 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
@@ -38,7 +38,6 @@
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Track;
-import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFileFormat.Type;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
@@ -56,10 +55,10 @@
private static final AudioFormat format = new AudioFormat(44100, 16, 2,
true, false);
- private static AudioFileFormat getAudioFileFormat(final Sequence seq) {
+ private static StandardFileFormat getAudioFileFormat(final Sequence seq) {
long totallen = seq.getMicrosecondLength() / 1000000;
long len = (long) (format.getFrameRate() * (totallen + 4));
- return new AudioFileFormat(MIDI, format, (int) len);
+ return new StandardFileFormat(MIDI, format, len);
}
private AudioInputStream getAudioInputStream(final Sequence seq)
@@ -140,7 +139,7 @@
}
@Override
- AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
try {
return getAudioFileFormat(MidiSystem.getSequence(stream));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardFileFormat.java Wed May 04 01:03:46 2016 +0300
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.media.sound;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * An instance of the {@code StandardFileFormat} describes the file's length in
+ * bytes and the length in sample frames as longs. This will provide an
+ * additional precision unlike the {@code AudioFileFormat}.
+ */
+class StandardFileFormat extends AudioFileFormat {
+
+ /**
+ * File length in bytes stored as long.
+ */
+ private final long byteLength;
+
+ /**
+ * Audio data length in sample frames stored as long.
+ */
+ private final long frameLength;
+
+ /**
+ * Constructs {@code StandardFileFormat} object.
+ *
+ * @param type the type of the audio file
+ * @param format the format of the audio data contained in the file
+ * @param frameLength the audio data length in sample frames, or
+ * {@code AudioSystem.NOT_SPECIFIED}
+ */
+ StandardFileFormat(final Type type, final AudioFormat format,
+ final long frameLength) {
+ this(type, AudioSystem.NOT_SPECIFIED, format, frameLength);
+ }
+
+ /**
+ * Constructs {@code StandardFileFormat} object.
+ *
+ * @param type the type of the audio file
+ * @param byteLength the length of the file in bytes, or
+ * {@code AudioSystem.NOT_SPECIFIED}
+ * @param format the format of the audio data contained in the file
+ * @param frameLength the audio data length in sample frames, or
+ * {@code AudioSystem.NOT_SPECIFIED}
+ */
+ StandardFileFormat(final Type type, final long byteLength,
+ final AudioFormat format, final long frameLength) {
+ super(type, clip(byteLength), format, clip(frameLength));
+ this.byteLength = byteLength;
+ this.frameLength = frameLength;
+ }
+
+ /**
+ * Replaces the passed value to {@code AudioSystem.NOT_SPECIFIED} if the
+ * value is greater than {@code Integer.MAX_VALUE}.
+ *
+ * @param value which should be clipped
+ * @return the clipped value
+ */
+ private static int clip(final long value) {
+ if (value > Integer.MAX_VALUE) {
+ return AudioSystem.NOT_SPECIFIED;
+ }
+ return (int) value;
+ }
+
+ /**
+ * Obtains the length of the audio data contained in the file, expressed in
+ * sample frames. The long precision is used.
+ *
+ * @return the number of sample frames of audio data in the file
+ * @see AudioSystem#NOT_SPECIFIED
+ */
+ public final long getLongFrameLength() {
+ return frameLength;
+ }
+
+ /**
+ * Obtains the size in bytes of the entire audio file (not just its audio
+ * data). The long precision is used.
+ *
+ * @return the audio file length in bytes
+ * @see AudioSystem#NOT_SPECIFIED
+ */
+ public final long getLongByteLength() {
+ return byteLength;
+ }
+}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. 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
@@ -47,7 +47,7 @@
abstract class SunFileReader extends AudioFileReader {
@Override
- public final AudioFileFormat getAudioFileFormat(final InputStream stream)
+ public final StandardFileFormat getAudioFileFormat(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
stream.mark(200); // The biggest value which was historically used
try {
@@ -87,11 +87,11 @@
throws UnsupportedAudioFileException, IOException {
stream.mark(200); // The biggest value which was historically used
try {
- final AudioFileFormat fileFormat = getAudioFileFormatImpl(stream);
+ final StandardFileFormat format = getAudioFileFormatImpl(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the audio data, so return an AudioInputStream
- return new AudioInputStream(stream, fileFormat.getFormat(),
- fileFormat.getFrameLength());
+ return new AudioInputStream(stream, format.getFormat(),
+ format.getLongFrameLength());
} catch (UnsupportedAudioFileException | EOFException ignored) {
// stream is unsupported or the header is less than was expected
stream.reset();
@@ -140,7 +140,7 @@
* UnsupportedAudioFileException if the header is less than was
* expected
*/
- abstract AudioFileFormat getAudioFileFormatImpl(InputStream stream)
+ abstract StandardFileFormat getAudioFileFormatImpl(InputStream stream)
throws UnsupportedAudioFileException, IOException;
// HELPER METHODS
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -34,7 +34,6 @@
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
-import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
@@ -167,7 +166,7 @@
}
@Override
- AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
RIFFReader riffiterator = new RIFFReader(stream);
@@ -249,19 +248,17 @@
} else {
throw new UnsupportedAudioFileException();
}
- long frameLength = dataSize / audioformat.getFrameSize();
- if (frameLength > Integer.MAX_VALUE) {
- frameLength = AudioSystem.NOT_SPECIFIED;
- }
- return new AudioFileFormat(AudioFileFormat.Type.WAVE, audioformat,
- (int) frameLength);
+ return new StandardFileFormat(AudioFileFormat.Type.WAVE, audioformat,
+ dataSize / audioformat.getFrameSize());
}
@Override
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
- final AudioFileFormat format = getAudioFileFormat(stream);
+ final StandardFileFormat format = getAudioFileFormat(stream);
+ final AudioFormat af = format.getFormat();
+ final long length = format.getLongFrameLength();
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
@@ -269,8 +266,6 @@
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
- final AudioFormat af = format.getFormat();
- final long length = chunk.getSize() / af.getFrameSize();
return new AudioInputStream(chunk, af, length);
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java Wed May 04 01:03:46 2016 +0300
@@ -33,7 +33,7 @@
*
* @author Jan Borgersen
*/
-final class WaveFileFormat extends AudioFileFormat {
+final class WaveFileFormat extends StandardFileFormat {
/**
* Wave format type.
@@ -73,9 +73,9 @@
static final int WAVE_FORMAT_SX7383 = 0x1C07;
static final int WAVE_FORMAT_EXTENSIBLE= 0xFFFE;
- WaveFileFormat(AudioFileFormat.Type type, int lengthInBytes, AudioFormat format, int lengthInFrames) {
-
- super(type,lengthInBytes,format,lengthInFrames);
+ WaveFileFormat(final AudioFileFormat.Type type, final long byteLength,
+ final AudioFormat format, final long frameLength) {
+ super(type, byteLength, format, frameLength);
AudioFormat.Encoding encoding = format.getEncoding();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. 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
@@ -45,7 +45,7 @@
public final class WaveFileReader extends SunFileReader {
@Override
- AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
// assumes sream is rewound
@@ -64,9 +64,9 @@
DataInputStream dis = new DataInputStream( stream );
int magic = dis.readInt();
- int fileLength = rllong(dis);
+ long /* unsigned int */ fileLength = rllong(dis) & 0xffffffffL;
int waveMagic = dis.readInt();
- int totallength;
+ long totallength;
if (fileLength <= 0) {
fileLength = AudioSystem.NOT_SPECIFIED;
totallength = AudioSystem.NOT_SPECIFIED;
@@ -186,19 +186,18 @@
}
}
// this is the length of the data chunk
- int dataLength = rllong(dis); nread += 4;
+ long /* unsigned int */ dataLength = rllong(dis) & 0xffffffffL; nread += 4;
// now build the new AudioFileFormat and return
-
+ final int frameSize = calculatePCMFrameSize(sampleSizeInBits, channels);
AudioFormat format = new AudioFormat(encoding,
(float)sampleRate,
sampleSizeInBits, channels,
- calculatePCMFrameSize(sampleSizeInBits, channels),
+ frameSize,
(float)sampleRate, false);
- return new WaveFileFormat(AudioFileFormat.Type.WAVE,
- totallength,
- format,
- dataLength / format.getFrameSize());
+ long frameLength = dataLength / format.getFrameSize();
+ return new WaveFileFormat(AudioFileFormat.Type.WAVE, totallength,
+ format, frameLength);
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java Wed May 04 01:03:46 2016 +0300
@@ -32,7 +32,6 @@
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
-import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
@@ -43,7 +42,7 @@
public final class WaveFloatFileReader extends SunFileReader {
@Override
- AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
+ StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
RIFFReader riffiterator = new RIFFReader(stream);
@@ -88,20 +87,17 @@
AudioFormat audioformat = new AudioFormat(
Encoding.PCM_FLOAT, samplerate, bits, channels,
framesize, samplerate, false);
- long frameLength = dataSize / audioformat.getFrameSize();
- if (frameLength > Integer.MAX_VALUE) {
- frameLength = AudioSystem.NOT_SPECIFIED;
- }
-
- return new AudioFileFormat(AudioFileFormat.Type.WAVE, audioformat,
- (int) frameLength);
+ return new StandardFileFormat(AudioFileFormat.Type.WAVE, audioformat,
+ dataSize / audioformat.getFrameSize());
}
@Override
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
- final AudioFileFormat format = getAudioFileFormat(stream);
+ final StandardFileFormat format = getAudioFileFormat(stream);
+ final AudioFormat af = format.getFormat();
+ final long length = format.getLongFrameLength();
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
@@ -109,8 +105,6 @@
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
- final AudioFormat af = format.getFormat();
- final long length = chunk.getSize() / af.getFrameSize();
return new AudioInputStream(chunk, af, length);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAiffFiles.java Wed May 04 01:03:46 2016 +0300
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.
+ *
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 6729836
+ */
+public final class RecognizeHugeAiffFiles {
+
+ /**
+ * The maximum number of sample frames per AIFF specification.
+ */
+ private static final /* unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;
+
+ /**
+ * The supported aiff sample size in bits.
+ */
+ private static final byte[] aiffBits = {
+ 1, 2, 4, 8, 11, 16, 20, 24, 27, 32
+ };
+
+ /**
+ * The list of supported sample rates.
+ */
+ private static final int[] sampleRates = {
+ 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,
+ 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,
+ 5644800, Integer.MAX_VALUE
+ };
+
+ /**
+ * The list of supported channels.
+ */
+ private static final int[] channels = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ };
+
+ /**
+ * The list of supported number of frames.
+ * <p>
+ * The {@code MAX_UNSIGNED_INT} is a maximum.
+ */
+ private static final long[] numberOfFrames = {
+ 0, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,
+ (long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT
+ };
+
+ public static void main(final String[] args) throws Exception {
+ for (final byte bits : aiffBits) {
+ for (final int sampleRate : sampleRates) {
+ for (final int channel : channels) {
+ for (final long dataSize : numberOfFrames) {
+ testAFF(bits, sampleRate, channel, dataSize);
+ testAIS(bits, sampleRate, channel, dataSize);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests the {@code AudioFileFormat} fetched from the fake header.
+ * <p>
+ * Note that the frameLength and byteLength are stored as int which means
+ * that {@code AudioFileFormat} will store the data above {@code MAX_INT} as
+ * NOT_SPECIFIED.
+ */
+ private static void testAFF(final byte bits, final int rate,
+ final int channel, final long frameLength)
+ throws Exception {
+ final byte[] header = createHeader(bits, rate, channel, frameLength);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);
+
+ if (aff.getType() != AudioFileFormat.Type.AIFF) {
+ throw new RuntimeException("Error");
+ }
+
+ if (frameLength <= Integer.MAX_VALUE) {
+ if (aff.getFrameLength() != frameLength) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ } else {
+ if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
+ System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ }
+ validateFormat(bits, rate, channel, aff.getFormat());
+ }
+
+ /**
+ * Tests the {@code AudioInputStream} fetched from the fake header.
+ * <p>
+ * Note that the frameLength is stored as long which means that {@code
+ * AudioInputStream} must store all possible data from aiff file.
+ */
+ private static void testAIS(final byte bits, final int rate,
+ final int channel, final long frameLength)
+ throws Exception {
+ final byte[] header = createHeader(bits, rate, channel, frameLength);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);
+ final AudioFormat format = ais.getFormat();
+
+ if (frameLength != ais.getFrameLength()) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + ais.getFrameLength());
+ throw new RuntimeException();
+ }
+ if (ais.available() < 0) {
+ System.err.println("available should be >=0: " + ais.available());
+ throw new RuntimeException();
+ }
+
+ validateFormat(bits, rate, channel, format);
+ }
+
+ /**
+ * Tests that format contains the same data as were provided to the fake
+ * stream.
+ */
+ private static void validateFormat(final byte bits, final int rate,
+ final int channel,
+ final AudioFormat format) {
+
+ if (Float.compare(format.getSampleRate(), rate) != 0) {
+ System.err.println("Expected: " + rate);
+ System.err.println("Actual: " + format.getSampleRate());
+ throw new RuntimeException();
+ }
+ if (format.getChannels() != channel) {
+ System.err.println("Expected: " + channel);
+ System.err.println("Actual: " + format.getChannels());
+ throw new RuntimeException();
+ }
+ int frameSize = ((bits + 7) / 8) * channel;
+ if (format.getFrameSize() != frameSize) {
+ System.out.println("Expected: " + frameSize);
+ System.err.println("Actual: " + format.getFrameSize());
+ throw new RuntimeException();
+ }
+ }
+
+ private static final int DOUBLE_MANTISSA_LENGTH = 52;
+ private static final int DOUBLE_EXPONENT_LENGTH = 11;
+ private static final long DOUBLE_SIGN_MASK = 0x8000000000000000L;
+ private static final long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L;
+ private static final long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL;
+ private static final int DOUBLE_EXPONENT_OFFSET = 1023;
+
+ private static final int EXTENDED_EXPONENT_OFFSET = 16383;
+ private static final int EXTENDED_MANTISSA_LENGTH = 63;
+ private static final int EXTENDED_EXPONENT_LENGTH = 15;
+ private static final long EXTENDED_INTEGER_MASK = 0x8000000000000000L;
+
+ /**
+ * Creates the custom header of the AIFF file. It is expected that all
+ * passed data are supported.
+ */
+ private static byte[] createHeader(final byte bits, final int rate,
+ final int channel, final long frameLength) {
+ long doubleBits = Double.doubleToLongBits(rate);
+
+ long sign = (doubleBits & DOUBLE_SIGN_MASK)
+ >> (DOUBLE_EXPONENT_LENGTH + DOUBLE_MANTISSA_LENGTH);
+ long doubleExponent = (doubleBits & DOUBLE_EXPONENT_MASK)
+ >> DOUBLE_MANTISSA_LENGTH;
+ long doubleMantissa = doubleBits & DOUBLE_MANTISSA_MASK;
+
+ long extendedExponent = doubleExponent - DOUBLE_EXPONENT_OFFSET
+ + EXTENDED_EXPONENT_OFFSET;
+ long extendedMantissa = doubleMantissa
+ << (EXTENDED_MANTISSA_LENGTH - DOUBLE_MANTISSA_LENGTH);
+ long extendedSign = sign << EXTENDED_EXPONENT_LENGTH;
+ short extendedBits79To64 = (short) (extendedSign | extendedExponent);
+ long extendedBits63To0 = EXTENDED_INTEGER_MASK | extendedMantissa;
+
+ return new byte[]{
+ // AIFF_MAGIC
+ 0x46, 0x4f, 0x52, 0x4d,
+ // fileLength (will use the number of frames for testing)
+ (byte) (frameLength >> 24), (byte) (frameLength >> 16),
+ (byte) (frameLength >> 8), (byte) frameLength,
+ // form aiff
+ 0x41, 0x49, 0x46, 0x46,
+ // COMM_MAGIC
+ 0x43, 0x4f, 0x4d, 0x4d,
+ // comm chunk size
+ 0, 0, 0, 18,
+ // channels
+ (byte) (channel >> 8),(byte) channel,
+ // numSampleFrames
+ (byte) (frameLength >> 24), (byte) (frameLength >> 16),
+ (byte) (frameLength >> 8), (byte) (frameLength),
+ // samplesize
+ (byte) (bits >> 8),(byte) (bits),
+ // samplerate
+ (byte) (extendedBits79To64 >> 8),
+ (byte) extendedBits79To64,
+ (byte) (extendedBits63To0 >> 56),
+ (byte) (extendedBits63To0 >> 48),
+ (byte) (extendedBits63To0 >> 40),
+ (byte) (extendedBits63To0 >> 32), (byte) (extendedBits63To0 >> 24),
+ (byte) (extendedBits63To0 >> 16), (byte) (extendedBits63To0 >> 8),
+ (byte) extendedBits63To0,
+ // SND_MAGIC
+ 0x53, 0x53, 0x4e, 0x44,
+ // data chunk size
+ 0, 0, 0, 0,
+ // dataOffset
+ 0, 0, 0, 0,
+ // blocksize
+ 0, 0, 0, 0,
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAuFiles.java Wed May 04 01:03:46 2016 +0300
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.
+ *
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 6729836
+ */
+public final class RecognizeHugeAuFiles {
+
+ /**
+ * The size of the header's data.
+ */
+ private static final byte AU_HEADER = 44;
+
+ /**
+ * This value should be used if the size in bytes is unknown.
+ */
+ private static final /* unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;
+
+ /**
+ * The list of supported au formats and sample size in bits per format.
+ */
+ private static final byte[][] auTypeBits = {
+ {1, 8}, {2, 8}, {3, 16}, {4, 24}, {5, 32}, {6, 32}, {27, 8}
+ };
+
+ /**
+ * The list of supported sample rates(stored as unsigned int).
+ */
+ private static final int[] sampleRates = {
+ 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,
+ 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,
+ 5644800, Integer.MAX_VALUE
+ };
+
+ /**
+ * The list of supported channels (stored as unsigned int).
+ */
+ private static final int[] channels = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ };
+
+ /**
+ * The list of supported size of data (stored as unsigned int).
+ * <p>
+ * The {@code MAX_UNSIGNED_INT} used if the size in bytes is unknown.
+ */
+ private static final long[] dataSizes = {
+ 0, 1, 2, 3, Integer.MAX_VALUE - AU_HEADER, Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE, (long) Integer.MAX_VALUE + 1,
+ (long) Integer.MAX_VALUE + AU_HEADER, MAX_UNSIGNED_INT - AU_HEADER,
+ MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT
+ };
+
+ public static void main(final String[] args) throws Exception {
+ for (final byte[] type : auTypeBits) {
+ for (final int sampleRate : sampleRates) {
+ for (final int channel : channels) {
+ for (final long dataSize : dataSizes) {
+ testAFF(type, sampleRate, channel, dataSize);
+ testAIS(type, sampleRate, channel, dataSize);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests the {@code AudioFileFormat} fetched from the fake header.
+ * <p>
+ * Note that the frameLength and byteLength are stored as int which means
+ * that {@code AudioFileFormat} will store the data above {@code MAX_INT}
+ * as NOT_SPECIFIED.
+ */
+ private static void testAFF(final byte[] type, final int rate,
+ final int channel, final long size)
+ throws Exception {
+ final byte[] header = createHeader(type, rate, channel, size);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);
+ final AudioFormat format = aff.getFormat();
+
+ if (aff.getType() != AudioFileFormat.Type.AU) {
+ throw new RuntimeException("Error");
+ }
+
+ final long frameLength = size / format.getFrameSize();
+ if (size != MAX_UNSIGNED_INT && frameLength <= Integer.MAX_VALUE) {
+ if (aff.getFrameLength() != frameLength) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ } else {
+ if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
+ System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ }
+
+ final long byteLength = size + AU_HEADER;
+ if (byteLength <= Integer.MAX_VALUE) {
+ if (aff.getByteLength() != byteLength) {
+ System.err.println("Expected: " + byteLength);
+ System.err.println("Actual: " + aff.getByteLength());
+ throw new RuntimeException();
+ }
+ } else {
+ if (aff.getByteLength() != AudioSystem.NOT_SPECIFIED) {
+ System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
+ System.err.println("Actual: " + aff.getByteLength());
+ throw new RuntimeException();
+ }
+ }
+ validateFormat(type[1], rate, channel, aff.getFormat());
+ }
+
+ /**
+ * Tests the {@code AudioInputStream} fetched from the fake header.
+ * <p>
+ * Note that the frameLength is stored as long which means
+ * that {@code AudioInputStream} must store all possible data from au file.
+ */
+ private static void testAIS(final byte[] type, final int rate,
+ final int channel, final long size)
+ throws Exception {
+ final byte[] header = createHeader(type, rate, channel, size);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);
+ final AudioFormat format = ais.getFormat();
+ final long frameLength = size / format.getFrameSize();
+ if (size != MAX_UNSIGNED_INT) {
+ if (frameLength != ais.getFrameLength()) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + ais.getFrameLength());
+ throw new RuntimeException();
+ }
+ } else {
+ if (ais.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
+ System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
+ System.err.println("Actual: " + ais.getFrameLength());
+ throw new RuntimeException();
+ }
+ }
+ if (ais.available() < 0) {
+ System.err.println("available should be >=0: " + ais.available());
+ throw new RuntimeException();
+ }
+ validateFormat(type[1], rate, channel, format);
+ }
+
+ /**
+ * Tests that format contains the same data as were provided to the fake
+ * stream.
+ */
+ private static void validateFormat(final byte bits, final int rate,
+ final int channel,
+ final AudioFormat format) {
+
+ if (Float.compare(format.getSampleRate(), rate) != 0) {
+ System.out.println("Expected: " + rate);
+ System.out.println("Actual: " + format.getSampleRate());
+ throw new RuntimeException();
+ }
+ if (format.getChannels() != channel) {
+ System.out.println("Expected: " + channel);
+ System.out.println("Actual: " + format.getChannels());
+ throw new RuntimeException();
+ }
+ int frameSize = ((bits + 7) / 8) * channel;
+ if (format.getFrameSize() != frameSize) {
+ System.out.println("Expected: " + frameSize);
+ System.out.println("Actual: " + format.getFrameSize());
+ throw new RuntimeException();
+ }
+ }
+
+ /**
+ * Creates the custom header of the AU file. It is expected that all passed
+ * data are supported.
+ */
+ private static byte[] createHeader(final byte[] type, final int rate,
+ final int channel, final long size) {
+ return new byte[]{
+ // AU_SUN_MAGIC
+ 0x2e, 0x73, 0x6e, 0x64,
+ // headerSize
+ 0, 0, 0, AU_HEADER,
+ // dataSize
+ (byte) (size >> 24), (byte) (size >> 16), (byte) (size >> 8),
+ (byte) size,
+ // encoding
+ 0, 0, 0, type[0],
+ // sampleRate
+ (byte) (rate >> 24), (byte) (rate >> 16), (byte) (rate >> 8),
+ (byte) (rate),
+ // channels
+ (byte) (channel >> 24), (byte) (channel >> 16),
+ (byte) (channel >> 8), (byte) (channel),
+ // data
+ 0, 0, 0, 0, 0, 0
+ };
+ }
+}
--- a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java Tue May 03 12:25:20 2016 -0700
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.java Wed May 04 01:03:46 2016 +0300
@@ -125,7 +125,7 @@
* Tests the {@code AudioInputStream} fetched from the fake header.
* <p>
* Note that the frameLength is stored as long which means that {@code
- * AudioInputStream} must store all possible data from au file.
+ * AudioInputStream} must store all possible data from wave file.
*/
private static void testAIS(final int[] type, final int rate,
final int channel, final long size)
@@ -166,8 +166,9 @@
System.err.println("Actual: " + format.getChannels());
throw new RuntimeException();
}
- if (format.getFrameSize() != ((bits + 7) / 8) * channel) {
- System.err.println("Expected: " + (bits * channel + 1) / 8);
+ int frameSize = ((bits + 7) / 8) * channel;
+ if (format.getFrameSize() != frameSize) {
+ System.err.println("Expected: " + frameSize);
System.err.println("Actual: " + format.getFrameSize());
throw new RuntimeException();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFiles.java Wed May 04 01:03:46 2016 +0300
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.
+ *
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 8132782 6729836
+ */
+public final class RecognizeHugeWaveFiles {
+
+ /**
+ * The maximum size in bytes per WAVE specification.
+ */
+ private static final /*unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;
+
+ /**
+ * The supported wave pcm_float format and sample size in bits.
+ */
+ private static final byte[][] waveTypeBits = {
+ {0x0001/*WAVE_FORMAT_PCM*/,1},
+ {0x0001/*WAVE_FORMAT_PCM*/,2},
+ {0x0001/*WAVE_FORMAT_PCM*/,4},
+ {0x0001/*WAVE_FORMAT_PCM*/,8},
+ {0x0001/*WAVE_FORMAT_PCM*/,16},
+ {0x0001/*WAVE_FORMAT_PCM*/,20},
+ {0x0001/*WAVE_FORMAT_PCM*/,24},
+ {0x0001/*WAVE_FORMAT_PCM*/,32},
+ {0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32},
+ {0x0006/*WAVE_FORMAT_ALAW*/, 8},
+ {0x0007/*WAVE_FORMAT_MULAW*/, 8}
+ };
+
+ /**
+ * The list of supported sample rates(stored as unsigned int).
+ */
+ private static final int[] sampleRates = {
+ 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,
+ 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,
+ 5644800, Integer.MAX_VALUE
+ };
+
+ /**
+ * The list of supported channels (stored as unsigned int).
+ */
+ private static final int[] channels = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ };
+
+ /**
+ * The list of supported size of data (stored as unsigned int).
+ * <p>
+ * The {@code MAX_UNSIGNED_INT} is a maximum size.
+ */
+ private static final long[] dataSizes = {
+ 0, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,
+ (long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT
+ };
+
+ public static void main(final String[] args) throws Exception {
+ for (final byte[] type : waveTypeBits) {
+ for (final int sampleRate : sampleRates) {
+ for (final int channel : channels) {
+ for (final long dataSize : dataSizes) {
+ testAFF(type, sampleRate, channel, dataSize);
+ testAIS(type, sampleRate, channel, dataSize);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests the {@code AudioFileFormat} fetched from the fake header.
+ * <p>
+ * Note that the frameLength and byteLength are stored as int which means
+ * that {@code AudioFileFormat} will store the data above {@code MAX_INT} as
+ * NOT_SPECIFIED.
+ */
+ private static void testAFF(final byte[] type, final int rate,
+ final int channel, final long size)
+ throws Exception {
+ final byte[] header = createHeader(type, rate, channel, size);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);
+ final AudioFormat format = aff.getFormat();
+
+ if (aff.getType() != AudioFileFormat.Type.WAVE) {
+ throw new RuntimeException("Error");
+ }
+
+ final long frameLength = size / format.getFrameSize();
+ if (frameLength <= Integer.MAX_VALUE) {
+ if (aff.getFrameLength() != frameLength) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ } else {
+ if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
+ System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
+ System.err.println("Actual: " + aff.getFrameLength());
+ throw new RuntimeException();
+ }
+ }
+ validateFormat(type[1], rate, channel, aff.getFormat());
+ }
+
+ /**
+ * Tests the {@code AudioInputStream} fetched from the fake header.
+ * <p>
+ * Note that the frameLength is stored as long which means that {@code
+ * AudioInputStream} must store all possible data from wave file.
+ */
+ private static void testAIS(final byte[] type, final int rate,
+ final int channel, final long size)
+ throws Exception {
+ final byte[] header = createHeader(type, rate, channel, size);
+ final ByteArrayInputStream fake = new ByteArrayInputStream(header);
+ final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);
+ final AudioFormat format = ais.getFormat();
+ final long frameLength = size / format.getFrameSize();
+ if (frameLength != ais.getFrameLength()) {
+ System.err.println("Expected: " + frameLength);
+ System.err.println("Actual: " + ais.getFrameLength());
+ throw new RuntimeException();
+ }
+ if (ais.available() < 0) {
+ System.err.println("available should be >=0: " + ais.available());
+ throw new RuntimeException();
+ }
+
+ validateFormat(type[1], rate, channel, format);
+ }
+
+ /**
+ * Tests that format contains the same data as were provided to the fake
+ * stream.
+ */
+ private static void validateFormat(final byte bits, final int rate,
+ final int channel,
+ final AudioFormat format) {
+
+ if (Float.compare(format.getSampleRate(), rate) != 0) {
+ System.err.println("Expected: " + rate);
+ System.err.println("Actual: " + format.getSampleRate());
+ throw new RuntimeException();
+ }
+ if (format.getChannels() != channel) {
+ System.err.println("Expected: " + channel);
+ System.err.println("Actual: " + format.getChannels());
+ throw new RuntimeException();
+ }
+ int frameSize = ((bits + 7) / 8) * channel;
+ if (format.getFrameSize() != frameSize) {
+ System.err.println("Expected: " + frameSize);
+ System.err.println("Actual: " + format.getFrameSize());
+ throw new RuntimeException();
+ }
+ }
+
+ /**
+ * Creates the custom header of the WAVE file. It is expected that all
+ * passed data are supported.
+ */
+ private static byte[] createHeader(final byte[] type, final int rate,
+ final int channel, final long size) {
+ final int frameSize = ((type[1] + 7) / 8) * channel;
+ return new byte[]{
+ // RIFF_MAGIC
+ 0x52, 0x49, 0x46, 0x46,
+ // fileLength
+ -1, -1, -1, -1,
+ // waveMagic
+ 0x57, 0x41, 0x56, 0x45,
+ // FMT_MAGIC
+ 0x66, 0x6d, 0x74, 0x20,
+ // size
+ 16, 0, 0, 0,
+ // wav_type WAVE_FORMAT_IEEE_FLOAT
+ type[0], 0,
+ // channels
+ (byte) (channel), (byte) (channel >> 8),
+ // samplerate
+ (byte) (rate), (byte) (rate >> 8), (byte) (rate >> 16),
+ (byte) (rate >> 24),
+ // framerate
+ 1, 0, 0, 0,
+ // framesize
+ (byte) (frameSize), (byte) (frameSize >> 8),
+ // bits
+ type[1], 0,
+ // DATA_MAGIC
+ 0x64, 0x61, 0x74, 0x61,
+ // data size
+ (byte) (size), (byte) (size >> 8), (byte) (size >> 16),
+ (byte) (size >> 24)
+ // data
+ , 0, 0, 0, 0, 0
+ };
+ }
+}
--- a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveFloatFiles.java Tue May 03 12:25:20 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. 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.
- *
- * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.ByteArrayInputStream;
-
-import javax.sound.sampled.AudioFileFormat;
-import javax.sound.sampled.AudioFormat;
-import javax.sound.sampled.AudioInputStream;
-import javax.sound.sampled.AudioSystem;
-
-/**
- * @test
- * @bug 8132782
- */
-public final class RecognizeHugeWaveFloatFiles {
-
- /**
- * The maximum size in bytes per WAVE specification.
- */
- private static final /*unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;
-
- /**
- * The supported wave pcm_float format and sample size in bits.
- */
- private static final byte[][] waveTypeBits = {
- {0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32}
- };
-
- /**
- * The list of supported sample rates(stored as unsigned int).
- */
- private static final int[] sampleRates = {
- 8000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,
- 50000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,
- 5644800, Integer.MAX_VALUE
- };
-
- /**
- * The list of supported channels (stored as unsigned int).
- */
- private static final int[] channels = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- };
-
- /**
- * The list of supported size of data (stored as unsigned int).
- * <p>
- * The {@code MAX_UNSIGNED_INT} is a maximum size.
- */
- private static final long[] dataSizes = {
- 0, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,
- (long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT
- };
-
- public static void main(final String[] args) throws Exception {
- for (final byte[] type : waveTypeBits) {
- for (final int sampleRate : sampleRates) {
- for (final int channel : channels) {
- for (final long dataSize : dataSizes) {
- testAFF(type, sampleRate, channel, dataSize);
- testAIS(type, sampleRate, channel, dataSize);
- }
- }
- }
- }
- }
-
- /**
- * Tests the {@code AudioFileFormat} fetched from the fake header.
- * <p>
- * Note that the frameLength and byteLength are stored as int which means
- * that {@code AudioFileFormat} will store the data above {@code MAX_INT} as
- * NOT_SPECIFIED.
- */
- private static void testAFF(final byte[] type, final int rate,
- final int channel, final long size)
- throws Exception {
- final byte[] header = createHeader(type, rate, channel, size);
- final ByteArrayInputStream fake = new ByteArrayInputStream(header);
- final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);
- final AudioFormat format = aff.getFormat();
-
- if (aff.getType() != AudioFileFormat.Type.WAVE) {
- throw new RuntimeException("Error");
- }
-
- final long frameLength = size / format.getFrameSize();
- if (frameLength <= Integer.MAX_VALUE) {
- if (aff.getFrameLength() != frameLength) {
- System.err.println("Expected: " + frameLength);
- System.err.println("Actual: " + aff.getFrameLength());
- throw new RuntimeException();
- }
- } else {
- if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
- System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);
- System.err.println("Actual: " + aff.getFrameLength());
- throw new RuntimeException();
- }
- }
- validateFormat(type[1], rate, channel, aff.getFormat());
- }
-
- /**
- * Tests the {@code AudioInputStream} fetched from the fake header.
- * <p>
- * Note that the frameLength is stored as long which means that {@code
- * AudioInputStream} must store all possible data from au file.
- */
- private static void testAIS(final byte[] type, final int rate,
- final int channel, final long size)
- throws Exception {
- final byte[] header = createHeader(type, rate, channel, size);
- final ByteArrayInputStream fake = new ByteArrayInputStream(header);
- final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);
- final AudioFormat format = ais.getFormat();
- final long frameLength = size / format.getFrameSize();
- if (frameLength != ais.getFrameLength()) {
- System.err.println("Expected: " + frameLength);
- System.err.println("Actual: " + ais.getFrameLength());
- throw new RuntimeException();
- }
- if (ais.available() < 0) {
- System.err.println("available should be >=0: " + ais.available());
- throw new RuntimeException();
- }
-
- validateFormat(type[1], rate, channel, format);
- }
-
- /**
- * Tests that format contains the same data as were provided to the fake
- * stream.
- */
- private static void validateFormat(final byte bits, final int rate,
- final int channel,
- final AudioFormat format) {
-
- if (Float.compare(format.getSampleRate(), rate) != 0) {
- System.err.println("Expected: " + rate);
- System.err.println("Actual: " + format.getSampleRate());
- throw new RuntimeException();
- }
- if (format.getChannels() != channel) {
- System.err.println("Expected: " + channel);
- System.err.println("Actual: " + format.getChannels());
- throw new RuntimeException();
- }
- if (format.getFrameSize() != ((bits + 7) / 8) * channel) {
- System.err.println("Expected: " + (bits * channel + 1) / 8);
- System.err.println("Actual: " + format.getFrameSize());
- throw new RuntimeException();
- }
- }
-
- /**
- * Creates the custom header of the WAVE file. It is expected that all
- * passed data are supported.
- */
- private static byte[] createHeader(final byte[] type, final int rate,
- final int channel, final long size) {
- final int frameSize = ((type[1] + 7) / 8) * channel;
- return new byte[]{
- // RIFF_MAGIC
- 0x52, 0x49, 0x46, 0x46,
- // fileLength
- -1, -1, -1, -1,
- // waveMagic
- 0x57, 0x41, 0x56, 0x45,
- // FMT_MAGIC
- 0x66, 0x6d, 0x74, 0x20,
- // size
- 16, 0, 0, 0,
- // wav_type WAVE_FORMAT_IEEE_FLOAT
- type[0], 0,
- // channels
- (byte) (channel), (byte) (channel >> 8),
- // samplerate
- (byte) (rate), (byte) (rate >> 8), (byte) (rate >> 16),
- (byte) (rate >> 24),
- // framerate
- 1, 0, 0, 0,
- // framesize
- (byte) (frameSize), (byte) (frameSize >> 8),
- // bits
- type[1], 0,
- // DATA_MAGIC
- 0x64, 0x61, 0x74, 0x61,
- // data size
- (byte) (size), (byte) (size >> 8), (byte) (size >> 16),
- (byte) (size >> 24)
- // data
- , 0, 0, 0, 0, 0
- };
- }
-}