/* * @(#)JavaSoundRenderer.java 1.34 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package com.sun.media.renderer.audio; import java.util.*; import java.awt.*; import java.io.*; import java.lang.reflect.Constructor; import javax.media.*; import javax.media.format.*; import javax.media.format.AudioFormat; import com.sun.media.*; import com.sun.media.util.*; import com.sun.media.controls.*; import com.sun.media.renderer.audio.device.*; import com.ibm.media.codec.audio.ulaw.JavaDecoder; /** * JavaSoundRenderer * @version */ public class JavaSoundRenderer extends AudioRenderer implements ExclusiveUse { static String NAME = "JavaSound Renderer"; Codec ulawDecoder; javax.media.Format ulawOutputFormat; javax.media.Format ulawFormat, linearFormat; static int METERHEIGHT = 4; static boolean available = false; static { String javaVersion = null; String subver = null; int len; try { javaVersion = (String)System.getProperty("java.version"); if ( javaVersion.length() < 3 ) len = javaVersion.length(); else len = 3; subver = javaVersion.substring(0,len); } catch (Throwable t) { javaVersion = null; subver = null; } if ( (subver == null) || (subver.compareTo("1.3") < 0)) { try { JMFSecurityManager.loadLibrary("jmutil"); JMFSecurityManager.loadLibrary("jsound"); available = true; } catch (Throwable t) { } } else { available = true; } } public JavaSoundRenderer() { super(); if (!available) throw new UnsatisfiedLinkError("No JavaSound library"); ulawFormat = new javax.media.format.AudioFormat( AudioFormat.ULAW); linearFormat = new javax.media.format.AudioFormat( AudioFormat.LINEAR); supportedFormats = new javax.media.Format[2]; supportedFormats[0] = linearFormat; supportedFormats[1] = ulawFormat; gainControl = new GCA(this); peakVolumeMeter = new PeakVolumeMeter(this); } public String getName() { return NAME; } public void open() throws ResourceUnavailableException { if (device == null && inputFormat != null) { if (!initDevice(inputFormat)) throw new ResourceUnavailableException("Cannot intialize audio device for playback"); device.pause(); } } public boolean isExclusive() { // JavaSound can mix audio return false; } protected boolean initDevice(javax.media.format.AudioFormat in) { javax.media.Format newInput = in; // Free the old ulaw decoder if there's one. if (ulawDecoder != null) { ulawDecoder.close(); ulawDecoder = null; } // Initialize a ulaw decoder if the input format is ulaw. Format outs[] = new Format[1]; if (ulawFormat.matches(in)) { ulawDecoder = SimpleGraphBuilder.findCodec(in, linearFormat, null, outs); if (ulawDecoder != null) { ulawOutputFormat = newInput = outs[0]; } else return false; } devFormat = in; return super.initDevice((javax.media.format.AudioFormat)newInput); } protected AudioOutput createDevice(javax.media.format.AudioFormat format) { return new JavaSoundOutput(); } Buffer decodeBuffer = null; public int processData(Buffer buffer) { if (!checkInput(buffer)) return BUFFER_PROCESSED_FAILED; // Processing linear data if (ulawDecoder == null) { try { ((PeakVolumeMeter)peakVolumeMeter).processData(buffer); } catch (Throwable t) { t.printStackTrace(); } return super.doProcessData(buffer); } // Pre-processing ulaw data, then feed it into JavaSound. if (decodeBuffer == null) { decodeBuffer = new Buffer(); decodeBuffer.setFormat(ulawOutputFormat); } decodeBuffer.setLength(0); decodeBuffer.setOffset(0); decodeBuffer.setFlags(buffer.getFlags()); decodeBuffer.setTimeStamp(buffer.getTimeStamp()); decodeBuffer.setSequenceNumber(buffer.getSequenceNumber()); int rc = ulawDecoder.process(buffer, decodeBuffer); if (rc == BUFFER_PROCESSED_OK) { try { ((PeakVolumeMeter)peakVolumeMeter).processData(decodeBuffer); } catch (Throwable t) { System.err.println(t); } return super.doProcessData(decodeBuffer); } return BUFFER_PROCESSED_FAILED; } public Object [] getControls() { Control c[] = new Control[] { gainControl, bufferControl, peakVolumeMeter }; return c; } class GCA extends GainControlAdapter { AudioRenderer renderer; protected GCA(AudioRenderer r) { super(false); renderer = r; } public void setMute(boolean mute) { if (renderer != null && renderer.device != null) renderer.device.setMute(mute); super.setMute(mute); } public float setLevel(float g) { float level = super.setLevel(g); if (renderer != null && renderer.device != null) renderer.device.setGain(getDB()); return level; } } class PeakVolumeMeter implements Control, Owned { int averagePeak = 0; int lastPeak = 0; Panel component = null; Checkbox cbEnabled = null; Canvas canvas = null; AudioRenderer renderer; long lastResetTime; Graphics cGraphics = null; public PeakVolumeMeter(AudioRenderer r) { this.renderer = r; lastResetTime = System.currentTimeMillis(); } public Object getOwner() { return renderer; } public Component getControlComponent() { if (component == null) { canvas = new Canvas() { public Dimension getPreferredSize() { return new Dimension(102, METERHEIGHT); } }; cbEnabled = new Checkbox("Peak Volume Meter", false); component = new Panel(); component.add(cbEnabled); component.add(canvas); canvas.setBackground(Color.black); } return component; } public void processData(Buffer buf) { AudioFormat af = (AudioFormat) buf.getFormat(); int index = 0; int peak = 0; int inc = 2; if (component == null) return; if (!cbEnabled.getState()) return; byte [] data = (byte[]) buf.getData(); boolean signed; if (buf.isDiscard()) return; if (buf.getLength() <= 0) return; if (af.getEndian() == AudioFormat.LITTLE_ENDIAN) index = 1; signed = af.getSigned() == AudioFormat.SIGNED; if (af.getSampleSizeInBits() == 8) inc = 1; if (signed) { for (int i = index; i < buf.getLength(); i += (inc * 5)) { int d = data[i]; if (d < 0) d = -d; if (d > peak) peak = d; } peak = (peak * 100) / 127; } else { for (int i = index; i < buf.getLength(); i += (inc * 5)) { if ((data[i] & 0xFF) > peak) peak = (data[i] & 0xFF); } peak = (peak * 100) / 255; } averagePeak = (peak + averagePeak) / 2; long currentTime = System.currentTimeMillis(); if (currentTime > lastResetTime + 100) { lastResetTime = currentTime; updatePeak(averagePeak); averagePeak = peak; } } private void updatePeak(int newPeak) { if (canvas == null) return; if (cGraphics == null) { cGraphics = canvas.getGraphics(); } if (cGraphics == null) return; if (newPeak > 99) newPeak = 99; cGraphics.setColor(Color.green); if (newPeak < 80) { cGraphics.drawLine(1, 1, newPeak + 1, 1); cGraphics.drawLine(1, 2, newPeak + 1, 2); } else { cGraphics.drawLine(1, 1, 80 + 1, 1); cGraphics.drawLine(1, 2, 80 + 1, 2); cGraphics.setColor(Color.yellow); if (newPeak < 90) { cGraphics.drawLine( 80 + 1, 1, newPeak + 1, 1); cGraphics.drawLine( 80 + 1, 2, newPeak + 1, 2); } else { cGraphics.drawLine( 80 + 1, 1, 90 + 1, 1); cGraphics.drawLine( 80 + 1, 2, 90 + 1, 2); cGraphics.setColor(Color.red); cGraphics.drawLine( 90 + 1, 1, newPeak + 1, 1); cGraphics.drawLine( 90 + 1, 2, newPeak + 1, 2); } } cGraphics.setColor(Color.black); cGraphics.drawLine( newPeak + 2, 1, 102, 1); cGraphics.drawLine( newPeak + 2, 2, 102, 2); lastPeak = newPeak; } } }