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.EOFException;
   28   import java.io.IOException;
   29   import java.io.InputStream;
   30   
   31   import javax.sound.sampled.AudioFormat;
   32   import javax.sound.sampled.AudioInputStream;
   33   
   34   /**
   35    * A jitter corrector to be used with SoftAudioPusher.
   36    *
   37    * @author Karl Helgason
   38    */
   39   public class SoftJitterCorrector extends AudioInputStream {
   40   
   41       private static class JitterStream extends InputStream {
   42   
   43           static int MAX_BUFFER_SIZE = 1048576;
   44           boolean active = true;
   45           Thread thread;
   46           AudioInputStream stream;
   47           // Cyclic buffer
   48           int writepos = 0;
   49           int readpos = 0;
   50           byte[][] buffers;
   51           Object buffers_mutex = new Object();
   52   
   53           // Adapative Drift Statistics
   54           int w_count = 1000;
   55           int w_min_tol = 2;
   56           int w_max_tol = 10;
   57           int w = 0;
   58           int w_min = -1;
   59           // Current read buffer
   60           int bbuffer_pos = 0;
   61           int bbuffer_max = 0;
   62           byte[] bbuffer = null;
   63   
   64           public byte[] nextReadBuffer() {
   65               synchronized (buffers_mutex) {
   66                   if (writepos > readpos) {
   67                       int w_m = writepos - readpos;
   68                       if (w_m < w_min)
   69                           w_min = w_m;
   70   
   71                       int buffpos = readpos;
   72                       readpos++;
   73                       return buffers[buffpos % buffers.length];
   74                   }
   75                   w_min = -1;
   76                   w = w_count - 1;
   77               }
   78               while (true) {
   79                   try {
   80                       Thread.sleep(1);
   81                   } catch (InterruptedException e) {
   82                       //e.printStackTrace();
   83                       return null;
   84                   }
   85                   synchronized (buffers_mutex) {
   86                       if (writepos > readpos) {
   87                           w = 0;
   88                           w_min = -1;
   89                           w = w_count - 1;
   90                           int buffpos = readpos;
   91                           readpos++;
   92                           return buffers[buffpos % buffers.length];
   93                       }
   94                   }
   95               }
   96           }
   97   
   98           public byte[] nextWriteBuffer() {
   99               synchronized (buffers_mutex) {
  100                   return buffers[writepos % buffers.length];
  101               }
  102           }
  103   
  104           public void commit() {
  105               synchronized (buffers_mutex) {
  106                   writepos++;
  107                   if ((writepos - readpos) > buffers.length) {
  108                       int newsize = (writepos - readpos) + 10;
  109                       newsize = Math.max(buffers.length * 2, newsize);
  110                       buffers = new byte[newsize][buffers[0].length];
  111                   }
  112               }
  113           }
  114   
  115           public JitterStream(AudioInputStream s, int buffersize,
  116                   int smallbuffersize) {
  117               this.w_count = 10 * (buffersize / smallbuffersize);
  118               if (w_count < 100)
  119                   w_count = 100;
  120               this.buffers
  121                       = new byte[(buffersize/smallbuffersize)+10][smallbuffersize];
  122               this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize;
  123               this.stream = s;
  124   
  125   
  126               Runnable runnable = new Runnable() {
  127   
  128                   public void run() {
  129                       AudioFormat format = stream.getFormat();
  130                       int bufflen = buffers[0].length;
  131                       int frames = bufflen / format.getFrameSize();
  132                       long nanos = (long) (frames * 1000000000.0
  133                                               / format.getSampleRate());
  134                       long now = System.nanoTime();
  135                       long next = now + nanos;
  136                       int correction = 0;
  137                       while (true) {
  138                           synchronized (JitterStream.this) {
  139                               if (!active)
  140                                   break;
  141                           }
  142                           int curbuffsize;
  143                           synchronized (buffers) {
  144                               curbuffsize = writepos - readpos;
  145                               if (correction == 0) {
  146                                   w++;
  147                                   if (w_min != Integer.MAX_VALUE) {
  148                                       if (w == w_count) {
  149                                           correction = 0;
  150                                           if (w_min < w_min_tol) {
  151                                               correction = (w_min_tol + w_max_tol)
  152                                                               / 2 - w_min;
  153                                           }
  154                                           if (w_min > w_max_tol) {
  155                                               correction = (w_min_tol + w_max_tol)
  156                                                               / 2 - w_min;
  157                                           }
  158                                           w = 0;
  159                                           w_min = Integer.MAX_VALUE;
  160                                       }
  161                                   }
  162                               }
  163                           }
  164                           while (curbuffsize > bbuffer_max) {
  165                               synchronized (buffers) {
  166                                   curbuffsize = writepos - readpos;
  167                               }
  168                               synchronized (JitterStream.this) {
  169                                   if (!active)
  170                                       break;
  171                               }
  172                               try {
  173                                   Thread.sleep(1);
  174                               } catch (InterruptedException e) {
  175                                   //e.printStackTrace();
  176                               }
  177                           }
  178   
  179                           if (correction < 0)
  180                               correction++;
  181                           else {
  182                               byte[] buff = nextWriteBuffer();
  183                               try {
  184                                   int n = 0;
  185                                   while (n != buff.length) {
  186                                       int s = stream.read(buff, n, buff.length
  187                                               - n);
  188                                       if (s < 0)
  189                                           throw new EOFException();
  190                                       if (s == 0)
  191                                           Thread.yield();
  192                                       n += s;
  193                                   }
  194                               } catch (IOException e1) {
  195                                   //e1.printStackTrace();
  196                               }
  197                               commit();
  198                           }
  199   
  200                           if (correction > 0) {
  201                               correction--;
  202                               next = System.nanoTime() + nanos;
  203                               continue;
  204                           }
  205                           long wait = next - System.nanoTime();
  206                           if (wait > 0) {
  207                               try {
  208                                   Thread.sleep(wait / 1000000L);
  209                               } catch (InterruptedException e) {
  210                                   //e.printStackTrace();
  211                               }
  212                           }
  213                           next += nanos;
  214                       }
  215                   }
  216               };
  217   
  218               thread = new Thread(runnable);
  219               thread.setDaemon(true);
  220               thread.setPriority(Thread.MAX_PRIORITY);
  221               thread.start();
  222           }
  223   
  224           public void close() throws IOException {
  225               synchronized (this) {
  226                   active = false;
  227               }
  228               try {
  229                   thread.join();
  230               } catch (InterruptedException e) {
  231                   //e.printStackTrace();
  232               }
  233               stream.close();
  234           }
  235   
  236           public int read() throws IOException {
  237               byte[] b = new byte[1];
  238               if (read(b) == -1)
  239                   return -1;
  240               return b[0] & 0xFF;
  241           }
  242   
  243           public void fillBuffer() {
  244               bbuffer = nextReadBuffer();
  245               bbuffer_pos = 0;
  246           }
  247   
  248           public int read(byte[] b, int off, int len) {
  249               if (bbuffer == null)
  250                   fillBuffer();
  251               int bbuffer_len = bbuffer.length;
  252               int offlen = off + len;
  253               while (off < offlen) {
  254                   if (available() == 0)
  255                       fillBuffer();
  256                   else {
  257                       byte[] bbuffer = this.bbuffer;
  258                       int bbuffer_pos = this.bbuffer_pos;
  259                       while (off < offlen && bbuffer_pos < bbuffer_len)
  260                           b[off++] = bbuffer[bbuffer_pos++];
  261                       this.bbuffer_pos = bbuffer_pos;
  262                   }
  263               }
  264               return len;
  265           }
  266   
  267           public int available() {
  268               return bbuffer.length - bbuffer_pos;
  269           }
  270       }
  271   
  272       public SoftJitterCorrector(AudioInputStream stream, int buffersize,
  273               int smallbuffersize) {
  274           super(new JitterStream(stream, buffersize, smallbuffersize),
  275                   stream.getFormat(), stream.getFrameLength());
  276       }
  277   }

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