Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]
    1   /*
    2    * Copyright (c) 2007, 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.File;
   28   import java.io.FileNotFoundException;
   29   import java.io.IOException;
   30   import java.io.OutputStream;
   31   import java.io.RandomAccessFile;
   32   
   33   /**
   34    * Resource Interchange File Format (RIFF) stream encoder.
   35    *
   36    * @author Karl Helgason
   37    */
   38   public class RIFFWriter extends OutputStream {
   39   
   40       private interface RandomAccessWriter {
   41   
   42           public void seek(long chunksizepointer) throws IOException;
   43   
   44           public long getPointer() throws IOException;
   45   
   46           public void close() throws IOException;
   47   
   48           public void write(int b) throws IOException;
   49   
   50           public void write(byte[] b, int off, int len) throws IOException;
   51   
   52           public void write(byte[] bytes) throws IOException;
   53   
   54           public long length() throws IOException;
   55   
   56           public void setLength(long i) throws IOException;
   57       }
   58   
   59       private static class RandomAccessFileWriter implements RandomAccessWriter {
   60   
   61           RandomAccessFile raf;
   62   
   63           public RandomAccessFileWriter(File file) throws FileNotFoundException {
   64               this.raf = new RandomAccessFile(file, "rw");
   65           }
   66   
   67           public RandomAccessFileWriter(String name) throws FileNotFoundException {
   68               this.raf = new RandomAccessFile(name, "rw");
   69           }
   70   
   71           public void seek(long chunksizepointer) throws IOException {
   72               raf.seek(chunksizepointer);
   73           }
   74   
   75           public long getPointer() throws IOException {
   76               return raf.getFilePointer();
   77           }
   78   
   79           public void close() throws IOException {
   80               raf.close();
   81           }
   82   
   83           public void write(int b) throws IOException {
   84               raf.write(b);
   85           }
   86   
   87           public void write(byte[] b, int off, int len) throws IOException {
   88               raf.write(b, off, len);
   89           }
   90   
   91           public void write(byte[] bytes) throws IOException {
   92               raf.write(bytes);
   93           }
   94   
   95           public long length() throws IOException {
   96               return raf.length();
   97           }
   98   
   99           public void setLength(long i) throws IOException {
  100               raf.setLength(i);
  101           }
  102       }
  103   
  104       private static class RandomAccessByteWriter implements RandomAccessWriter {
  105   
  106           byte[] buff = new byte[32];
  107           int length = 0;
  108           int pos = 0;
  109           byte[] s;
  110           OutputStream stream;
  111   
  112           public RandomAccessByteWriter(OutputStream stream) {
  113               this.stream = stream;
  114           }
  115   
  116           public void seek(long chunksizepointer) throws IOException {
  117               pos = (int) chunksizepointer;
  118           }
  119   
  120           public long getPointer() throws IOException {
  121               return pos;
  122           }
  123   
  124           public void close() throws IOException {
  125               stream.write(buff, 0, length);
  126               stream.close();
  127           }
  128   
  129           public void write(int b) throws IOException {
  130               if (s == null)
  131                   s = new byte[1];
  132               s[0] = (byte)b;
  133               write(s, 0, 1);
  134           }
  135   
  136           public void write(byte[] b, int off, int len) throws IOException {
  137               int newsize = pos + len;
  138               if (newsize > length)
  139                   setLength(newsize);
  140               int end = off + len;
  141               for (int i = off; i < end; i++) {
  142                   buff[pos++] = b[i];
  143               }
  144           }
  145   
  146           public void write(byte[] bytes) throws IOException {
  147               write(bytes, 0, bytes.length);
  148           }
  149   
  150           public long length() throws IOException {
  151               return length;
  152           }
  153   
  154           public void setLength(long i) throws IOException {
  155               length = (int) i;
  156               if (length > buff.length) {
  157                   int newlen = Math.max(buff.length << 1, length);
  158                   byte[] newbuff = new byte[newlen];
  159                   System.arraycopy(buff, 0, newbuff, 0, buff.length);
  160                   buff = newbuff;
  161               }
  162           }
  163       }
  164       private int chunktype = 0; // 0=RIFF, 1=LIST; 2=CHUNK
  165       private RandomAccessWriter raf;
  166       private long chunksizepointer;
  167       private long startpointer;
  168       private RIFFWriter childchunk = null;
  169       private boolean open = true;
  170       private boolean writeoverride = false;
  171   
  172       public RIFFWriter(String name, String format) throws IOException {
  173           this(new RandomAccessFileWriter(name), format, 0);
  174       }
  175   
  176       public RIFFWriter(File file, String format) throws IOException {
  177           this(new RandomAccessFileWriter(file), format, 0);
  178       }
  179   
  180       public RIFFWriter(OutputStream stream, String format) throws IOException {
  181           this(new RandomAccessByteWriter(stream), format, 0);
  182       }
  183   
  184       private RIFFWriter(RandomAccessWriter raf, String format, int chunktype)
  185               throws IOException {
  186           if (chunktype == 0)
  187               if (raf.length() != 0)
  188                   raf.setLength(0);
  189           this.raf = raf;
  190           if (raf.getPointer() % 2 != 0)
  191               raf.write(0);
  192   
  193           if (chunktype == 0)
  194               raf.write("RIFF".getBytes("ascii"));
  195           else if (chunktype == 1)
  196               raf.write("LIST".getBytes("ascii"));
  197           else
  198               raf.write((format + "    ").substring(0, 4).getBytes("ascii"));
  199   
  200           chunksizepointer = raf.getPointer();
  201           this.chunktype = 2;
  202           writeUnsignedInt(0);
  203           this.chunktype = chunktype;
  204           startpointer = raf.getPointer();
  205           if (chunktype != 2)
  206               raf.write((format + "    ").substring(0, 4).getBytes("ascii"));
  207   
  208       }
  209   
  210       public void seek(long pos) throws IOException {
  211           raf.seek(pos);
  212       }
  213   
  214       public long getFilePointer() throws IOException {
  215           return raf.getPointer();
  216       }
  217   
  218       public void setWriteOverride(boolean writeoverride) {
  219           this.writeoverride = writeoverride;
  220       }
  221   
  222       public boolean getWriteOverride() {
  223           return writeoverride;
  224       }
  225   
  226       public void close() throws IOException {
  227           if (!open)
  228               return;
  229           if (childchunk != null) {
  230               childchunk.close();
  231               childchunk = null;
  232           }
  233   
  234           int bakchunktype = chunktype;
  235           long fpointer = raf.getPointer();
  236           raf.seek(chunksizepointer);
  237           chunktype = 2;
  238           writeUnsignedInt(fpointer - startpointer);
  239   
  240           if (bakchunktype == 0)
  241               raf.close();
  242           else
  243               raf.seek(fpointer);
  244           open = false;
  245           raf = null;
  246       }
  247   
  248       public void write(int b) throws IOException {
  249           if (!writeoverride) {
  250               if (chunktype != 2) {
  251                   throw new IllegalArgumentException(
  252                           "Only chunks can write bytes!");
  253               }
  254               if (childchunk != null) {
  255                   childchunk.close();
  256                   childchunk = null;
  257               }
  258           }
  259           raf.write(b);
  260       }
  261   
  262       public void write(byte b[], int off, int len) throws IOException {
  263           if (!writeoverride) {
  264               if (chunktype != 2) {
  265                   throw new IllegalArgumentException(
  266                           "Only chunks can write bytes!");
  267               }
  268               if (childchunk != null) {
  269                   childchunk.close();
  270                   childchunk = null;
  271               }
  272           }
  273           raf.write(b, off, len);
  274       }
  275   
  276       public RIFFWriter writeList(String format) throws IOException {
  277           if (chunktype == 2) {
  278               throw new IllegalArgumentException(
  279                       "Only LIST and RIFF can write lists!");
  280           }
  281           if (childchunk != null) {
  282               childchunk.close();
  283               childchunk = null;
  284           }
  285           childchunk = new RIFFWriter(this.raf, format, 1);
  286           return childchunk;
  287       }
  288   
  289       public RIFFWriter writeChunk(String format) throws IOException {
  290           if (chunktype == 2) {
  291               throw new IllegalArgumentException(
  292                       "Only LIST and RIFF can write chunks!");
  293           }
  294           if (childchunk != null) {
  295               childchunk.close();
  296               childchunk = null;
  297           }
  298           childchunk = new RIFFWriter(this.raf, format, 2);
  299           return childchunk;
  300       }
  301   
  302       // Write ASCII chars to stream
  303       public void writeString(String string) throws IOException {
  304           byte[] buff = string.getBytes();
  305           write(buff);
  306       }
  307   
  308       // Write ASCII chars to stream
  309       public void writeString(String string, int len) throws IOException {
  310           byte[] buff = string.getBytes();
  311           if (buff.length > len)
  312               write(buff, 0, len);
  313           else {
  314               write(buff);
  315               for (int i = buff.length; i < len; i++)
  316                   write(0);
  317           }
  318       }
  319   
  320       // Write 8 bit signed integer to stream
  321       public void writeByte(int b) throws IOException {
  322           write(b);
  323       }
  324   
  325       // Write 16 bit signed integer to stream
  326       public void writeShort(short b) throws IOException {
  327           write((b >>> 0) & 0xFF);
  328           write((b >>> 8) & 0xFF);
  329       }
  330   
  331       // Write 32 bit signed integer to stream
  332       public void writeInt(int b) throws IOException {
  333           write((b >>> 0) & 0xFF);
  334           write((b >>> 8) & 0xFF);
  335           write((b >>> 16) & 0xFF);
  336           write((b >>> 24) & 0xFF);
  337       }
  338   
  339       // Write 64 bit signed integer to stream
  340       public void writeLong(long b) throws IOException {
  341           write((int) (b >>> 0) & 0xFF);
  342           write((int) (b >>> 8) & 0xFF);
  343           write((int) (b >>> 16) & 0xFF);
  344           write((int) (b >>> 24) & 0xFF);
  345           write((int) (b >>> 32) & 0xFF);
  346           write((int) (b >>> 40) & 0xFF);
  347           write((int) (b >>> 48) & 0xFF);
  348           write((int) (b >>> 56) & 0xFF);
  349       }
  350   
  351       // Write 8 bit unsigned integer to stream
  352       public void writeUnsignedByte(int b) throws IOException {
  353           writeByte((byte) b);
  354       }
  355   
  356       // Write 16 bit unsigned integer to stream
  357       public void writeUnsignedShort(int b) throws IOException {
  358           writeShort((short) b);
  359       }
  360   
  361       // Write 32 bit unsigned integer to stream
  362       public void writeUnsignedInt(long b) throws IOException {
  363           writeInt((int) b);
  364       }
  365   }

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