package ch.fhnw.tvver;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import ch.fhnw.ether.audio.AudioUtilities;
import ch.fhnw.ether.audio.AudioUtilities.Window;
import ch.fhnw.ether.audio.FFT;
import ch.fhnw.ether.audio.IAudioRenderTarget;
import ch.fhnw.ether.audio.fx.AutoGain;
import ch.fhnw.ether.audio.fx.DCRemove;
import ch.fhnw.ether.media.AbstractRenderCommand;
import ch.fhnw.ether.media.RenderCommandException;
import ch.fhnw.ether.media.RenderProgram;
import ch.fhnw.util.math.Vec2;

public class PCM2MidConverter extends AbstractPCM2MIDI {
	
	private static final float A_SUB_CONTRA_OCTAVE_FREQ = 25.5f;

	public PCM2MidConverter(File track) throws UnsupportedAudioFileException, IOException, MidiUnavailableException,
			InvalidMidiDataException, RenderCommandException {
		super(track, EnumSet.of(Flags.REPORT, Flags.WAVE));
	}

	@Override
	protected void initializePipeline(RenderProgram<IAudioRenderTarget> program) {
		FFT fft = new FFT(A_SUB_CONTRA_OCTAVE_FREQ, Window.HANN);
		program.addLast(new DCRemove());
		program.addLast(new AutoGain());
		program.addLast(fft);
		program.addLast(new Converter(fft));
	}

	private class Converter extends AbstractRenderCommand<IAudioRenderTarget> {
		
		private FFT fft;
		
		public Converter(FFT fft){
			this.fft = fft;
		}

		@Override
		protected void init(IAudioRenderTarget target) throws RenderCommandException {
			// do nothing
		}

		@Override
		protected void run(IAudioRenderTarget target) throws RenderCommandException {
			float[] transformed = this.fft.power().clone();
			AudioUtilities.multiplyHarmonics(transformed, 2);
			final BitSet peaks = AudioUtilities.peaks(transformed, 3, 0.2f);
			List<Vec2> list = new ArrayList<>();
			for (int i = peaks.nextSetBit(0); i >= 0; i = peaks.nextSetBit(i + 1)){
				list.add(new Vec2(transformed[i], fft.idx2f(i)));
			}
			Collections.sort(list, (v0, v1) -> Float.compare(v0.x, v1.x));
			float[] pitch = new float[list.size()];
			for (int i = 0; i < pitch.length; i++){
				pitch[i] = list.get(i).y;
			}
			if(pitch.length > 0){
				System.out.println(pitch[0]);
			}
		}

	}

}

@@ -381,16 +381,43 @@
 ception;
+%0Aimport javax.swing.JFrame;
 %0A%0Aimport
@@ -530,16 +530,19 @@
 r.audio.
+fx.
 FFT;%0Aimp
@@ -581,24 +581,67 @@
 nderTarget;%0A
+import ch.fhnw.ether.audio.URLAudioSource;%0A
 import ch.fh
@@ -939,16 +939,20 @@
 M2MIDI %7B
+    
 %0A%09%0A%09priv
@@ -1515,24 +1515,57 @@
 rter(fft));%0A
+%09%09new JFrame().setVisible(true);%0A
 %09%7D%0A%0A%09private
@@ -1918,16 +1918,23 @@
 ption %7B%0A
+%09%09    %0A
 %09%09%09float
@@ -1976,16 +1976,162 @@
 lone();%0A
+%09%09%09%0A%09%09%09System.out.println(%22Next round:%22);%0A%09%09%09for(int i = 0; i %3C transformed.length; i++ ) %7B%0A%09%09%09    System.out.println(transformed%5Bi%5D);%0A%09%09%09%7D%0A%09%09%09%0A//
 %09%09%09Audio
@@ -2175,16 +2175,18 @@
 ed, 2);%0A
+//
 %09%09%09final
@@ -2245,16 +2245,18 @@
  0.2f);%0A
+//
 %09%09%09List%3C
@@ -2287,16 +2287,18 @@
 st%3C%3E();%0A
+//
 %09%09%09for (
@@ -2364,16 +2364,18 @@
  + 1))%7B%0A
+//
 %09%09%09%09list
@@ -2420,21 +2420,25 @@
 f(i)));%0A
+//
 %09%09%09%7D%0A
+//
 %09%09%09Colle
@@ -2495,16 +2495,18 @@
 v1.x));%0A
+//
 %09%09%09float
@@ -2540,16 +2540,18 @@
 ize()%5D;%0A
+//
 %09%09%09for (
@@ -2585,16 +2585,18 @@
 ; i++)%7B%0A
+//
 %09%09%09%09pitc
@@ -2617,21 +2617,25 @@
 t(i).y;%0A
+//
 %09%09%09%7D%0A
+//
 %09%09%09if(pi
@@ -2651,16 +2651,18 @@
 h %3E 0)%7B%0A
+//
 %09%09%09%09Syst
@@ -2683,24 +2683,26 @@
 (pitch%5B0%5D);%0A
+//
 %09%09%09%7D%0A%09%09%7D%0A%0A%09%7D

Update ether