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 javax.sound.sampled.AudioFormat;
28 import javax.sound.sampled.AudioInputStream;
29 import java.io.EOFException;
30 import java.io.IOException;
31 import java.io.InputStream;
32
33 /**
34 * A jitter corrector to be used with SoftAudioPusher.
35 *
36 * @author Karl Helgason
37 */
38 public final class SoftJitterCorrector extends AudioInputStream {
39
40 private static class JitterStream extends InputStream {
41
42 static int MAX_BUFFER_SIZE = 1048576;
43 boolean active = true;
44 Thread thread;
45 AudioInputStream stream;
46 // Cyclic buffer
47 int writepos = 0;
48 int readpos = 0;
49 byte[][] buffers;
50 private final Object buffers_mutex = new Object();
51
52 // Adapative Drift Statistics
107 int newsize = (writepos - readpos) + 10;
108 newsize = Math.max(buffers.length * 2, newsize);
109 buffers = new byte[newsize][buffers[0].length];
110 }
111 }
112 }
113
114 JitterStream(AudioInputStream s, int buffersize,
115 int smallbuffersize) {
116 this.w_count = 10 * (buffersize / smallbuffersize);
117 if (w_count < 100)
118 w_count = 100;
119 this.buffers
120 = new byte[(buffersize/smallbuffersize)+10][smallbuffersize];
121 this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize;
122 this.stream = s;
123
124
125 Runnable runnable = new Runnable() {
126
127 public void run() {
128 AudioFormat format = stream.getFormat();
129 int bufflen = buffers[0].length;
130 int frames = bufflen / format.getFrameSize();
131 long nanos = (long) (frames * 1000000000.0
132 / format.getSampleRate());
133 long now = System.nanoTime();
134 long next = now + nanos;
135 int correction = 0;
136 while (true) {
137 synchronized (JitterStream.this) {
138 if (!active)
139 break;
140 }
141 int curbuffsize;
142 synchronized (buffers) {
143 curbuffsize = writepos - readpos;
144 if (correction == 0) {
145 w++;
146 if (w_min != Integer.MAX_VALUE) {
203 }
204 long wait = next - System.nanoTime();
205 if (wait > 0) {
206 try {
207 Thread.sleep(wait / 1000000L);
208 } catch (InterruptedException e) {
209 //e.printStackTrace();
210 }
211 }
212 next += nanos;
213 }
214 }
215 };
216
217 thread = new Thread(null, runnable, "JitterCorrector", 0, false);
218 thread.setDaemon(true);
219 thread.setPriority(Thread.MAX_PRIORITY);
220 thread.start();
221 }
222
223 public void close() throws IOException {
224 synchronized (this) {
225 active = false;
226 }
227 try {
228 thread.join();
229 } catch (InterruptedException e) {
230 //e.printStackTrace();
231 }
232 stream.close();
233 }
234
235 public int read() throws IOException {
236 byte[] b = new byte[1];
237 if (read(b) == -1)
238 return -1;
239 return b[0] & 0xFF;
240 }
241
242 public void fillBuffer() {
243 bbuffer = nextReadBuffer();
244 bbuffer_pos = 0;
245 }
246
247 public int read(byte[] b, int off, int len) {
248 if (bbuffer == null)
249 fillBuffer();
250 int bbuffer_len = bbuffer.length;
251 int offlen = off + len;
252 while (off < offlen) {
253 if (available() == 0)
254 fillBuffer();
255 else {
256 byte[] bbuffer = this.bbuffer;
257 int bbuffer_pos = this.bbuffer_pos;
258 while (off < offlen && bbuffer_pos < bbuffer_len)
259 b[off++] = bbuffer[bbuffer_pos++];
260 this.bbuffer_pos = bbuffer_pos;
261 }
262 }
263 return len;
264 }
265
266 public int available() {
267 return bbuffer.length - bbuffer_pos;
268 }
269 }
270
271 public SoftJitterCorrector(AudioInputStream stream, int buffersize,
272 int smallbuffersize) {
273 super(new JitterStream(stream, buffersize, smallbuffersize),
274 stream.getFormat(), stream.getFrameLength());
275 }
276 }
|
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.EOFException;
29 import java.io.IOException;
30 import java.io.InputStream;
31
32 import javax.sound.sampled.AudioFormat;
33 import javax.sound.sampled.AudioInputStream;
34
35 /**
36 * A jitter corrector to be used with SoftAudioPusher.
37 *
38 * @author Karl Helgason
39 */
40 public final class SoftJitterCorrector extends AudioInputStream {
41
42 private static class JitterStream extends InputStream {
43
44 static int MAX_BUFFER_SIZE = 1048576;
45 boolean active = true;
46 Thread thread;
47 AudioInputStream stream;
48 // Cyclic buffer
49 int writepos = 0;
50 int readpos = 0;
51 byte[][] buffers;
52 private final Object buffers_mutex = new Object();
53
54 // Adapative Drift Statistics
109 int newsize = (writepos - readpos) + 10;
110 newsize = Math.max(buffers.length * 2, newsize);
111 buffers = new byte[newsize][buffers[0].length];
112 }
113 }
114 }
115
116 JitterStream(AudioInputStream s, int buffersize,
117 int smallbuffersize) {
118 this.w_count = 10 * (buffersize / smallbuffersize);
119 if (w_count < 100)
120 w_count = 100;
121 this.buffers
122 = new byte[(buffersize/smallbuffersize)+10][smallbuffersize];
123 this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize;
124 this.stream = s;
125
126
127 Runnable runnable = new Runnable() {
128
129 @Override
130 public void run() {
131 AudioFormat format = stream.getFormat();
132 int bufflen = buffers[0].length;
133 int frames = bufflen / format.getFrameSize();
134 long nanos = (long) (frames * 1000000000.0
135 / format.getSampleRate());
136 long now = System.nanoTime();
137 long next = now + nanos;
138 int correction = 0;
139 while (true) {
140 synchronized (JitterStream.this) {
141 if (!active)
142 break;
143 }
144 int curbuffsize;
145 synchronized (buffers) {
146 curbuffsize = writepos - readpos;
147 if (correction == 0) {
148 w++;
149 if (w_min != Integer.MAX_VALUE) {
206 }
207 long wait = next - System.nanoTime();
208 if (wait > 0) {
209 try {
210 Thread.sleep(wait / 1000000L);
211 } catch (InterruptedException e) {
212 //e.printStackTrace();
213 }
214 }
215 next += nanos;
216 }
217 }
218 };
219
220 thread = new Thread(null, runnable, "JitterCorrector", 0, false);
221 thread.setDaemon(true);
222 thread.setPriority(Thread.MAX_PRIORITY);
223 thread.start();
224 }
225
226 @Override
227 public void close() throws IOException {
228 synchronized (this) {
229 active = false;
230 }
231 try {
232 thread.join();
233 } catch (InterruptedException e) {
234 //e.printStackTrace();
235 }
236 stream.close();
237 }
238
239 @Override
240 public int read() throws IOException {
241 byte[] b = new byte[1];
242 if (read(b) == -1)
243 return -1;
244 return b[0] & 0xFF;
245 }
246
247 public void fillBuffer() {
248 bbuffer = nextReadBuffer();
249 bbuffer_pos = 0;
250 }
251
252 @Override
253 public int read(byte[] b, int off, int len) {
254 if (bbuffer == null)
255 fillBuffer();
256 int bbuffer_len = bbuffer.length;
257 int offlen = off + len;
258 while (off < offlen) {
259 if (available() == 0)
260 fillBuffer();
261 else {
262 byte[] bbuffer = this.bbuffer;
263 int bbuffer_pos = this.bbuffer_pos;
264 while (off < offlen && bbuffer_pos < bbuffer_len)
265 b[off++] = bbuffer[bbuffer_pos++];
266 this.bbuffer_pos = bbuffer_pos;
267 }
268 }
269 return len;
270 }
271
272 @Override
273 public int available() {
274 return bbuffer.length - bbuffer_pos;
275 }
276 }
277
278 public SoftJitterCorrector(AudioInputStream stream, int buffersize,
279 int smallbuffersize) {
280 super(new JitterStream(stream, buffersize, smallbuffersize),
281 stream.getFormat(), stream.getFrameLength());
282 }
283 }
|