/* * Created on Feb 14, 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.audio.analysis; import com.frinika.util.math.MyMath; public class PeakAnalyst { double peakShort; double peakLong; double decayShort; double decayLong; double riseShort; double riseLong; double decayShort1; double decayLong1; double riseShort1; double riseLong1; double riseInf; double decayInf; double riseInf1; double decayInf1; double average; double noiseLevel; // double hsyterFact; // // boolean hold; double rate; int frameSize; Thread pulseWaitThread; int pulseTimeInSamples; long sampleCount; long pulseCount; static PeakAnalyst the; /** * * @param feed * FramedFeed * @param shortT * double decay time to smooth out freq time scale stuff. * @param longT * double decay Time to suss out pulses in the music. */ static public PeakAnalyst the() { return the; } // public PeakAnalyst(FramedFeed feed) { public PeakAnalyst() { assert (the == null); the = this; //this.rate = feed.getSampleRate(); // feed.addFramedFeedListener(this); this.decayShort = MyMath.halfLifeToLambda(this.rate / 100); this.riseShort = MyMath.halfLifeToLambda(this.rate / 500); this.decayLong = MyMath.halfLifeToLambda(this.rate * 0.2); this.riseLong = MyMath.halfLifeToLambda(this.rate * 0.02); this.decayInf = MyMath.halfLifeToLambda(this.rate * 5); this.riseInf = MyMath.halfLifeToLambda(this.rate * 5); /* * System.out.println( decayShort); System.out.println( riseShort); * System.out.println( decayLong); System.out.println( riseLong); * System.out.println( decayInf); System.out.println( riseInf); */ this.decayShort1 = 1.0 - this.decayShort; this.riseShort1 = 1.0 - this.riseShort; this.decayLong1 = 1.0 - this.decayLong; this.riseLong1 = 1.0 - this.riseLong; this.decayInf1 = 1.0 - this.decayInf; this.riseInf1 = 1.0 - this.riseInf; //this.frameSize = feed.getWindowSize(); } public void fireNewFramedFeedData(short[] v) { int n = v.length; for (int i = 0; i < n; i++) { this.sampleCount++; double val = Math.abs(v[i]); if (val < this.peakShort) this.peakShort = this.peakShort * this.decayShort + val * this.decayShort1; else this.peakShort = this.peakShort * this.riseShort + val * this.riseShort1; if (this.peakShort < this.peakLong) this.peakLong = this.peakLong * this.decayLong + this.peakShort * this.decayLong1; else this.peakLong = this.peakLong * this.riseLong + this.peakShort * this.riseLong1; if (this.peakLong < this.average) this.average = this.average * this.decayInf + this.peakLong * this.decayInf1; else this.average = this.average * this.riseInf + this.peakLong * this.riseInf1; if (this.peakLong > this.average && this.pulseWaitThread != null) { this.pulseCount = this.sampleCount; this.pulseWaitThread.interrupt(); this.pulseWaitThread = null; } } // System.out.println(peakShort + " " + peakLong + " " + average); } public synchronized long waitForPulse(long milliMax) { assert (this.pulseWaitThread == null); this.pulseWaitThread = Thread.currentThread(); try { wait(milliMax); System.out.println(" waitForPulse timed out"); this.pulseWaitThread = null; } catch (InterruptedException ex) { this.pulseWaitThread = null; return (long) ((this.pulseCount * 1000.0) / this.rate); } return -1; } }