package kr.util.audio;

/**
 * L-R in the left channel and R-L in the right channel
 */
public class SubtractedBkgAudioClip extends EffectAudioClip {
	 
	public SubtractedBkgAudioClip()
	{}

	@Override
	public int getNumChannels() {
		return 2;
	}
	@Override
	public int length() {
		if(source == null) return 0;
		return source.length();
	}
	
	@Override
	public int getRate() {
		if(source == null) return 0;
		return source.getRate();
	}
	
	@Override
	public int getSampleSizeInBits()
	{
		if(source == null) return 0;
		return source.getSampleSizeInBits();
	}
	
	@Override
	public byte byteAt(int index) {
		if(source == null) return 0;
		
		if(source.getSampleSizeInBits() == 16)
		{
			int total = 0;
			int byteIndex = index % 4;
			index -= byteIndex;
			for(int i = 0; i < source.getNumChannels(); i++)
			{
				total += (source.byteAt(index + i * 2) + source.byteAt(index + 1 + i * 2 ) * 256) * (i == 0 ? 1 : -1);
			}
			
			if(byteIndex == 0)
				return (byte)((total / 2) & 0xff);
			else if(byteIndex == 1)
				return (byte)((total / 2) >> 8);
			else if(byteIndex == 2)
				return (byte)((total / 2) & 0xff);
			else // if(byteIndex == 3)
				return (byte)(-(total / 2) >> 8);
		}
		else //sample size is 8 bits
		{
			int total = 0;
			int byteIndex = index % 2;
			index -= byteIndex;
			for(int i = 0; i < source.getNumChannels(); i++)
			{
				total += (source.byteAt(index + i)) * (i == 0 ? 1 : -1);
			}
			
			if(byteIndex == 0)
				return (byte)(total / 2);
			else //if(byteIndex == 1)
				return (byte)(- total / 2);
		}
	}
	
	@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;
		}
		
		//if doesnt start on an even frame, use byteAt() until it does
		while(offset % (2 * getSampleSizeInBits() / 8) != 0)
		{
			dest[destOffset] = byteAt(offset);
			offset++;
		}
		
		source.copyTo(offset, length, dest, destOffset);
		
		if(source.getSampleSizeInBits() == 8)
		{
			for(int i = 0; i < length; i+=2)
			{
				int val = (dest[destOffset+i] - dest[destOffset+i+1])/2;
				
				dest[i] = (byte)(val);
			}
		}
		else
		{
			for(int i = 0; i < length; i+=4)
			{
				int val = ((dest[destOffset+i] + dest[destOffset+i+1] * 256) 
						- (dest[destOffset+i+2] + dest[destOffset+i+2] * 256))/2;
				
				dest[i] = (byte)(val & 0xff);
				dest[i+1] = (byte)(val >> 8);
				dest[i+2] = (byte) -dest[i];
				dest[i+3] = (byte) -dest[i+1];
			}
		}

	}
	
}
