package chromaticTuner.tuner;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder.AudioSource;

public class Recorder {
	private int m_bufferSize=0;
	private float m_bufferDuration=0.0625f;
	private int m_sampleRate=0;
	private AudioRecord m_audioRecord = null;
	private Thread m_recordingThread = null;
	private OnAudioBufferListener m_audioBufferListener = null;
	private OnAudioRecorderInitializeErrorListener m_audioRecorderInitializeErrorListener = null;
	
	public Recorder()
	{
		m_sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
	}
	
	public void createAudioRecord()
	{
	    m_audioRecord = new AudioRecord(AudioSource.MIC, m_sampleRate, AudioFormat.CHANNEL_IN_MONO,
	    		AudioFormat.ENCODING_PCM_16BIT, AudioRecord.getMinBufferSize(m_sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT));
	    m_bufferSize = (int)(m_bufferDuration*m_sampleRate);
    }
	
	public synchronized void start()
	{
		if (m_recordingThread==null)
		{
			m_recordingThread = new Thread(new RecordingRunnable() {});
		}
		
		if (m_recordingThread.isAlive())
		{
			return;
		}
		
		try
		 {
			createAudioRecord();
			if (m_audioRecord.getState()!=AudioRecord.STATE_INITIALIZED)
			{
				throw new Exception();
			}
			m_recordingThread.start();
		 }
		 catch (Exception e)
		 {
			 if (m_audioRecorderInitializeErrorListener!=null)
			 {
				 m_audioRecorderInitializeErrorListener.audioRecorderInitializeError();
			 }
			 e.printStackTrace();
		 }
	}
	public synchronized void stop()
	{
		if (m_recordingThread==null || !m_recordingThread.isAlive())
		{
			return;
		}
		m_recordingThread.interrupt();
		try {
			m_recordingThread.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		m_recordingThread=null;
		m_audioRecord.release();
		m_audioRecord=null;
	}
	
	public void setOnAudioBufferListener(OnAudioBufferListener listener)
	{
		m_audioBufferListener = listener;
	}
	
	public void setOnAudioRecorderInitializeError(OnAudioRecorderInitializeErrorListener listener)
	{
		m_audioRecorderInitializeErrorListener = listener;
	}
	
	public class RecordingRunnable implements Runnable {
	    public void run() {
			m_audioRecord.startRecording();
			 
			short buffer[] = new short[m_bufferSize];
			while(!m_recordingThread.isInterrupted())
			{
				m_audioRecord.read(buffer, 0, m_bufferSize);
				if (m_audioBufferListener!=null)
				{
					m_audioBufferListener.onAudioBuffer(buffer);
				}
			 }
	    }
	}
	
	public int getSampleRate()
	{
		return m_sampleRate;
	}
	
	public int getBufferSize()
	{
		return m_bufferSize;
	}
}
