All Downloads are FREE. Search and download functionalities are using the official Maven repository.

be.tarsos.dsp.beatroot.Peaks Maven / Gradle / Ivy

There is a newer version: 2.4-1
Show newest version
/*
*      _______                       _____   _____ _____  
*     |__   __|                     |  __ \ / ____|  __ \ 
*        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
*        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
*        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
*        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
*                                                         
* -------------------------------------------------------------
*
* TarsosDSP is developed by Joren Six at IPEM, University Ghent
*  
* -------------------------------------------------------------
*
*  Info: http://0110.be/tag/TarsosDSP
*  Github: https://github.com/JorenSix/TarsosDSP
*  Releases: http://0110.be/releases/TarsosDSP/
*  
*  TarsosDSP includes modified source code by various authors,
*  for credits and info, see README.
* 
*/

/*
	Copyright (C) 2001, 2006 by Simon Dixon

	This program 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.

	This program 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 this program (the file gpl.txt); if not, download it from
	http://www.gnu.org/licenses/gpl.txt or write to the
	Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package be.tarsos.dsp.beatroot;

import java.util.LinkedList;

public class Peaks {

	public static boolean debug = false;
	public static int pre = 3;
	public static int post = 1;
	
	/** 
	 * General peak picking method for finding n local maxima in an array
	 *  @param data input data
	 *  @param peaks list of peak indexes
	 *  @param width minimum distance between peaks
	 *  @return The number of peaks found
	 */
	public static int findPeaks(double[] data, int[] peaks, int width) {
		int peakCount = 0;
		int maxp = 0;
		int mid = 0;
		int end = data.length;
		while (mid < end) {
			int i = mid - width;
			if (i < 0)
				i = 0;
			int stop = mid + width + 1;
			if (stop > data.length)
				stop = data.length;
			maxp = i;
			for (i++; i < stop; i++)
				if (data[i] > data[maxp])
					maxp = i;
			if (maxp == mid) {
				int j;
				for (j = peakCount; j > 0; j--) {
					if (data[maxp] <= data[peaks[j-1]])
						break;
					else if (j < peaks.length)
						peaks[j] = peaks[j-1];
				}
				if (j != peaks.length)
					peaks[j] = maxp;
				if (peakCount != peaks.length)
					peakCount++;
			}
			mid++;
		}
		return peakCount;
	} // findPeaks()

	/** General peak picking method for finding local maxima in an array
	 *  @param data input data
	 *  @param width minimum distance between peaks
	 *  @param threshold minimum value of peaks
	 *  @return list of peak indexes
	 */
	public static LinkedList findPeaks(double[] data, int width,
												double threshold) {
		return findPeaks(data, width, threshold, 0, false);
	} // findPeaks()
	
	/** General peak picking method for finding local maxima in an array
	 *  @param data input data
	 *  @param width minimum distance between peaks
	 *  @param threshold minimum value of peaks
	 *  @param decayRate how quickly previous peaks are forgotten
	 *  @param isRelative minimum value of peaks is relative to local average
	 *  @return list of peak indexes
	 */
	public static LinkedList findPeaks(double[] data, int width,
				double threshold, double decayRate, boolean isRelative) {
		LinkedList peaks = new LinkedList();
		int maxp = 0;
		int mid = 0;
		int end = data.length;
		double av = data[0];
		while (mid < end) {
			av = decayRate * av + (1 - decayRate) * data[mid];
			if (av < data[mid])
				av = data[mid];
			int i = mid - width;
			if (i < 0)
				i = 0;
			int stop = mid + width + 1;
			if (stop > data.length)
				stop = data.length;
			maxp = i;
			for (i++; i < stop; i++)
				if (data[i] > data[maxp])
					maxp = i;
			if (maxp == mid) {
				if (overThreshold(data, maxp, width, threshold, isRelative,av)){
					if (debug)
						System.out.println(" peak");
					peaks.add(new Integer(maxp));
				} else if (debug)
					System.out.println();
			}
			mid++;
		}
		return peaks;
	} // findPeaks()

	public static double expDecayWithHold(double av, double decayRate,
										  double[] data, int start, int stop) {
		while (start < stop) {
			av = decayRate * av + (1 - decayRate) * data[start];
			if (av < data[start])
				av = data[start];
			start++;
		}
		return av;
	} // expDecayWithHold()

	public static boolean overThreshold(double[] data, int index, int width,
										double threshold, boolean isRelative,
										double av) {
		if (debug)
			System.out.printf("%4d : %6.3f     Av1: %6.3f    ",
								index, data[index], av);
		if (data[index] < av)
			return false;
		if (isRelative) {
			int iStart = index - pre * width;
			if (iStart < 0)
				iStart = 0;
			int iStop = index + post * width;
			if (iStop > data.length)
				iStop = data.length;
			double sum = 0;
			int count = iStop - iStart;
			while (iStart < iStop)
				sum += data[iStart++];
			if (debug)
				System.out.printf("    %6.3f    %6.3f   ", sum / count,
							data[index] - sum / count - threshold);
			return (data[index] > sum / count + threshold);
		} else
			return (data[index] > threshold);
	} // overThreshold()

	public static void normalise(double[] data) {
		double sx = 0;
		double sxx = 0;
		for (int i = 0; i < data.length; i++) {
			sx += data[i];
			sxx += data[i] * data[i];
		}
		double mean = sx / data.length;
		double sd = Math.sqrt((sxx - sx * mean) / data.length);
		if (sd == 0)
			sd = 1;		// all data[i] == mean  -> 0; avoids div by 0
		for (int i = 0; i < data.length; i++) {
			data[i] = (data[i] - mean) / sd;
		}
	} // normalise()

	/** Uses an n-point linear regression to estimate the slope of data.
	 *  @param data input data
	 *  @param hop spacing of data points
	 *  @param n length of linear regression
	 *  @param slope output data
	 */
	public static void getSlope(double[] data, double hop, int n,
								double[] slope) {
		int i = 0, j = 0;
		double t;
		double sx = 0, sxx = 0, sy = 0, sxy = 0;
		for ( ; i < n; i++) {
			t = i * hop;
			sx += t;
			sxx += t * t;
			sy += data[i];
			sxy += t * data[i];
		}
		double delta = n * sxx - sx * sx;
		for ( ; j < n / 2; j++)
			slope[j] = (n * sxy - sx * sy) / delta;
		for ( ; j < data.length - (n + 1) / 2; j++, i++) {
			slope[j] = (n * sxy - sx * sy) / delta;
			sy += data[i] - data[i - n];
			sxy += hop * (n * data[i] - sy);
		}
		for ( ; j < data.length; j++)
			slope[j] = (n * sxy - sx * sy) / delta;
	} // getSlope()

	public static double min(double[] arr) { return arr[imin(arr)]; }

	public static double max(double[] arr) { return arr[imax(arr)]; }

	public static int imin(double[] arr) {
		int i = 0;
		for (int j = 1; j < arr.length; j++)
			if (arr[j] < arr[i])
				i = j;
		return i;
	} // imin()

	public static int imax(double[] arr) {
		int i = 0;
		for (int j = 1; j < arr.length; j++)
			if (arr[j] > arr[i])
				i = j;
		return i;
	} // imax()

} // class Peaks




© 2015 - 2024 Weber Informatics LLC | Privacy Policy