/* * @(#)JavaSoundOutput.java 1.27 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package com.sun.media.renderer.audio.device; import java.io.*; import javax.sound.sampled.*; import javax.sound.sampled.AudioFormat.Encoding; import com.sun.media.*; //import javax.sound.sampled.FloatControl.*; //import javax.sound.sampled.BooleanControl.*; public class JavaSoundOutput implements AudioOutput { static Mixer mixer = null; static Object initSync = new Object(); protected SourceDataLine dataLine; protected FloatControl gc; protected FloatControl rc; protected BooleanControl mc; protected boolean paused = true; protected int bufSize; protected javax.media.format.AudioFormat format; public JavaSoundOutput() { } public boolean initialize(javax.media.format.AudioFormat format, int bufSize) { synchronized (initSync) { DataLine.Info info; javax.sound.sampled.AudioFormat afmt; afmt = convertFormat(format); //System.err.println("Render buffer size = " + bufSize); info = new DataLine.Info(SourceDataLine.class, afmt, bufSize); try { if (!AudioSystem.isLineSupported(info)) { Log.warning("DataLine not supported: " + format); return false; } dataLine = (SourceDataLine)AudioSystem.getLine(info); dataLine.open(afmt, bufSize); } catch (Exception e) { Log.warning("Cannot open audio device: " + e); return false; } this.format = format; this.bufSize = bufSize; if (dataLine == null) { Log.warning("JavaSound unsupported format: " + format); return false; } try { gc = (FloatControl)dataLine.getControl(FloatControl.Type.MASTER_GAIN); mc = (BooleanControl)dataLine.getControl(BooleanControl.Type.MUTE); } catch (Exception e) { Log.warning("JavaSound: No gain control"); } try { rc = (FloatControl)dataLine.getControl(FloatControl.Type.SAMPLE_RATE); } catch (Exception e) { Log.warning("JavaSound: No rate control"); } return true; } } // $$ AudioRenderer's abortPrefetch() calls this method public void dispose() { dataLine.close(); } public void finalize() throws Throwable { super.finalize(); dispose(); } public void pause() { if (dataLine != null) dataLine.stop(); paused = true; } public void resume() { if (dataLine != null) dataLine.start(); paused = false; } // Remove this method public void drain() { dataLine.drain(); } // Clean the buffer. public void flush() { dataLine.flush(); } public javax.media.format.AudioFormat getFormat() { return format; } long lastPos = 0; long originPos = 0; long totalCount = 0; public long getMediaNanoseconds() { if (dataLine == null || format == null) return 0; long pos = dataLine.getFramePosition(); if (pos < lastPos) { // Wraps around. totalCount += lastPos - originPos; originPos = pos; } lastPos = pos; return (long)(((totalCount + pos - originPos) * 1000 / format.getSampleRate()) * 1000000); } public void setGain(double g) { if (gc != null) gc.setValue((float)g); } public double getGain() { return (gc != null ? gc.getValue() : 0); } public void setMute(boolean m) { if (mc != null) mc.setValue(m); } public boolean getMute() { return (mc != null ? mc.getValue() : false); } public float setRate(float r) { if (rc == null) return 1.0f; float rate = (float)(r * format.getSampleRate()); if (rate > rc.getMaximum() || rate < rc.getMinimum()) return getRate(); rc.setValue(rate); return r; } public float getRate() { if (rc == null) return 1.0f; return (float)(rc.getValue() / format.getSampleRate()); } public int bufferAvailable() { return dataLine.available(); } public int write(byte data[], int off, int len) { return dataLine.write(data, off, len); } public static boolean isOpen() { Mixer mixer = AudioSystem.getMixer(null); Line lines[] = mixer.getSourceLines(); return (lines != null && lines.length > 0); } /** * Convert a JavaSound format to a JMF format. */ public static javax.media.format.AudioFormat convertFormat( javax.sound.sampled.AudioFormat fmt) { Encoding type = fmt.getEncoding(); String encoding; if (type == Encoding.PCM_SIGNED || type == Encoding.PCM_UNSIGNED) encoding = javax.media.format.AudioFormat.LINEAR; else if (type == Encoding.ALAW) encoding = javax.media.format.AudioFormat.ALAW; else if (type == Encoding.ULAW) encoding = javax.media.format.AudioFormat.ULAW; else encoding = null; return new javax.media.format.AudioFormat( encoding, fmt.getSampleRate(), fmt.getSampleSizeInBits(), fmt.getChannels(), (fmt.isBigEndian() ? javax.media.format.AudioFormat.BIG_ENDIAN : javax.media.format.AudioFormat.LITTLE_ENDIAN), (type == Encoding.PCM_SIGNED ? javax.media.format.AudioFormat.SIGNED : javax.media.format.AudioFormat.UNSIGNED)); } /** * Convert a JMF format to a JavaSound format. */ public static javax.sound.sampled.AudioFormat convertFormat( javax.media.format.AudioFormat fmt) { return new javax.sound.sampled.AudioFormat( (fmt.getSampleRate() == javax.media.format.AudioFormat.NOT_SPECIFIED ? 8000f : (float)fmt.getSampleRate()), (fmt.getSampleSizeInBits() == javax.media.format.AudioFormat.NOT_SPECIFIED ? 16 : fmt.getSampleSizeInBits()), (fmt.getChannels() == javax.media.format.AudioFormat.NOT_SPECIFIED ? 1 : fmt.getChannels()), (fmt.getSigned() == javax.media.format.AudioFormat.SIGNED ? true : false), (fmt.getEndian() == javax.media.format.AudioFormat.BIG_ENDIAN ? true : false)); } }