6729836: JavaSound treats large file sizes as negative and cannot read or skip
Reviewed-by: prr
This commit is contained in:
parent
4ff0d8b26f
commit
214029ed2b
@ -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 @@ final class AiffFileFormat extends AudioFileFormat {
|
||||
/** 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);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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 @@ public final class AiffFileReader extends SunFileReader {
|
||||
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 @@ public final class AiffFileReader extends SunFileReader {
|
||||
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) {
|
||||
|
@ -33,7 +33,7 @@ import javax.sound.sampled.AudioFormat;
|
||||
*
|
||||
* @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 @@ final class AuFileFormat extends AudioFileFormat {
|
||||
|
||||
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();
|
||||
|
||||
|
@ -29,7 +29,6 @@ import java.io.DataInputStream;
|
||||
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 @@ import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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 @@ public final class AuFileReader extends SunFileReader {
|
||||
}
|
||||
|
||||
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 @@ public final class AuFileReader extends SunFileReader {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -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.MidiUnavailableException;
|
||||
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 @@ public final class SoftMidiAudioFileReader extends SunFileReader {
|
||||
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 @@ public final class SoftMidiAudioFileReader extends SunFileReader {
|
||||
}
|
||||
|
||||
@Override
|
||||
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
|
||||
StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
|
||||
throws UnsupportedAudioFileException, IOException {
|
||||
try {
|
||||
return getAudioFileFormat(MidiSystem.getSequence(stream));
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 @@ import javax.sound.sampled.spi.AudioFileReader;
|
||||
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 @@ abstract class SunFileReader extends AudioFileReader {
|
||||
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 @@ abstract class SunFileReader extends AudioFileReader {
|
||||
* UnsupportedAudioFileException if the header is less than was
|
||||
* expected
|
||||
*/
|
||||
abstract AudioFileFormat getAudioFileFormatImpl(InputStream stream)
|
||||
abstract StandardFileFormat getAudioFileFormatImpl(InputStream stream)
|
||||
throws UnsupportedAudioFileException, IOException;
|
||||
|
||||
// HELPER METHODS
|
||||
|
@ -34,7 +34,6 @@ import javax.sound.sampled.AudioFileFormat;
|
||||
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 @@ public final class WaveExtensibleFileReader extends SunFileReader {
|
||||
}
|
||||
|
||||
@Override
|
||||
AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
|
||||
StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
|
||||
throws UnsupportedAudioFileException, IOException {
|
||||
|
||||
RIFFReader riffiterator = new RIFFReader(stream);
|
||||
@ -249,19 +248,17 @@ public final class WaveExtensibleFileReader extends SunFileReader {
|
||||
} 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 @@ public final class WaveExtensibleFileReader extends SunFileReader {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import javax.sound.sampled.AudioFormat;
|
||||
*
|
||||
* @author Jan Borgersen
|
||||
*/
|
||||
final class WaveFileFormat extends AudioFileFormat {
|
||||
final class WaveFileFormat extends StandardFileFormat {
|
||||
|
||||
/**
|
||||
* Wave format type.
|
||||
@ -73,9 +73,9 @@ final class WaveFileFormat extends AudioFileFormat {
|
||||
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();
|
||||
|
||||
|
@ -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 @@ import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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 @@ public final class WaveFileReader extends SunFileReader {
|
||||
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 @@ public final class WaveFileReader extends SunFileReader {
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import javax.sound.sampled.AudioFileFormat;
|
||||
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 @@ import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
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 @@ public final class WaveFloatFileReader extends SunFileReader {
|
||||
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 @@ public final class WaveFloatFileReader extends SunFileReader {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
@ -125,7 +125,7 @@ public final class RecognizeHugeWaveExtFiles {
|
||||
* 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 @@ public final class RecognizeHugeWaveExtFiles {
|
||||
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();
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ import javax.sound.sampled.AudioSystem;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8132782
|
||||
* @bug 8132782 6729836
|
||||
*/
|
||||
public final class RecognizeHugeWaveFloatFiles {
|
||||
public final class RecognizeHugeWaveFiles {
|
||||
|
||||
/**
|
||||
* The maximum size in bytes per WAVE specification.
|
||||
@ -43,7 +43,17 @@ public final class RecognizeHugeWaveFloatFiles {
|
||||
* The supported wave pcm_float format and sample size in bits.
|
||||
*/
|
||||
private static final byte[][] waveTypeBits = {
|
||||
{0x0003/*WAVE_FORMAT_IEEE_FLOAT*/, 32}
|
||||
{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}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -125,7 +135,7 @@ public final class RecognizeHugeWaveFloatFiles {
|
||||
* 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 byte[] type, final int rate,
|
||||
final int channel, final long size)
|
||||
@ -166,8 +176,9 @@ public final class RecognizeHugeWaveFloatFiles {
|
||||
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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user