Mercurial > hg > release > icedtea6-1.2
view overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java @ 843:bcba163568ac
Integrate Gervill.
2008-04-30 Mark Wielaard <mark@klomp.org>
* Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch.
* Makefile.in: Regenerated.
* patches/icedtea-gervill.patch: New patch.
* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*:
New Gervill files.
author | Mark Wielaard <mark@klomp.org> |
---|---|
date | Wed, 30 Apr 2008 22:09:08 +0200 |
parents | |
children |
line wrap: on
line source
/* * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package com.sun.media.sound; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; /** * A jitter corrector to be used with SoftAudioPusher. * * @version %I%, %E% * @author Karl Helgason */ public class SoftJitterCorrector extends AudioInputStream { private static class JitterStream extends InputStream { static int MAX_BUFFER_SIZE = 1048576; boolean active = true; Thread thread; AudioInputStream stream; // Cyclic buffer int writepos = 0; int readpos = 0; byte[][] buffers; byte[] nullbuff; // Adapative Drift Statistics int w_count = 1000; int w_min_tol = 2; int w_max_tol = 10; int w = 0; int w_min = -1; // Current read buffer int bbuffer_pos = 0; int bbuffer_max = 0; byte[] bbuffer = null; public byte[] nextReadBuffer() { synchronized(buffers) { if(writepos > readpos) { int w_m = writepos - readpos; if(w_m < w_min) w_min = w_m; int buffpos = readpos; readpos++; return buffers[buffpos % buffers.length]; } w_min = -1; w = w_count-1; } while(true) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); return null; } synchronized(buffers) { if(writepos > readpos) { w = 0; w_min = -1; w = w_count-1; int buffpos = readpos; readpos++; return buffers[buffpos % buffers.length]; } } } } public byte[] nextWriteBuffer() { synchronized(buffers) { return buffers[writepos % buffers.length]; } } public void commit() { synchronized(buffers) { writepos++; if((writepos - readpos) > buffers.length) { int newsize = (writepos - readpos) + 10; newsize = Math.max(buffers.length*2, newsize); buffers = new byte[newsize][buffers[0].length]; } } } public JitterStream(AudioInputStream s, int buffersize, int smallbuffersize) { this.w_count = 10 * (buffersize/smallbuffersize); if(w_count < 100) w_count = 100; this.buffers = new byte[(buffersize/smallbuffersize)+10][smallbuffersize]; this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize; this.nullbuff = new byte[smallbuffersize]; this.stream = s; Runnable runnable = new Runnable() { public void run() { AudioFormat format = stream.getFormat(); int bufflen = buffers[0].length; int frames = bufflen / format.getFrameSize(); long nanos = (long) ( frames * 1000000000.0 / format.getSampleRate() ); long now = System.nanoTime(); long next = now + nanos; int correction = 0; while(true) { synchronized (JitterStream.this) { if(!active) break; } int curbuffsize; synchronized (buffers) { curbuffsize = writepos - readpos; if(correction == 0) { w++; if(w_min != Integer.MAX_VALUE) if(w == w_count) { correction = 0; if(w_min < w_min_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min; if(w_min > w_max_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min; w = 0; w_min = Integer.MAX_VALUE; } } } while(curbuffsize > bbuffer_max) { synchronized (buffers) { curbuffsize = writepos - readpos; } synchronized (JitterStream.this) { if(!active) break; } try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } if(correction < 0) { correction++; } else { byte[] buff = nextWriteBuffer(); try { stream.read(buff, 0, buff.length); } catch (IOException e1) { e1.printStackTrace(); } commit(); } if(correction > 0) { correction--; next = System.nanoTime() + nanos; continue; } long wait = next - System.nanoTime(); if(wait > 0) { try { Thread.sleep(wait / 1000000L); } catch (InterruptedException e) { e.printStackTrace(); } } next += nanos; } } }; thread = new Thread(runnable); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } public void close() throws IOException { synchronized (this) { active = false; } try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } stream.close(); } public int read() throws IOException { byte[] b = new byte[1]; if (read(b) == -1) return -1; return b[0] & 0xFF; } public void fillBuffer() { bbuffer = nextReadBuffer(); bbuffer_pos = 0; } public int read(byte[] b, int off, int len) { if(bbuffer == null) fillBuffer(); int bbuffer_len = bbuffer.length; int offlen = off + len; while (off < offlen) if (available() == 0) fillBuffer(); else { byte[] bbuffer = this.bbuffer; int bbuffer_pos = this.bbuffer_pos; while (off < offlen && bbuffer_pos < bbuffer_len) b[off++] = bbuffer[bbuffer_pos++]; this.bbuffer_pos = bbuffer_pos; } return len; } public int available() { return bbuffer.length - bbuffer_pos; } }; public SoftJitterCorrector(AudioInputStream stream, int buffersize, int smallbuffersize) { super(new JitterStream(stream, buffersize, smallbuffersize), stream.getFormat(), stream .getFrameLength()); } }