package kr.util.audio;

public class MonoAudioClip extends AudioClip {
	private AudioClip source;
	 
	//if we should subtract the right channel from the left, in an attempt to remove
	// the center channel where vocals are usually kept (only works properly with two channels)
	private boolean subtracted;
	
	public MonoAudioClip()
	{}

	public MonoAudioClip(boolean subtracted) {
		this.subtracted = subtracted;
	}
	@Override
	public int getNumChannels() {
		return 1;
	}
	@Override
	public int length() {
		if(source == null) return 0;
		return source.length()/ source.getNumChannels();
	}
	
	@Override
	public int getRate() {
		if(source == null) return 0;
		return source.getRate();
	}
	@Override
	public byte byteAt(int index) {
		if(source == null) return 0;
		int total =0;
		for(int i = 0; i < source.getNumChannels(); i++)
		{
			total += source.byteAt(index*source.getNumChannels()+i) * (subtracted && i == 1 ? -1 : 1) ;
		}
		
		return (byte)(total / source.getNumChannels());
	}
	
	private byte [] intBuffer;
	
	@Override
	public void copyTo(int offset, int length, byte[] dest, int destOffset) {
		if(source == null)
		{
			for(int i = destOffset; i < length; i++)
			{
				dest[i] = 0;
			}
			return;
		}
		
		int numChannels = source.getNumChannels();
		
		if(intBuffer == null || intBuffer.length < length * numChannels)
		{
			intBuffer = new byte[length * numChannels];
		}
		
		source.copyTo(offset * numChannels, length * numChannels, intBuffer, 0);
		
		for(int i = 0; i < length * numChannels; i+=numChannels)
		{
			int total = 0;
			for(int j = 0; j < numChannels; j++)
			{
				total += intBuffer[i+j] * (subtracted && j == 1 ? -1 : 1) ;
			}
			
			dest[i/numChannels+destOffset] = (byte)(total/numChannels);
		}

//		//HACK
//		int runningBlanks = 0;
//		int startBlankIndex=0, endBlankIndex;
//		
//		for(int hack = 0; hack < length; hack++)
//		{
//			if(Math.abs(dest[hack]) < 3)
//			{
//				if(runningBlanks == 0)
//					startBlankIndex = offset + hack;
//				runningBlanks ++;
//			}
//			else {
//				if(runningBlanks > 10)
//				{
//					System.out.println(String.format("blank indexes %d - %d, micros %f - %f",
//							startBlankIndex,
//							startBlankIndex + runningBlanks,
//							((double)startBlankIndex) / getRate() * 1000000,
//							((double)startBlankIndex + runningBlanks) / getRate() * 1000000));
//				}
//				runningBlanks = 0;
//			}			
//		}
//		//END HACK

	}
	
	public AudioClip getSource() {
		return source;
	}

	public void setSource(AudioClip source) {
		this.source = source;
	}
}
