/* * Created on Dec 14, 2004 * * Copyright (c) 2005 Peter Johan Salomonsen (http://www.petersalomonsen.com) * * 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.benchmark.audio; import javax.sound.sampled.TargetDataLine; import com.frinika.benchmark.SyncVoice; import com.frinika.global.FrinikaConfig; import com.frinika.sequencer.FrinikaSequencer; import com.frinika.sequencer.gui.AudioDeviceHandle; /** * Use for capturing inputs and for direct monitoring. Based on Peters Sampler * code. * * @author pjl * @author Peter Johan Salomonsen * */ public class ClickListener extends SyncVoice { TargetDataLine lineIn = null; byte[] inBuffer; FrinikaSequencer sequencer; static int OFF = 0; static int ARMED = 1; static int RECORDING = 2; AudioDeviceHandle audioDeviceHandle; int state = OFF; int nChannel = 0; long framePtrLast=0; // remember the last sample so we can correct if there is a glitch OR song postion change float thresh; boolean monit; private ClickOscillator out; public ClickListener(FrinikaSequencer seq, boolean monit, ClickOscillator out,float thresh) { super(seq); this.monit = monit; this.out = out; this.thresh=thresh; } public void setAudioDeviceHandle(AudioDeviceHandle audio) { audioDeviceHandle = audio; nChannel = audioDeviceHandle.getChannels(); System.out.println(audioDeviceHandle.toString() + " " + nChannel); } public void fillBuffer(int startBufferPos, int endBufferPos, float[] buffer) { try { if (lineIn == null) { lineIn = audioDeviceHandle.getOpenLine(); lineIn.start(); } if (inBuffer == null || inBuffer.length != buffer.length * nChannel) inBuffer = new byte[buffer.length * nChannel]; if (glitched) doSync(0); // 2 channels out but 2 byte per in sample int nByte = nChannel * (endBufferPos - startBufferPos); if (lineIn.available() >= nByte) { int nread; int cnt = 0; do { nread = lineIn.read(inBuffer, 0, nByte); cnt++; } while (lineIn.available() > 2 * nByte); if (cnt != 1) { System.err.println(" LineIn OVER RUN "); glitched = true; } 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; if (n % nChannel == 0) framePtr++; if (val > thresh) { long nF=(framePtr - out.clickFrame); double t= nF/FrinikaConfig.sampleRate; System.out.println(" latency in frames " + nF + " [ " +t + " secs]"); } if (monit) { if (nChannel == 1) { buffer[startBufferPos + 2 * n] += val; buffer[startBufferPos + 2 * n + 1] += val; } else { buffer[startBufferPos + n] += val; } } } } else { System.err.println(" LineIn UNDER RUN "); glitched = true; } } catch (Exception e) { e.printStackTrace(); } framePtrLast=framePtr; } @Override protected void correctGlitch() { // TODO Auto-generated method stub } }