// Path: src/java/org/sidoh/peak_detection/StatefulPeakDetector.java
// public abstract class StatefulPeakDetector implements ValueListener {
// 	
// 	public abstract static class Builder {
// 		public abstract StatefulPeakDetector create(PeakListener peaks);
// 		
// 		public Builder withSmoothingFunction(StatefulSmoothingFunction.Builder smoothingFnBuilder) {
// 			if (smoothingFnBuilder == null) {
// 				return this;
// 			}
// 			else {
// 				return new StatefulSmoothedPeakDetector.Builder(smoothingFnBuilder, this);
// 			}
// 		}
// 	}
// 	
// 	private final PeakListener peaks;
// 	private int index;
// 	
// 	private static int counter = 0;
// 	protected int count;
// 	
// 	public StatefulPeakDetector(PeakListener peaks) {
// 		this.peaks = peaks;
// 		this.index = 0;
// 		count = counter++;
// 	}
// 	
// 	/**
// 	 * Informs the PeakListener that there is a peak at #index.
// 	 * 
// 	 * @param index
// 	 */
// 	protected final void offerPeak(int index, double value) {
// 		peaks.peakDetected(index, value);
// 	}
// 	
// 	/**
// 	 * 
// 	 */
// 	public final void offerNewValue(double value) {
// 		handleNewInput(index++, value);
// 	}
// 	
// 	/**
// 	 * Handles a new input value.
// 	 * 
// 	 * @param value
// 	 */
// 	protected abstract void handleNewInput(int index, double value);
// 	
// 	/**
// 	 * Get a Builder that creates instances of {@link StatefulSdsFromMeanPeakDetector}
// 	 * with the provided arguments.
// 	 * 
// 	 * @param windowWidth
// 	 * @param sds
// 	 * @return
// 	 */
// 	public static StatefulSdsFromMeanPeakDetector.Builder sdsFromMean(int windowWidth, double sds) {
// 		return new StatefulSdsFromMeanPeakDetector.Builder(windowWidth, sds);
// 	}
// 	
// 	/**
// 	 * Get a Builder that creates instances of {@link StatefulMeanDeltaPeakDetector}.
// 	 * 
// 	 * @param windowWidth
// 	 * @return
// 	 */
// 	public static StatefulMeanDeltaPeakDetector.Builder meanDelta(int windowWidth) {
// 		return new StatefulMeanDeltaPeakDetector.Builder(windowWidth);
// 	}
// }
// 
// Path: src/java/org/sidoh/peak_detection/StatelessPeakDetector.java
// public abstract class StatelessPeakDetector {
// 	/**
// 	 * Accepts a time series and returns the locations within the series that this 
// 	 * detector considers peaks. The locations should be 0-indexed from the first 
// 	 * thing in the time series.
// 	 * 
// 	 * @param series
// 	 * @return
// 	 */
// 	public abstract Iterable<Integer> findPeaks(Iterable<Double> values);
// }
// 
// Path: src/java/org/sidoh/song_recognition/signature/ConstellationMap.java
// public static class Star implements Serializable {
// 	private static final long serialVersionUID = 1851275921474044916L;
// 		
// 
// 	private final double time;
// 	private final double frequency;
// 	private final double intensity;
// 	private final int x;
// 	private final int y;
// 		
// 	public Star(final double time, final double frequency, final double intensity, final int x, final int y) {
// 		this.time = time;
// 		this.frequency = frequency;
// 		this.intensity = intensity;
// 		this.x = x;
// 		this.y = y;
// 	}
// 
// 	public double getTime() {
// 		return time;
// 	}
// 
// 	public double getFrequency() {
// 		return frequency;
// 	}
// 
// 	public double getIntensity() {
// 		return intensity;
// 	}
// 		
// 	public int getTick() {
// 		return x;
// 	}
// 		
// 	public int getBin() {
// 		return y;
// 	}
// 		
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + x;
// 		result = prime * result + y;
// 		return result;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		Star other = (Star) obj;
// 		if (x != other.x)
// 			return false;
// 		if (y != other.y)
// 			return false;
// 		return true;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Star [x=" + x + ", y=" + y + ", intensity=" + intensity + "]";
// 	}
// }


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import org.sidoh.io.ProgressNotifier;
import org.sidoh.io.ProgressNotifier.Builder;
import org.sidoh.peak_detection.PeakListener;
import org.sidoh.peak_detection.StatefulPeakDetector;
import org.sidoh.peak_detection.StatelessPeakDetector;
import org.sidoh.song_recognition.signature.ConstellationMap.Star;
import org.sidoh.song_recognition.spectrogram.Spectrogram;
package org.sidoh.song_recognition.signature;



public class ConstellationMapExtractor implements SpectrogramSignatureExtractor<ConstellationMapSignature> {
	
	private final StatefulPeakDetector.Builder peakDetector;
	private final double starDensityFactor;
	private final ProgressNotifier.Builder progressNotifer;
	private final int threadCount;
	private final StarBuffer.Builder bufferBuilder;
	
	public ConstellationMapExtractor(StatefulPeakDetector.Builder peakDetectorBuilder, 
			double starDensityFactor, 
			ProgressNotifier.Builder progressNotifer,
			StarBuffer.Builder bufferBuilder) {
		this(peakDetectorBuilder,
			starDensityFactor,
			progressNotifer,
			bufferBuilder,
			Runtime.getRuntime().availableProcessors());
	}
	
// Path: src/java/org/sidoh/peak_detection/StatefulPeakDetector.java
// public abstract class StatefulPeakDetector implements ValueListener {
// 	
// 	public abstract static class Builder {
// 		public abstract StatefulPeakDetector create(PeakListener peaks);
// 		
// 		public Builder withSmoothingFunction(StatefulSmoothingFunction.Builder smoothingFnBuilder) {
// 			if (smoothingFnBuilder == null) {
// 				return this;
// 			}
// 			else {
// 				return new StatefulSmoothedPeakDetector.Builder(smoothingFnBuilder, this);
// 			}
// 		}
// 	}
// 	
// 	private final PeakListener peaks;
// 	private int index;
// 	
// 	private static int counter = 0;
// 	protected int count;
// 	
// 	public StatefulPeakDetector(PeakListener peaks) {
// 		this.peaks = peaks;
// 		this.index = 0;
// 		count = counter++;
// 	}
// 	
// 	/**
// 	 * Informs the PeakListener that there is a peak at #index.
// 	 * 
// 	 * @param index
// 	 */
// 	protected final void offerPeak(int index, double value) {
// 		peaks.peakDetected(index, value);
// 	}
// 	
// 	/**
// 	 * 
// 	 */
// 	public final void offerNewValue(double value) {
// 		handleNewInput(index++, value);
// 	}
// 	
// 	/**
// 	 * Handles a new input value.
// 	 * 
// 	 * @param value
// 	 */
// 	protected abstract void handleNewInput(int index, double value);
// 	
// 	/**
// 	 * Get a Builder that creates instances of {@link StatefulSdsFromMeanPeakDetector}
// 	 * with the provided arguments.
// 	 * 
// 	 * @param windowWidth
// 	 * @param sds
// 	 * @return
// 	 */
// 	public static StatefulSdsFromMeanPeakDetector.Builder sdsFromMean(int windowWidth, double sds) {
// 		return new StatefulSdsFromMeanPeakDetector.Builder(windowWidth, sds);
// 	}
// 	
// 	/**
// 	 * Get a Builder that creates instances of {@link StatefulMeanDeltaPeakDetector}.
// 	 * 
// 	 * @param windowWidth
// 	 * @return
// 	 */
// 	public static StatefulMeanDeltaPeakDetector.Builder meanDelta(int windowWidth) {
// 		return new StatefulMeanDeltaPeakDetector.Builder(windowWidth);
// 	}
// }
// 
// Path: src/java/org/sidoh/peak_detection/StatelessPeakDetector.java
// public abstract class StatelessPeakDetector {
// 	/**
// 	 * Accepts a time series and returns the locations within the series that this 
// 	 * detector considers peaks. The locations should be 0-indexed from the first 
// 	 * thing in the time series.
// 	 * 
// 	 * @param series
// 	 * @return
// 	 */
// 	public abstract Iterable<Integer> findPeaks(Iterable<Double> values);
// }
// 
// Path: src/java/org/sidoh/song_recognition/signature/ConstellationMap.java
// public static class Star implements Serializable {
// 	private static final long serialVersionUID = 1851275921474044916L;
// 		
// 
// 	private final double time;
// 	private final double frequency;
// 	private final double intensity;
// 	private final int x;
// 	private final int y;
// 		
// 	public Star(final double time, final double frequency, final double intensity, final int x, final int y) {
// 		this.time = time;
// 		this.frequency = frequency;
// 		this.intensity = intensity;
// 		this.x = x;
// 		this.y = y;
// 	}
// 
// 	public double getTime() {
// 		return time;
// 	}
// 
// 	public double getFrequency() {
// 		return frequency;
// 	}
// 
// 	public double getIntensity() {
// 		return intensity;
// 	}
// 		
// 	public int getTick() {
// 		return x;
// 	}
// 		
// 	public int getBin() {
// 		return y;
// 	}
// 		
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + x;
// 		result = prime * result + y;
// 		return result;
// 	}
// 
// 	@Override
// 	public boolean equals(Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		Star other = (Star) obj;
// 		if (x != other.x)
// 			return false;
// 		if (y != other.y)
// 			return false;
// 		return true;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "Star [x=" + x + ", y=" + y + ", intensity=" + intensity + "]";
// 	}
// }


// Path: src/java/org/sidoh/song_recognition/signature/ConstellationMapExtractor.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import org.sidoh.io.ProgressNotifier;
import org.sidoh.io.ProgressNotifier.Builder;
import org.sidoh.peak_detection.PeakListener;
import org.sidoh.peak_detection.StatefulPeakDetector;
import org.sidoh.peak_detection.StatelessPeakDetector;
import org.sidoh.song_recognition.signature.ConstellationMap.Star;
import org.sidoh.song_recognition.spectrogram.Spectrogram;

package org.sidoh.song_recognition.signature;



public class ConstellationMapExtractor implements SpectrogramSignatureExtractor<ConstellationMapSignature> {
	
	private final StatefulPeakDetector.Builder peakDetector;
	private final double starDensityFactor;
	private final ProgressNotifier.Builder progressNotifer;
	private final int threadCount;
	private final StarBuffer.Builder bufferBuilder;
	
	public ConstellationMapExtractor(StatefulPeakDetector.Builder peakDetectorBuilder, 
			double starDensityFactor, 
			ProgressNotifier.Builder progressNotifer,
			StarBuffer.Builder bufferBuilder) {
		this(peakDetectorBuilder,
			starDensityFactor,
			progressNotifer,
			bufferBuilder,
			Runtime.getRuntime().availableProcessors());
	}
	
	public ConstellationMapExtractor(StatefulPeakDetector.Builder peakDetectorBuilder, 