package my5_1bit;

/**
 *
 * @author Viliam Krizan
 */



import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.*;

public class CaptureMicrophoneData extends JFrame {

    boolean stopCapture = false;
    ByteArrayOutputStream byteArrayOutputStream;
    AudioFormat audioFormat;
    TargetDataLine targetDataLine;
    AudioInputStream audioInputStream;
    SourceDataLine sourceDataLine;
    int c = 0;
    int saveCounter = 0;
    Date start,stop;
    long time;
    File AudioData = new File("ADBinary.txt");
    BufferedWriter writer;
    
    //
    byte previousByte;
    

    public static void main(String args[]) {
        new CaptureMicrophoneData();
    }

    public CaptureMicrophoneData() {
        final JButton captureBtn = new JButton("Capture");
        final JButton stopBtn = new JButton("Stop");
        final JButton playBtn = new JButton("Playback");
        final JButton analyzeBtn = new JButton("analyze");

        captureBtn.setEnabled(true);
        stopBtn.setEnabled(false);
        playBtn.setEnabled(false);
        analyzeBtn.setEnabled(false);

        
        captureBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                captureBtn.setEnabled(false);
                stopBtn.setEnabled(true);
                playBtn.setEnabled(false);
                
                captureAudio();
                }
            }
        );
        getContentPane().add(captureBtn);

        stopBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                captureBtn.setEnabled(true);
                stopBtn.setEnabled(false);
                playBtn.setEnabled(true);
                analyzeBtn.setEnabled(true);
                stopCapture = true;
                stop = new Date();
                time = stop.getTime() - start.getTime();
                System.out.println("time: " + time + "ms");
                }
            }
        );
        getContentPane().add(stopBtn);

        playBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                playAudio();
                }
            }
        );
        getContentPane().add(playBtn);
        
        
        getContentPane().add(analyzeBtn);
        

        getContentPane().setLayout(new FlowLayout());
        setTitle("Capture/Playback");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(300, 200);
        setVisible(true);
        
        
        try {
            writer = new BufferedWriter(new FileWriter(AudioData));
        } catch (IOException ex) {
            
        }
    }

    
    private void captureAudio() {
        try {
            audioFormat = getAudioFormat();
            DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
            targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
            targetDataLine.open(audioFormat);
            targetDataLine.start();
            
            Thread captureThread = new Thread(new CaptureThread());
            start = new Date();
            captureThread.start();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }
    
    private void playAudio() {
        try {
            
            byte audioData[] = byteArrayOutputStream.toByteArray();
            
            InputStream byteArrayInputStream = new ByteArrayInputStream(audioData);
            AudioFormat audioFormat = getAudioFormat();
            audioInputStream = new AudioInputStream(byteArrayInputStream,
                                                    audioFormat,
                                                    audioData.length / audioFormat.
                                                    getFrameSize());
            DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
            sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
            sourceDataLine.open(audioFormat);
            sourceDataLine.start();

            
            Thread playThread = new Thread(new PlayThread());
            
            playThread.start();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }
    
    private AudioFormat getAudioFormat() {
        float sampleRate = 192000.0F;
        //8000,11025,16000,22050,44100
        int sampleSizeInBits = 16;
        //8,16
        int channels = 1;
        //1,2
        boolean signed = true;
        //bity su znamienkove pre true
        //true,false
        boolean bigEndian = true;
        //urcuje kde sa nachadya LSB
        //true,false
        return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
    }


    class CaptureThread extends Thread {

        byte tempBuffer[] = new byte[10000];

        public void run() {
            byteArrayOutputStream = new ByteArrayOutputStream();
            stopCapture = false;
            try {
                while (!stopCapture) {
                    int cnt = targetDataLine.read(tempBuffer,0,tempBuffer.length);
                    if (cnt > 0) {
                        byteArrayOutputStream.write(tempBuffer, 0, cnt);
                        saveDataToText(tempBuffer,cnt);
                    }
                    
                }
                byteArrayOutputStream.close();
            } catch (Exception e) {
                System.out.println(e);
                System.exit(0);
            }
        }
    }
    
    private void saveDataToText(byte[] aData, int cnt){
        /*File AudioData = new File("AudioData.txt");
        byte sample;
        String s1,s2;

        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(AudioData,true));
            
            //System.out.println("zapisujem, cnt = " + cnt);
            for (int i = 0; i < cnt; i++) {
                //writer.write(c + "\t"  + aData[i] + System.lineSeparator());
                
                
                sample = aData[i];
                s1 = String.format("%8s", Integer.toBinaryString(sample & 0xFF)).replace(' ', '0');
                s2 = s1.substring(6);
                writer.write(c + "\t"  + aData[i] +"\t" + s1 + "\t" + s2 + System.lineSeparator());
                
                c++;
            }
            
            writer.close();
        } catch (IOException ex) {
            System.out.println("cant write");
            ex.printStackTrace();
        }*/
        
        //saving data for next processing
        
        

        //try {
            //BufferedWriter writer = new BufferedWriter(new FileWriter(AudioData,true));
            System.out.println("saving");
            byte sample;
            String s1,s2;
            //System.out.println("zapisujem");
            for (int i = 0; i < cnt; i++) {
                if(i%2 == 0){
                    continue;
                }
                sample = aData[i];
                if(previousByte == sample){
                    //continue;
                }
                //sample = (byte) Math.abs(aData[i]);
                s1 = String.format("%8s", Integer.toBinaryString(sample & 0xFF)).replace(' ', '0');
                s2 = s1.substring(7);
                if(saveCounter < 3){
                    try {
                        writer.write(s2);
                    } catch (IOException ex) {
                    }
                    saveCounter++;
                }else{
                    try {
                        writer.write(s2 + System.lineSeparator());
                    } catch (IOException ex) {
                    }
                    saveCounter = 0;
                }
                previousByte = aData[i];
                
            }
            
            //writer.close();
        //} catch (IOException ex) {
            //System.out.println("cant write");
            
        //}
    }
    
    


    class PlayThread extends Thread {

        byte tempBuffer[] = new byte[10000];

        public void run() {
            try {
                int cnt;
                
                while ((cnt = audioInputStream.
                        read(tempBuffer, 0,
                                tempBuffer.length)) != -1) {
                    if (cnt > 0) {
                        sourceDataLine.write(
                                tempBuffer, 0, cnt);
                    }
                }
                sourceDataLine.drain();
                sourceDataLine.close();
            } catch (Exception e) {
                System.out.println(e);
                System.exit(0);
            }
        }
    }
}
