/* * Created on Jun 13, 2006 * * Copyright (c) 2006 P.J.Leonard * * http://www.frinika.com * * This file is part of Frinika. * * Frinika is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Frinika 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 for more details. * You should have received a copy of the GNU General Public License * along with Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.sequencer.gui; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.TargetDataLine; import uk.org.toot.audio.server.AudioServer; public class MixerAudioDeviceHandle implements AudioDeviceHandle { private Mixer mixer; private AudioFormat af; private DataLine.Info info; private TargetDataLine line; private AudioServer server; private byte inBuffer[]; public MixerAudioDeviceHandle(Mixer mixer, AudioFormat af, DataLine.Info info, AudioServer server) { this.mixer = mixer; this.af = af; this.info = info; this.line = null; this.server = server; } public String toString() { if (af.getChannels() == 1) return mixer.getMixerInfo().getName() + " (MONO)"; // + // af.toString(); else if (af.getChannels() == 2) return mixer.getMixerInfo().getName() + " (STEREO)"; // + // af.toString(); else return mixer.getMixerInfo().getName() + "channels=" + af.getChannels(); // + af.toString(); } /** *@deprecated To be rpelaced with COnnections */ public TargetDataLine getLine() { // DataLine.Info infoIn) { try { System.out.println(this + " **** " + af); DataLine.Info infoIn = new DataLine.Info(TargetDataLine.class, af); // lineIn = // (TargetDataLine)AudioSystem.getMixer(mixers.get(0)).getLine(infoIn); line = (TargetDataLine) mixer.getLine(infoIn); } catch (LineUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public void fillBuffers(int nFrame) { // System.out.println(" Dev fill buffer "); try { // 2 channels out but 2 byte per in sample int nByte = af.getChannels()*nFrame*2; if (inBuffer == null || inBuffer.length != nByte ) inBuffer=new byte[nByte]; // TODO: Why would nByte be 0 anyway? This is a quick fix if (line.available() >= nByte && nByte > 0) { int nread; int cnt = 0; /** * If we have glitches in the output, this means that there will * be more data in the input buffer than we are able to handle * in this fillBuffer session. Unless we compensate here by * skipping data from the input, the software monitoring would * have introduced an extra delay. However we don't want to skip * this data in the recording, so what we do is to put all this * samples in the recordbuffer, but skip to send them to the * preoscillator sample buffer. */ do { nread = line.read(inBuffer, 0, nByte); if (nread == 0) System.out.println("active :" + line.isActive() + " available:" + line.available() + " nByte: " + nByte + " inBuffersize: " + inBuffer.length); //inputFramesReadCount += nByte / 2 / af.getChannels(); cnt++; for (int n = 0; n < nByte / 2; n++) { short sample = (short) ((0xff & inBuffer[2 * n + 1]) + ((0xff & inBuffer[2 * n]) * 256)); float val = sample / 32768f; } } while (line.available() > 2 * nByte); if (cnt != 1) System.out.println(" COUNT WAS " + cnt); } else { System.err.println(String.format(" GLITCH avail=%d actual=%d ",line.available(),nByte )); } } catch (Exception e) { e.printStackTrace(); } } /** * @deprecated TO be replaced by Connections */ public TargetDataLine getOpenLine() { if (isOpen()) return line; // TODO Auto-generated method stub try { if (line == null) line = (TargetDataLine) mixer.getLine(info); line.open(af); return line; } catch (LineUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } // public void start() { // line.flush(); // line.start(); // // } public int getChannels() { return af.getChannels(); } public AudioFormat getFormat() { return af; } public boolean isOpen() { if (line == null) return false; return line.isOpen(); } /** * open and start the line. */ public void open() { System.out.println(" Opening MixrerAudioDevice line"); if (isOpen()) return; try { if (line == null) line = (TargetDataLine) mixer.getLine(info); line.open(af); System.out.println(" . . .. Open"); line.start(); System.out.println(" . . .. Start " + isOpen()); } catch (LineUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void close() { if (!isOpen()) return; line.close(); } public byte[] getBuffer() { // TODO Auto-generated method stub return inBuffer; } }