Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]
    1   /*
    2    * Copyright (c) 2007, 2010, 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 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           public 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;
  132               if (x6 != t.x6)
  133                   return false;
  134               if (x7 != t.x7)
  135                   return false;
  136               if (x8 != t.x8)
  137                   return false;
  138               return true;
  139           }
  140   
  141       }
  142   
  143       private static String[] channelnames = { "FL", "FR", "FC", "LF",
  144               "BL",
  145               "BR", // 5.1
  146               "FLC", "FLR", "BC", "SL", "SR", "TC", "TFL", "TFC", "TFR", "TBL",
  147               "TBC", "TBR" };
  148   
  149       private static 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 GUID SUBTYPE_PCM = new GUID(0x00000001, 0x0000, 0x0010,
  159               0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
  160   
  161       private static 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           StringBuffer sb = new StringBuffer();
  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] + " ");
  171                   } else {
  172                       sb.append(allchannelnames[i] + " ");
  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   
  217           while (riffiterator.hasNextChunk()) {
  218               RIFFReader chunk = riffiterator.nextChunk();
  219   
  220               if (chunk.getFormat().equals("fmt ")) {
  221                   fmt_found = true;
  222   
  223                   int format = chunk.readUnsignedShort();
  224                   if (format != 0xFFFE)
  225                       throw new UnsupportedAudioFileException(); // WAVE_FORMAT_EXTENSIBLE
  226                   // only
  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   }

Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]