// Path: src/main/java/org/harmony_analyser/jharmonyanalyser/chroma_analyser/Chroma.java
// @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
// 
// public class Chroma {
// 	public final float[] values;
// 
// 	public static final Chroma EMPTY_CHROMA = new Chroma();
// 
// 	/* Exceptions */
// 
// 	public class WrongChromaSize extends Exception {
// 		public WrongChromaSize(String message) {
// 			super(message);
// 		}
// 	}
// 
// 	public Chroma() {
// 		this.values = new float[0];
// 	}
// 
// 	public Chroma(float[] chroma) throws WrongChromaSize {
// 		this.values = new float[Chromanal.CHROMA_LENGTH];
// 		if (chroma.length != Chromanal.CHROMA_LENGTH) {
// 			throw new WrongChromaSize("Wrong Chroma size");
// 		}
// 		System.arraycopy(chroma, 0, values, 0, Chromanal.CHROMA_LENGTH - 1);
// 	}
// 
// 	/* Public / Package methods */
// 
// 	/* Private methods */
// }
// 
// Path: src/main/java/org/harmony_analyser/jharmonyanalyser/plugins/LineChartPlugin.java
// @SuppressWarnings("SameParameterValue")
// 
// public abstract class LineChartPlugin extends AnalysisPlugin {
// 	public VisualizationData getDataFromOutput(String inputWavFile) throws IOException, AudioAnalyser.OutputNotReady, AudioAnalyser.ParseOutputError, AudioAnalyser.IncorrectInputException, AudioAnalyser.OutputAlreadyExists {
// 		VisualizationData data = super.prepareVisualizationData();
// 		List<Float> timestamps = new ArrayList<>();
// 		List<Float> values = new ArrayList<>();
// 		List<String> linesList = readOutputFile(inputWavFile);
// 
// 		float timestamp, value;
// 
// 		/* Plugin-specific parsing of the result */
// 		try {
// 			for (String line : linesList) {
// 				timestamp = AudioAnalysisHelper.getTimestampFromLine(line);
// 				value = Float.parseFloat(AudioAnalysisHelper.getLabelFromLine(line));
// 				timestamps.add(timestamp);
// 				values.add(value);
// 			}
// 		} catch (NumberFormatException e) {
// 			throw new AudioAnalyser.ParseOutputError("Output did not have the required fields");
// 		}
// 		data.setTimestamps(timestamps);
// 		data.setValues(values);
// 		return data;
// 	}
// }


import org.harmony_analyser.jharmonyanalyser.services.*;
import org.harmony_analyser.jharmonyanalyser.chord_analyser.*;
import org.harmony_analyser.jharmonyanalyser.chroma_analyser.Chroma;
import org.harmony_analyser.jharmonyanalyser.plugins.LineChartPlugin;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
		}

		float chromaTimestamp;
		float[] chroma;
		float[] chromaSums = new float[12];
		Arrays.fill(chromaSums, (float) 0);
		float[] chromaVector;
		int[] harmony;
		List<int[]> chordProgression = new ArrayList<>();
		List<Float> timestampList = new ArrayList<>();
		int countChromasForAveraging = 0;
		int segmentationIndex = 0;
		float segmentationTimestamp;
		segmentationTimestamp = segmentationTimestampList.get(0);

		// 2. Iterate over chromas, transforming them into chord progression
		for (String line : chromaLinesList) {
			chromaTimestamp = AudioAnalysisHelper.getTimestampFromLine(line);

			if (chromaTimestamp > segmentationTimestamp) {
				// Go to the next segmentation timestamp
				segmentationIndex++;
				if (segmentationIndex > segmentationTimestampList.size()-1) {
					break;
				}
				timestampList.add(segmentationTimestamp);
				segmentationTimestamp = segmentationTimestampList.get(segmentationIndex);

				// Average chromas in the previous block, use AUDIBLE_THRESHOLD to filter non-audible activations
				chromaVector = AudioAnalysisHelper.filterChroma(AudioAnalysisHelper.averageChroma(chromaSums, countChromasForAveraging), audibleThreshold);
// Path: src/main/java/org/harmony_analyser/jharmonyanalyser/chroma_analyser/Chroma.java
// @SuppressWarnings({"SameParameterValue", "WeakerAccess"})
// 
// public class Chroma {
// 	public final float[] values;
// 
// 	public static final Chroma EMPTY_CHROMA = new Chroma();
// 
// 	/* Exceptions */
// 
// 	public class WrongChromaSize extends Exception {
// 		public WrongChromaSize(String message) {
// 			super(message);
// 		}
// 	}
// 
// 	public Chroma() {
// 		this.values = new float[0];
// 	}
// 
// 	public Chroma(float[] chroma) throws WrongChromaSize {
// 		this.values = new float[Chromanal.CHROMA_LENGTH];
// 		if (chroma.length != Chromanal.CHROMA_LENGTH) {
// 			throw new WrongChromaSize("Wrong Chroma size");
// 		}
// 		System.arraycopy(chroma, 0, values, 0, Chromanal.CHROMA_LENGTH - 1);
// 	}
// 
// 	/* Public / Package methods */
// 
// 	/* Private methods */
// }
// 
// Path: src/main/java/org/harmony_analyser/jharmonyanalyser/plugins/LineChartPlugin.java
// @SuppressWarnings("SameParameterValue")
// 
// public abstract class LineChartPlugin extends AnalysisPlugin {
// 	public VisualizationData getDataFromOutput(String inputWavFile) throws IOException, AudioAnalyser.OutputNotReady, AudioAnalyser.ParseOutputError, AudioAnalyser.IncorrectInputException, AudioAnalyser.OutputAlreadyExists {
// 		VisualizationData data = super.prepareVisualizationData();
// 		List<Float> timestamps = new ArrayList<>();
// 		List<Float> values = new ArrayList<>();
// 		List<String> linesList = readOutputFile(inputWavFile);
// 
// 		float timestamp, value;
// 
// 		/* Plugin-specific parsing of the result */
// 		try {
// 			for (String line : linesList) {
// 				timestamp = AudioAnalysisHelper.getTimestampFromLine(line);
// 				value = Float.parseFloat(AudioAnalysisHelper.getLabelFromLine(line));
// 				timestamps.add(timestamp);
// 				values.add(value);
// 			}
// 		} catch (NumberFormatException e) {
// 			throw new AudioAnalyser.ParseOutputError("Output did not have the required fields");
// 		}
// 		data.setTimestamps(timestamps);
// 		data.setValues(values);
// 		return data;
// 	}
// }


// Path: src/main/java/org/harmony_analyser/jharmonyanalyser/plugins/chordanal_plugins/ChordAnalyserPlugin.java
import org.harmony_analyser.jharmonyanalyser.services.*;
import org.harmony_analyser.jharmonyanalyser.chord_analyser.*;
import org.harmony_analyser.jharmonyanalyser.chroma_analyser.Chroma;
import org.harmony_analyser.jharmonyanalyser.plugins.LineChartPlugin;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;

		}

		float chromaTimestamp;
		float[] chroma;
		float[] chromaSums = new float[12];
		Arrays.fill(chromaSums, (float) 0);
		float[] chromaVector;
		int[] harmony;
		List<int[]> chordProgression = new ArrayList<>();
		List<Float> timestampList = new ArrayList<>();
		int countChromasForAveraging = 0;
		int segmentationIndex = 0;
		float segmentationTimestamp;
		segmentationTimestamp = segmentationTimestampList.get(0);

		// 2. Iterate over chromas, transforming them into chord progression
		for (String line : chromaLinesList) {
			chromaTimestamp = AudioAnalysisHelper.getTimestampFromLine(line);

			if (chromaTimestamp > segmentationTimestamp) {
				// Go to the next segmentation timestamp
				segmentationIndex++;
				if (segmentationIndex > segmentationTimestampList.size()-1) {
					break;
				}
				timestampList.add(segmentationTimestamp);
				segmentationTimestamp = segmentationTimestampList.get(segmentationIndex);

				// Average chromas in the previous block, use AUDIBLE_THRESHOLD to filter non-audible activations
				chromaVector = AudioAnalysisHelper.filterChroma(AudioAnalysisHelper.averageChroma(chromaSums, countChromasForAveraging), audibleThreshold);
				Arrays.fill(chromaSums, (float) 0);