import pyaudio
import wave
import time
import librosa 
import librosa.display
import IPython.display as ipd 
import soundfile as sf
import matplotlib.pyplot as plt
import serial
startTime = time.time()

#https://www.thepythoncode.com/article/play-and-record-audio-sound-in-python
def record():
    # the file name output you want to record into
    filename = "recorded.wav"
    # set the chunk size of 1024 samples
    chunk = 1024
    # sample format
    FORMAT = pyaudio.paInt16
    # mono, change to 2 if you want stereo
    channels = 1
    # 44100 samples per second
    sample_rate = 44100
    record_seconds = 10
    # initialize PyAudio object
    p = pyaudio.PyAudio()
    # open stream object as input & output
    stream = p.open(format=FORMAT,
                    channels=channels,
                    rate=sample_rate,
                    input=True,
                    output=True,
                    frames_per_buffer=chunk)
    frames = []
    print("Recording...")
    recordTime = time.time()
    for i in range(int(sample_rate / chunk * record_seconds)):
        data = stream.read(chunk)
        # if you want to hear your voice while recording
        # stream.write(data)
        frames.append(data)
    print("Finished recording.")
    # stop and close stream
    stream.stop_stream()
    stream.close()
    # terminate pyaudio object
    p.terminate()
    # save audio file
    # open the file in 'write bytes' mode
    wf = wave.open(filename, "wb")
    # set the channels
    wf.setnchannels(channels)
    # set the sample format
    wf.setsampwidth(p.get_sample_size(FORMAT))
    # set the sample rate
    wf.setframerate(sample_rate)
    # write the frames as bytes
    wf.writeframes(b"".join(frames))
    # close the file
    wf.close()
    return recordTime - startTime

#https://www.analyticsvidhya.com/blog/2018/02/audio-beat-tracking-for-music-information-retrieval/
def analyzeBeats(filename):
    # read audio file 
    x, sr = librosa.load(filename) 
    ipd.Audio(x, rate=sr)

    tempo, beat_times = librosa.beat.beat_track(x, sr=sr, start_bpm=60, units='time')
    clicks = librosa.clicks(beat_times, sr=sr, length=len(x))
    print("Clicks: ",beat_times)
    ipd.Audio(x + clicks, rate=sr, autoplay=True)
    sf.write('test3.wav',x+clicks,sr)
    return beat_times

#https://create.arduino.cc/projecthub/ansh2919/serial-communication-between-python-and-arduino-e7cce0 
def write_read(arduino, x):
    arduino.write(bytes(x, 'utf-8'))
    time.sleep(0.05)
    # data = arduino.readline()
    data =" "
    return data
def main():
    recordStartTime = record()
    beatTimes = analyzeBeats("recorded.wav")
    firstBeat = beatTimes[0]
    interval = beatTimes[1] - beatTimes[0]
    passString = str(recordStartTime) + " " + str(firstBeat) + " " + str(interval)
    arduino = serial.Serial(port='/dev/cu.usbmodem14401', baudrate=115200, timeout=.1)
    #Just for testing purposes to see if the string went through
    time.sleep(0.5)
    print(passString)
    value = write_read(arduino,passString)
    print(value)
    time.sleep(0.5)
    data = arduino.readline()
    print(data)
    while(True):
        # time.sleep(0.5)
        data = arduino.readline()
        print(data)
    # time.sleep(0.5)
    # data = arduino.readline()
    # print(data)
    # time.sleep(0.5)
    # data = arduino.readline()
    # print(data)
    # read = write_read(arduino, "3")
    # print(read)
main()


    
