// Frequencies:
// E:   82.4  Hz
// A:  110.0  Hz
// d:  146.8  Hz
// g:  196.0  Hz
// h:  246.92 Hz
// e1: 329.6  Hz
package at.priv.toastfreeware.jguitartuner;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class JGuitarTuner {
	
	
	static void convert(byte[] rawData, int[] soundData, AudioFormat af) {
		for (int i = 0; i != soundData.length; ++i) {
			// The following two lines ...
			// if (rawData[2*i+1] >= 0) soundData[i] = rawData[2*i] * 256 + rawData[2*i+1];
			// else soundData[i] = rawData[2*i] * 256 + rawData[2*i+1] + 256;
			// ... would to the same thing as ...
			soundData[i] = (rawData[2*i] << 8) + (rawData[2*i+1] & 0xFF);
			// ... but are slower
		}
		// maybe the whole conversion would also be possible with a java.io.DataInputStream?
	}
	
	
	/** Analyze input, either from microphone (no argument) or from .wav file (filename as argument)
	 * @param args
	 * @throws LineUnavailableException 
	 * @throws IOException 
	 * @throws UnsupportedAudioFileException 
	 */
	public static void main(String[] args) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
		if (args.length == 0) {
			// Read from microphone
			AudioFormat format = new AudioFormat(44100, 16, 1, true, true);
			double updatesPerSecond = 10;
			
			int bufferFrameCount = (int) Math.round(format.getFrameRate() / updatesPerSecond); // 2 * 44100 / 10
			byte[] bufferArray = new byte[bufferFrameCount  * format.getFrameSize()];
			int[] soundData = new int[bufferFrameCount];
			
			TargetDataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
			TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
			
			line.open(format);
			line.start();
			
			int totalCount = 0;
			for (int i = 0; i != 20; ++i) {
				int byteReadCount = line.read(bufferArray, 0, bufferArray.length);
				convert(bufferArray, soundData, format);
				totalCount += byteReadCount;
				// System.out.println(totalCount);
				// for (int j = 0; j != bufferArray.length; ++j) {
				//	System.out.println(bufferArray[j]);
				//}
				for (int j = 0; j != soundData.length; ++j) {
					System.out.println(soundData[j]);
				}
				
			}
			// System.out.println(line.getFormat().toString());
			
			line.stop();
			line.close();
			
		} else if (args.length == 1) {
			// Read from file
			String fileName = args[0];
			AudioInputStream is1 = AudioSystem.getAudioInputStream(new File(fileName));
			AudioFormat format = is1.getFormat();
			AudioInputStream is2 = AudioSystem.getAudioInputStream(new AudioFormat(format.getSampleRate(), format.getSampleSizeInBits(), 1, true, true), is1);
			Vector<Complex> sound = new Vector<Complex>();
			BufferedInputStream isb = new BufferedInputStream(is2, 2);
			DataInputStream is3 = new DataInputStream(isb);
			for (long size = is1.getFrameLength(); size != 10; --size) {
				int av = is1.available();
				sound.add(new Complex(is3.readShort()));
			}
			Vector<Complex> soundFft = Calculus.fft(sound);
			System.out.print(soundFft);
		}
	}

}
