Path: blob/master/test/jdk/javax/sound/sampled/spi/AudioFileReader/RecognizeHugeWaveExtFiles.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 813278233*/34public final class RecognizeHugeWaveExtFiles {3536/**37* The maximum size in bytes per WAVE specification.38*/39private static final /*unsigned int */ long MAX_UNSIGNED_INT = 0xffffffffL;4041/**42* The supported wave ext format and sample size in bits.43*/44private static final int[][] waveTypeBits = {45{0xFFFE/*WAVE_FORMAT_EXTENSIBLE*/, 8}46};4748/**49* The list of supported sample rates(stored as unsigned int).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 (stored as unsigned int).59*/60private static final int[] channels = {611, 2, 3, 4, 5, 6, 7, 8, 9, 1062};6364/**65* The list of supported size of data (stored as unsigned int).66* <p>67* The {@code MAX_UNSIGNED_INT} is a maximum size.68*/69private static final long[] dataSizes = {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 int[] type : waveTypeBits) {76for (final int sampleRate : sampleRates) {77for (final int channel : channels) {78for (final long dataSize : dataSizes) {79testAFF(type, sampleRate, channel, dataSize);80testAIS(type, 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 int[] type, final int rate,95final int channel, final long size)96throws Exception {97final byte[] header = createHeader(type, rate, channel, size);98final ByteArrayInputStream fake = new ByteArrayInputStream(header);99final AudioFileFormat aff = AudioSystem.getAudioFileFormat(fake);100final AudioFormat format = aff.getFormat();101102if (aff.getType() != AudioFileFormat.Type.WAVE) {103throw new RuntimeException("Error");104}105106final long frameLength = size / format.getFrameSize();107if (frameLength <= Integer.MAX_VALUE) {108if (aff.getFrameLength() != frameLength) {109System.err.println("Expected: " + frameLength);110System.err.println("Actual: " + aff.getFrameLength());111throw new RuntimeException();112}113} else {114if (aff.getFrameLength() != AudioSystem.NOT_SPECIFIED) {115System.err.println("Expected: " + AudioSystem.NOT_SPECIFIED);116System.err.println("Actual: " + aff.getFrameLength());117throw new RuntimeException();118}119}120validateFormat(type[1], rate, channel, aff.getFormat());121}122123/**124* Tests the {@code AudioInputStream} fetched from the fake header.125* <p>126* Note that the frameLength is stored as long which means that {@code127* AudioInputStream} must store all possible data from wave file.128*/129private static void testAIS(final int[] type, final int rate,130final int channel, final long size)131throws Exception {132final byte[] header = createHeader(type, rate, channel, size);133final ByteArrayInputStream fake = new ByteArrayInputStream(header);134final AudioInputStream ais = AudioSystem.getAudioInputStream(fake);135final AudioFormat format = ais.getFormat();136final long frameLength = size / format.getFrameSize();137if (frameLength != ais.getFrameLength()) {138System.err.println("Expected: " + frameLength);139System.err.println("Actual: " + ais.getFrameLength());140throw new RuntimeException();141}142if (ais.available() < 0) {143System.err.println("available should be >=0: " + ais.available());144throw new RuntimeException();145}146147validateFormat(type[1], rate, channel, format);148}149150/**151* Tests that format contains the same data as were provided to the fake152* stream.153*/154private static void validateFormat(final int bits, final int rate,155final int channel,156final AudioFormat format) {157158if (Float.compare(format.getSampleRate(), rate) != 0) {159System.err.println("Expected: " + rate);160System.err.println("Actual: " + format.getSampleRate());161throw new RuntimeException();162}163if (format.getChannels() != channel) {164System.err.println("Expected: " + channel);165System.err.println("Actual: " + format.getChannels());166throw new RuntimeException();167}168int frameSize = ((bits + 7) / 8) * channel;169if (format.getFrameSize() != frameSize) {170System.err.println("Expected: " + frameSize);171System.err.println("Actual: " + format.getFrameSize());172throw new RuntimeException();173}174}175176/**177* Creates the custom header of the WAVE file. It is expected that all178* passed data are supported.179*/180private static byte[] createHeader(final int[] type, final int rate,181final int channel, final long size) {182final int frameSize = ((type[1] + 7) / 8) * channel;183return new byte[]{184// RIFF_MAGIC1850x52, 0x49, 0x46, 0x46,186// fileLength187-1, -1, -1, -1,188// waveMagic1890x57, 0x41, 0x56, 0x45,190// FMT_MAGIC1910x66, 0x6d, 0x74, 0x20,192// size19340, 0, 0, 0,194// wav_type WAVE_FORMAT_EXTENSIBLE195(byte) (type[0]), (byte) (type[0] >> 8),196// channels197(byte) (channel), (byte) (channel >> 8),198// samplerate199(byte) (rate), (byte) (rate >> 8), (byte) (rate >> 16),200(byte) (rate >> 24),201// framerate2021, 0, 0, 0,203// framesize204(byte) (frameSize), (byte) (frameSize >> 8),205// bits206(byte) type[1], 0,207// cbsize20822, 0,209// validBitsPerSample2108, 0,211// channelMask2120, 0, 0, 0,213// SUBTYPE_IEEE_FLOAT214// i12150x3, 0x0, 0x0, 0x0,216//s12170x0, 0x0,218//s22190x10, 0,220//x1221(byte) 0x80,222//x22230x0,224//x32250x0,226//x4227(byte) 0xaa,228//x52290x0,230//x62310x38,232//x7233(byte) 0x9b,234//x82350x71,236// DATA_MAGIC2370x64, 0x61, 0x74, 0x61,238// data size239(byte) (size), (byte) (size >> 8), (byte) (size >> 16),240(byte) (size >> 24)241// data242, 0, 0, 0, 0, 0243};244}245}246247248