< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java

Print this page


   1 /*
   2  * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */

  25 package com.sun.media.sound;
  26 
  27 import java.io.BufferedInputStream;
  28 import java.io.File;
  29 import java.io.FileInputStream;
  30 import java.io.IOException;
  31 import java.io.InputStream;
  32 import java.net.URL;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 
  36 import javax.sound.sampled.AudioFileFormat;
  37 import javax.sound.sampled.AudioFormat;

  38 import javax.sound.sampled.AudioInputStream;
  39 import javax.sound.sampled.AudioSystem;
  40 import javax.sound.sampled.UnsupportedAudioFileException;
  41 import javax.sound.sampled.AudioFormat.Encoding;
  42 import javax.sound.sampled.spi.AudioFileReader;
  43 
  44 /**
  45  * WAVE file reader for files using format WAVE_FORMAT_EXTENSIBLE (0xFFFE).
  46  *
  47  * @author Karl Helgason
  48  */
  49 public final class WaveExtensibleFileReader extends AudioFileReader {
  50 
  51     static private class GUID {
  52         long i1;
  53 
  54         int s1;
  55 
  56         int s2;
  57 
  58         int x1;
  59 
  60         int x2;
  61 
  62         int x3;
  63 
  64         int x4;
  65 
  66         int x5;
  67 
  68         int x6;
  69 
  70         int x7;
  71 
  72         int x8;
  73 












  74         private GUID() {
  75         }
  76 
  77         GUID(long i1, int s1, int s2, int x1, int x2, int x3, int x4,
  78                 int x5, int x6, int x7, int x8) {
  79             this.i1 = i1;
  80             this.s1 = s1;
  81             this.s2 = s2;
  82             this.x1 = x1;
  83             this.x2 = x2;
  84             this.x3 = x3;
  85             this.x4 = x4;
  86             this.x5 = x5;
  87             this.x6 = x6;
  88             this.x7 = x7;
  89             this.x8 = x8;
  90         }
  91 
  92         public static GUID read(RIFFReader riff) throws IOException {
  93             GUID d = new GUID();
  94             d.i1 = riff.readUnsignedInt();
  95             d.s1 = riff.readUnsignedShort();
  96             d.s2 = riff.readUnsignedShort();
  97             d.x1 = riff.readUnsignedByte();
  98             d.x2 = riff.readUnsignedByte();
  99             d.x3 = riff.readUnsignedByte();
 100             d.x4 = riff.readUnsignedByte();
 101             d.x5 = riff.readUnsignedByte();
 102             d.x6 = riff.readUnsignedByte();
 103             d.x7 = riff.readUnsignedByte();
 104             d.x8 = riff.readUnsignedByte();
 105             return d;
 106         }
 107 

 108         public int hashCode() {
 109             return (int) i1;
 110         }
 111 

 112         public boolean equals(Object obj) {
 113             if (!(obj instanceof GUID))
 114                 return false;
 115             GUID t = (GUID) obj;
 116             if (i1 != t.i1)
 117                 return false;
 118             if (s1 != t.s1)
 119                 return false;
 120             if (s2 != t.s2)
 121                 return false;
 122             if (x1 != t.x1)
 123                 return false;
 124             if (x2 != t.x2)
 125                 return false;
 126             if (x3 != t.x3)
 127                 return false;
 128             if (x4 != t.x4)
 129                 return false;
 130             if (x5 != t.x5)
 131                 return false;


 144             "BL",
 145             "BR", // 5.1
 146             "FLC", "FLR", "BC", "SL", "SR", "TC", "TFL", "TFC", "TFR", "TBL",
 147             "TBC", "TBR" };
 148 
 149     private static final String[] allchannelnames = { "w1", "w2", "w3", "w4", "w5",
 150             "w6", "w7", "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
 151             "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", "w24",
 152             "w25", "w26", "w27", "w28", "w29", "w30", "w31", "w32", "w33",
 153             "w34", "w35", "w36", "w37", "w38", "w39", "w40", "w41", "w42",
 154             "w43", "w44", "w45", "w46", "w47", "w48", "w49", "w50", "w51",
 155             "w52", "w53", "w54", "w55", "w56", "w57", "w58", "w59", "w60",
 156             "w61", "w62", "w63", "w64" };
 157 
 158     private static final GUID SUBTYPE_PCM = new GUID(0x00000001, 0x0000, 0x0010,
 159             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 160 
 161     private static final GUID SUBTYPE_IEEE_FLOAT = new GUID(0x00000003, 0x0000,
 162             0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 163 
 164     private String decodeChannelMask(long channelmask) {
 165         StringBuilder sb = new StringBuilder();
 166         long m = 1;
 167         for (int i = 0; i < allchannelnames.length; i++) {
 168             if ((channelmask & m) != 0L) {
 169                 if (i < channelnames.length) {
 170                     sb.append(channelnames[i]).append(' ');
 171                 } else {
 172                     sb.append(allchannelnames[i]).append(' ');
 173                 }
 174             }
 175             m *= 2L;
 176         }
 177         if (sb.length() == 0)
 178             return null;
 179         return sb.substring(0, sb.length() - 1);
 180 
 181     }
 182 
 183     public AudioFileFormat getAudioFileFormat(InputStream stream)
 184             throws UnsupportedAudioFileException, IOException {
 185 
 186         stream.mark(200);
 187         AudioFileFormat format;
 188         try {
 189             format = internal_getAudioFileFormat(stream);
 190         } finally {
 191             stream.reset();
 192         }
 193         return format;
 194     }
 195 
 196     private AudioFileFormat internal_getAudioFileFormat(InputStream stream)
 197             throws UnsupportedAudioFileException, IOException {
 198 
 199         RIFFReader riffiterator = new RIFFReader(stream);
 200         if (!riffiterator.getFormat().equals("RIFF"))
 201             throw new UnsupportedAudioFileException();
 202         if (!riffiterator.getType().equals("WAVE"))
 203             throw new UnsupportedAudioFileException();
 204 
 205         boolean fmt_found = false;
 206         boolean data_found = false;
 207 
 208         int channels = 1;
 209         long samplerate = 1;
 210         // long framerate = 1;
 211         int framesize = 1;
 212         int bits = 1;
 213         int validBitsPerSample = 1;
 214         long channelMask = 0;
 215         GUID subFormat = null;
 216 


 227                 channels = chunk.readUnsignedShort();
 228                 samplerate = chunk.readUnsignedInt();
 229                 /* framerate = */chunk.readUnsignedInt();
 230                 framesize = chunk.readUnsignedShort();
 231                 bits = chunk.readUnsignedShort();
 232                 int cbSize = chunk.readUnsignedShort();
 233                 if (cbSize != 22)
 234                     throw new UnsupportedAudioFileException();
 235                 validBitsPerSample = chunk.readUnsignedShort();
 236                 if (validBitsPerSample > bits)
 237                     throw new UnsupportedAudioFileException();
 238                 channelMask = chunk.readUnsignedInt();
 239                 subFormat = GUID.read(chunk);
 240 
 241             }
 242             if (chunk.getFormat().equals("data")) {
 243                 data_found = true;
 244                 break;
 245             }
 246         }
 247 
 248         if (!fmt_found)
 249             throw new UnsupportedAudioFileException();
 250         if (!data_found)
 251             throw new UnsupportedAudioFileException();
 252 
 253         Map<String, Object> p = new HashMap<String, Object>();
 254         String s_channelmask = decodeChannelMask(channelMask);
 255         if (s_channelmask != null)
 256             p.put("channelOrder", s_channelmask);
 257         if (channelMask != 0)
 258             p.put("channelMask", channelMask);
 259         // validBitsPerSample is only informational for PCM data,
 260         // data is still encode according to SampleSizeInBits.
 261         p.put("validBitsPerSample", validBitsPerSample);
 262 
 263         AudioFormat audioformat = null;
 264         if (subFormat.equals(SUBTYPE_PCM)) {
 265             if (bits == 8) {
 266                 audioformat = new AudioFormat(Encoding.PCM_UNSIGNED,
 267                         samplerate, bits, channels, framesize, samplerate,
 268                         false, p);
 269             } else {
 270                 audioformat = new AudioFormat(Encoding.PCM_SIGNED, samplerate,
 271                         bits, channels, framesize, samplerate, false, p);
 272             }
 273         } else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) {
 274             audioformat = new AudioFormat(Encoding.PCM_FLOAT,
 275                     samplerate, bits, channels, framesize, samplerate, false, p);
 276         } else
 277             throw new UnsupportedAudioFileException();
 278 
 279         AudioFileFormat fileformat = new AudioFileFormat(
 280                 AudioFileFormat.Type.WAVE, audioformat,
 281                 AudioSystem.NOT_SPECIFIED);
 282         return fileformat;
 283     }
 284 
 285     public AudioInputStream getAudioInputStream(InputStream stream)

 286             throws UnsupportedAudioFileException, IOException {
 287 
 288         AudioFileFormat format = getAudioFileFormat(stream);



 289         RIFFReader riffiterator = new RIFFReader(stream);
 290         if (!riffiterator.getFormat().equals("RIFF"))
 291             throw new UnsupportedAudioFileException();
 292         if (!riffiterator.getType().equals("WAVE"))
 293             throw new UnsupportedAudioFileException();
 294         while (riffiterator.hasNextChunk()) {
 295             RIFFReader chunk = riffiterator.nextChunk();
 296             if (chunk.getFormat().equals("data")) {
 297                 return new AudioInputStream(chunk, format.getFormat(), chunk
 298                         .getSize());
 299             }
 300         }
 301         throw new UnsupportedAudioFileException();
 302     }
 303 
 304     public AudioFileFormat getAudioFileFormat(URL url)
 305             throws UnsupportedAudioFileException, IOException {
 306         InputStream stream = url.openStream();
 307         AudioFileFormat format;
 308         try {
 309             format = getAudioFileFormat(new BufferedInputStream(stream));
 310         } finally {
 311             stream.close();
 312         }
 313         return format;
 314     }
 315 
 316     public AudioFileFormat getAudioFileFormat(File file)
 317             throws UnsupportedAudioFileException, IOException {
 318         InputStream stream = new FileInputStream(file);
 319         AudioFileFormat format;
 320         try {
 321             format = getAudioFileFormat(new BufferedInputStream(stream));
 322         } finally {
 323             stream.close();
 324         }
 325         return format;
 326     }
 327 
 328     public AudioInputStream getAudioInputStream(URL url)
 329             throws UnsupportedAudioFileException, IOException {
 330         return getAudioInputStream(new BufferedInputStream(url.openStream()));
 331     }
 332 
 333     public AudioInputStream getAudioInputStream(File file)
 334             throws UnsupportedAudioFileException, IOException {
 335         return getAudioInputStream(new BufferedInputStream(new FileInputStream(
 336                 file)));
 337     }
 338 
 339 }
   1 /*
   2  * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.media.sound;
  27 



  28 import java.io.IOException;
  29 import java.io.InputStream;

  30 import java.util.HashMap;
  31 import java.util.Map;
  32 
  33 import javax.sound.sampled.AudioFileFormat;
  34 import javax.sound.sampled.AudioFormat;
  35 import javax.sound.sampled.AudioFormat.Encoding;
  36 import javax.sound.sampled.AudioInputStream;
  37 import javax.sound.sampled.AudioSystem;
  38 import javax.sound.sampled.UnsupportedAudioFileException;


  39 
  40 /**
  41  * WAVE file reader for files using format WAVE_FORMAT_EXTENSIBLE (0xFFFE).
  42  *
  43  * @author Karl Helgason
  44  */
  45 public final class WaveExtensibleFileReader extends SunFileReader {























  46 
  47     private static class GUID {
  48         private long i1;
  49         private int s1;
  50         private int s2;
  51         private int x1;
  52         private int x2;
  53         private int x3;
  54         private int x4;
  55         private int x5;
  56         private int x6;
  57         private int x7;
  58         private int x8;
  59         private GUID() {
  60         }
  61 
  62         GUID(long i1, int s1, int s2, int x1, int x2, int x3, int x4,
  63                 int x5, int x6, int x7, int x8) {
  64             this.i1 = i1;
  65             this.s1 = s1;
  66             this.s2 = s2;
  67             this.x1 = x1;
  68             this.x2 = x2;
  69             this.x3 = x3;
  70             this.x4 = x4;
  71             this.x5 = x5;
  72             this.x6 = x6;
  73             this.x7 = x7;
  74             this.x8 = x8;
  75         }
  76 
  77         public static GUID read(RIFFReader riff) throws IOException {
  78             GUID d = new GUID();
  79             d.i1 = riff.readUnsignedInt();
  80             d.s1 = riff.readUnsignedShort();
  81             d.s2 = riff.readUnsignedShort();
  82             d.x1 = riff.readUnsignedByte();
  83             d.x2 = riff.readUnsignedByte();
  84             d.x3 = riff.readUnsignedByte();
  85             d.x4 = riff.readUnsignedByte();
  86             d.x5 = riff.readUnsignedByte();
  87             d.x6 = riff.readUnsignedByte();
  88             d.x7 = riff.readUnsignedByte();
  89             d.x8 = riff.readUnsignedByte();
  90             return d;
  91         }
  92 
  93         @Override
  94         public int hashCode() {
  95             return (int) i1;
  96         }
  97 
  98         @Override
  99         public boolean equals(Object obj) {
 100             if (!(obj instanceof GUID))
 101                 return false;
 102             GUID t = (GUID) obj;
 103             if (i1 != t.i1)
 104                 return false;
 105             if (s1 != t.s1)
 106                 return false;
 107             if (s2 != t.s2)
 108                 return false;
 109             if (x1 != t.x1)
 110                 return false;
 111             if (x2 != t.x2)
 112                 return false;
 113             if (x3 != t.x3)
 114                 return false;
 115             if (x4 != t.x4)
 116                 return false;
 117             if (x5 != t.x5)
 118                 return false;


 131             "BL",
 132             "BR", // 5.1
 133             "FLC", "FLR", "BC", "SL", "SR", "TC", "TFL", "TFC", "TFR", "TBL",
 134             "TBC", "TBR" };
 135 
 136     private static final String[] allchannelnames = { "w1", "w2", "w3", "w4", "w5",
 137             "w6", "w7", "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
 138             "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", "w24",
 139             "w25", "w26", "w27", "w28", "w29", "w30", "w31", "w32", "w33",
 140             "w34", "w35", "w36", "w37", "w38", "w39", "w40", "w41", "w42",
 141             "w43", "w44", "w45", "w46", "w47", "w48", "w49", "w50", "w51",
 142             "w52", "w53", "w54", "w55", "w56", "w57", "w58", "w59", "w60",
 143             "w61", "w62", "w63", "w64" };
 144 
 145     private static final GUID SUBTYPE_PCM = new GUID(0x00000001, 0x0000, 0x0010,
 146             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 147 
 148     private static final GUID SUBTYPE_IEEE_FLOAT = new GUID(0x00000003, 0x0000,
 149             0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 150 
 151     private static String decodeChannelMask(long channelmask) {
 152         StringBuilder sb = new StringBuilder();
 153         long m = 1;
 154         for (int i = 0; i < allchannelnames.length; i++) {
 155             if ((channelmask & m) != 0L) {
 156                 if (i < channelnames.length) {
 157                     sb.append(channelnames[i]).append(' ');
 158                 } else {
 159                     sb.append(allchannelnames[i]).append(' ');
 160                 }
 161             }
 162             m *= 2L;
 163         }
 164         if (sb.length() == 0)
 165             return null;
 166         return sb.substring(0, sb.length() - 1);
 167 
 168     }
 169 
 170     @Override
 171     AudioFileFormat getAudioFileFormatImpl(final InputStream stream)












 172             throws UnsupportedAudioFileException, IOException {
 173 
 174         RIFFReader riffiterator = new RIFFReader(stream);
 175         if (!riffiterator.getFormat().equals("RIFF"))
 176             throw new UnsupportedAudioFileException();
 177         if (!riffiterator.getType().equals("WAVE"))
 178             throw new UnsupportedAudioFileException();
 179 
 180         boolean fmt_found = false;
 181         boolean data_found = false;
 182 
 183         int channels = 1;
 184         long samplerate = 1;
 185         // long framerate = 1;
 186         int framesize = 1;
 187         int bits = 1;
 188         int validBitsPerSample = 1;
 189         long channelMask = 0;
 190         GUID subFormat = null;
 191 


 202                 channels = chunk.readUnsignedShort();
 203                 samplerate = chunk.readUnsignedInt();
 204                 /* framerate = */chunk.readUnsignedInt();
 205                 framesize = chunk.readUnsignedShort();
 206                 bits = chunk.readUnsignedShort();
 207                 int cbSize = chunk.readUnsignedShort();
 208                 if (cbSize != 22)
 209                     throw new UnsupportedAudioFileException();
 210                 validBitsPerSample = chunk.readUnsignedShort();
 211                 if (validBitsPerSample > bits)
 212                     throw new UnsupportedAudioFileException();
 213                 channelMask = chunk.readUnsignedInt();
 214                 subFormat = GUID.read(chunk);
 215 
 216             }
 217             if (chunk.getFormat().equals("data")) {
 218                 data_found = true;
 219                 break;
 220             }
 221         }
 222         if (!fmt_found || !data_found) {



 223             throw new UnsupportedAudioFileException();
 224         }
 225         Map<String, Object> p = new HashMap<String, Object>();
 226         String s_channelmask = decodeChannelMask(channelMask);
 227         if (s_channelmask != null)
 228             p.put("channelOrder", s_channelmask);
 229         if (channelMask != 0)
 230             p.put("channelMask", channelMask);
 231         // validBitsPerSample is only informational for PCM data,
 232         // data is still encode according to SampleSizeInBits.
 233         p.put("validBitsPerSample", validBitsPerSample);
 234 
 235         AudioFormat audioformat = null;
 236         if (subFormat.equals(SUBTYPE_PCM)) {
 237             if (bits == 8) {
 238                 audioformat = new AudioFormat(Encoding.PCM_UNSIGNED,
 239                         samplerate, bits, channels, framesize, samplerate,
 240                         false, p);
 241             } else {
 242                 audioformat = new AudioFormat(Encoding.PCM_SIGNED, samplerate,
 243                         bits, channels, framesize, samplerate, false, p);
 244             }
 245         } else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) {
 246             audioformat = new AudioFormat(Encoding.PCM_FLOAT,
 247                     samplerate, bits, channels, framesize, samplerate, false, p);
 248         } else {
 249             throw new UnsupportedAudioFileException();
 250         }
 251         return new AudioFileFormat(AudioFileFormat.Type.WAVE, audioformat,

 252                                    AudioSystem.NOT_SPECIFIED);

 253     }
 254 
 255     @Override
 256     public AudioInputStream getAudioInputStream(final InputStream stream)
 257             throws UnsupportedAudioFileException, IOException {
 258 
 259         AudioFileFormat format = getAudioFileFormat(stream);
 260         // we've got everything, the stream is supported and it is at the
 261         // beginning of the header, so find the data chunk again and return an
 262         // AudioInputStream
 263         RIFFReader riffiterator = new RIFFReader(stream);




 264         while (riffiterator.hasNextChunk()) {
 265             RIFFReader chunk = riffiterator.nextChunk();
 266             if (chunk.getFormat().equals("data")) {
 267                 return new AudioInputStream(chunk, format.getFormat(), chunk
 268                         .getSize());
 269             }
 270         }
 271         throw new UnsupportedAudioFileException();
 272     }




































 273 }
< prev index next >