/*
*
      
_______
                       
_____
   
_____ _____
  

*
     
|__
   
__|
                     
|
  
__ \ / ____|__ \
 

*
        
| | __ _ _ __ ___
  
______| || | (___ | |__) |
*
        
| |/ _` | '__/ __|/ _ \/ __| |
  
| |\___ \|___/
 

*
        
| | (_| | |
  
\__ \ (_) \__ \ |__| |____) | |
     

*
        
|_|\__,_|_|
  
|___/\___/|___/_____/|_____/|_|
     

*
                                                         

* -------------------------------------------------------------
*
* 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.
*
 

*/

package be.tarsos.dsp.ui.layers;

import java.awt.Color;
import java.awt.Graphics2D;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

import javax.sound.sampled.UnsupportedAudioFileException;

import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.io.jvm.AudioDispatcherFactory;
import be.tarsos.dsp.pitch.PitchDetectionHandler;
import be.tarsos.dsp.pitch.PitchDetectionResult;
import be.tarsos.dsp.pitch.PitchProcessor;
import be.tarsos.dsp.pitch.PitchProcessor.PitchEstimationAlgorithm;
import be.tarsos.dsp.ui.Axis;
import be.tarsos.dsp.ui.CoordinateSystem;
import be.tarsos.dsp.util.PitchConverter;


public class PitchContourLayer implements Layer {
	

	
private TreeMap<Double, float[]> features;
	
private final CoordinateSystem cs;
	
private final Color color;
	
private final int frameSize;
	
private final int overlap;
	
private final File audioFile;
	


	
public PitchContourLayer(CoordinateSystem cs, File audioFile , Color color , int frameSize, int overlap) {
		
this.features = new TreeMap<Double, float[]>();
		
this.cs = cs;
		
this.color = color;
		

		
this.audioFile = audioFile;
		

		
this.frameSize = frameSize;
		
this.overlap = overlap;
		

		
initialise();
	
}

	
public void draw(Graphics2D graphics) {
		
graphics.setColor(color);
		
int ovalWidth = Math.round(LayerUtilities.pixelsToUnits(graphics, 4,true));
		
int ovalHeight = Math.round(LayerUtilities.pixelsToUnits(graphics, 4,false));
		

		

		
// every second
		
if(features !=null){
			
Map<Double, float[]> submap = features.subMap(cs.getMin(Axis.X) / 1000.0,cs.getMax(Axis.X) / 1000.0);
			
for (Map.Entry<Double, float[]> entry : submap.entrySet()) {
				
double time = entry.getKey();// in seconds
				
double pitch = entry.getValue()[0];// in cents
				
if (pitch > cs.getMin(Axis.Y) && pitch < cs.getMax(Axis.Y)) {
					
graphics.drawOval((int) (time * 1000), (int) pitch, ovalWidth,ovalHeight);
				
}
			
}
		
}
	
}

	

	
public void initialise() {
		
try {
			
AudioDispatcher adp = AudioDispatcherFactory.fromFile(audioFile, frameSize,overlap);
			

			
final double timeLag = frameSize / 44100.0;

			
final TreeMap<Double, float[]> fe = new TreeMap<Double, float[]>();
			
adp.addAudioProcessor(new PitchProcessor(
					
PitchEstimationAlgorithm.FFT_YIN, 44100, frameSize,
					
new PitchDetectionHandler() {
						

						
public void handlePitch(
								
PitchDetectionResult pitchDetectionResult,
								
AudioEvent audioEvent) {
							
if (pitchDetectionResult.isPitched()) {
								
float[] pitch = new float[1];
								
pitch[0] = (float) PitchConverter
										
.hertzToAbsoluteCent
(pitchDetectionResult
												
.getPitch
());
								
fe.put(audioEvent.getTimeStamp() - timeLag,
										
pitch);
							
}
						
}
					
}));
			
adp.addAudioProcessor(new AudioProcessor() {
				
@Override
				
public void processingFinished() {
					
PitchContourLayer.this.features = fe;
				
}
				

				
@Override
				
public boolean process(AudioEvent audioEvent) {
					
return true;
				
}
			
});
			
new Thread(adp).start();
		
} catch (UnsupportedAudioFileException e) {
			
e.printStackTrace();
		
} catch (IOException e2){
			
e2.printStackTrace();
		
}
	
}

	
@Override
	
public String getName() {
		
return "Pitch contour layer";
	
}

}