Path: blob/master/test/jdk/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeAiffFiles.java
40527 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.ByteArrayInputStream;2425import javax.sound.sampled.AudioFileFormat;26import javax.sound.sampled.AudioFormat;27import javax.sound.sampled.AudioInputStream;28import javax.sound.sampled.AudioSystem;2930/**31* @test32* @bug 672983633*/34public final class RecognizeHugeAiffFiles {3536/**37* The maximum number of sample frames per AIFF specification.38*/39private static final /* unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;4041/**42* The supported aiff sample size in bits.43*/44private static final byte[] aiffBits = {451, 2, 4, 8, 11, 16, 20, 24, 27, 3246};4748/**49* The list of supported sample rates.50*/51private static final int[] sampleRates = {528000, 11025, 16000, 22050, 32000, 37800, 44056, 44100, 47250, 48000,5350000, 50400, 88200, 96000, 176400, 192000, 352800, 2822400,545644800, Integer.MAX_VALUE55};5657/**58* The list of supported channels.59*/60private static final int[] channels = {611, 2, 3, 4, 5, 6, 7, 8, 9, 1062};6364/**65* The list of supported number of frames.66* <p>67* The {@code MAX_UNSIGNED_INT} is a maximum.68*/69private static final long[] numberOfFrames = {700, 1, 2, 3, Integer.MAX_VALUE - 1, Integer.MAX_VALUE,71(long) Integer.MAX_VALUE + 1, MAX_UNSIGNED_INT - 1, MAX_UNSIGNED_INT72};7374public static void main(final String[] args) throws Exception {75for (final byte bits : aiffBits) {76for (final int sampleRate : sampleRates) {77for (final int channel : channels) {78for (final long dataSize : numberOfFrames) {79testAFF(bits, sampleRate, channel, dataSize);80testAIS(bits, sampleRate, channel, dataSize);81}82}83}84}85}8687/**88* Tests the {@code AudioFileFormat} fetched from the fake header.89* <p>90* Note that the frameLength and byteLength are stored as int which means91* that {@code AudioFileFormat} will store the data above {@code MAX_INT} as92* NOT_SPECIFIED.93*/94private static void testAFF(final byte bits, final int rate,95final int channel, final long frameLength)96throws Exception {97final byte[] header = createHeader(bits, rate, channel, frameLength);98final ByteArrayInputStream fake = new ByteArrayInputStream(header);99final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);100101if (aff.getType() != AudioFileFormat.Type.AIFF) {102throw new RuntimeException("Error");103}104105if (frameLength <= Integer.MAX_VALUE) {106if (aff.getFrameLength() != frameLength) {107System.err.println("Expected: " + frameLength);108System.err.println("Actual: " + aff.getFrameLength());109throw new RuntimeException();110}111} else {112if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {113System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);114System.err.println("Actual: " + aff.getFrameLength());115throw new RuntimeException();116}117}118validateFormat(bits, rate, channel, aff.getFormat());119}120121/**122* Tests the {@code AudioInputStream} fetched from the fake header.123* <p>124* Note that the frameLength is stored as long which means that {@code125* AudioInputStream} must store all possible data from aiff file.126*/127private static void testAIS(final byte bits, final int rate,128final int channel, final long frameLength)129throws Exception {130final byte[] header = createHeader(bits, rate, channel, frameLength);131final ByteArrayInputStream fake = new ByteArrayInputStream(header);132final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);133final AudioFormat format = ais.getFormat();134135if (frameLength != ais.getFrameLength()) {136System.err.println("Expected: " + frameLength);137System.err.println("Actual: " + ais.getFrameLength());138throw new RuntimeException();139}140if (ais.available() < 0) {141System.err.println("available should be >=0: " + ais.available());142throw new RuntimeException();143}144145validateFormat(bits, rate, channel, format);146}147148/**149* Tests that format contains the same data as were provided to the fake150* stream.151*/152private static void validateFormat(final byte bits, final int rate,153final int channel,154final AudioFormat format) {155156if (Float.compare(format.getSampleRate(), rate) != 0) {157System.err.println("Expected: " + rate);158System.err.println("Actual: " + format.getSampleRate());159throw new RuntimeException();160}161if (format.getChannels() != channel) {162System.err.println("Expected: " + channel);163System.err.println("Actual: " + format.getChannels());164throw new RuntimeException();165}166int frameSize = ((bits + 7) / 8) * channel;167if (format.getFrameSize() != frameSize) {168System.out.println("Expected: " + frameSize);169System.err.println("Actual: " + format.getFrameSize());170throw new RuntimeException();171}172}173174private static final int DOUBLE_MANTISSA_LENGTH = 52;175private static final int DOUBLE_EXPONENT_LENGTH = 11;176private static final long DOUBLE_SIGN_MASK = 0x8000000000000000L;177private static final long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L;178private static final long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL;179private static final int DOUBLE_EXPONENT_OFFSET = 1023;180181private static final int EXTENDED_EXPONENT_OFFSET = 16383;182private static final int EXTENDED_MANTISSA_LENGTH = 63;183private static final int EXTENDED_EXPONENT_LENGTH = 15;184private static final long EXTENDED_INTEGER_MASK = 0x8000000000000000L;185186/**187* Creates the custom header of the AIFF file. It is expected that all188* passed data are supported.189*/190private static byte[] createHeader(final byte bits, final int rate,191final int channel, final long frameLength) {192long doubleBits = Double.doubleToLongBits(rate);193194long sign = (doubleBits & DOUBLE_SIGN_MASK)195>> (DOUBLE_EXPONENT_LENGTH + DOUBLE_MANTISSA_LENGTH);196long doubleExponent = (doubleBits & DOUBLE_EXPONENT_MASK)197>> DOUBLE_MANTISSA_LENGTH;198long doubleMantissa = doubleBits & DOUBLE_MANTISSA_MASK;199200long extendedExponent = doubleExponent - DOUBLE_EXPONENT_OFFSET201+ EXTENDED_EXPONENT_OFFSET;202long extendedMantissa = doubleMantissa203<< (EXTENDED_MANTISSA_LENGTH - DOUBLE_MANTISSA_LENGTH);204long extendedSign = sign << EXTENDED_EXPONENT_LENGTH;205short extendedBits79To64 = (short) (extendedSign | extendedExponent);206long extendedBits63To0 = EXTENDED_INTEGER_MASK | extendedMantissa;207208return new byte[]{209// AIFF_MAGIC2100x46, 0x4f, 0x52, 0x4d,211// fileLength (will use the number of frames for testing)212(byte) (frameLength >> 24), (byte) (frameLength >> 16),213(byte) (frameLength >> 8), (byte) frameLength,214// form aiff2150x41, 0x49, 0x46, 0x46,216// COMM_MAGIC2170x43, 0x4f, 0x4d, 0x4d,218// comm chunk size2190, 0, 0, 18,220// channels221(byte) (channel >> 8),(byte) channel,222// numSampleFrames223(byte) (frameLength >> 24), (byte) (frameLength >> 16),224(byte) (frameLength >> 8), (byte) (frameLength),225// samplesize226(byte) (bits >> 8),(byte) (bits),227// samplerate228(byte) (extendedBits79To64 >> 8),229(byte) extendedBits79To64,230(byte) (extendedBits63To0 >> 56),231(byte) (extendedBits63To0 >> 48),232(byte) (extendedBits63To0 >> 40),233(byte) (extendedBits63To0 >> 32), (byte) (extendedBits63To0 >> 24),234(byte) (extendedBits63To0 >> 16), (byte) (extendedBits63To0 >> 8),235(byte) extendedBits63To0,236// SND_MAGIC2370x53, 0x53, 0x4e, 0x44,238// data chunk size2390, 0, 0, 0,240// dataOffset2410, 0, 0, 0,242// blocksize2430, 0, 0, 0,244};245}246}247248249