#### Programmer par Romain Joly - Institut Fourier ####

import wave
import struct
import math
from tkinter import *

import winsound #### pour Windows


########## donnees de depart########
# pour le son
nbCanal = 1    # mono
nbOctet = 1    # taille d'un échantillon : 1 octet = 8 bits
fech = 90000   # fréquence d'échantillonnage
duree = 2       
frequence = 180
nbEchantillon = int(duree*fech)
nbPeriode = int(fech/frequence)
parametres = (nbCanal,nbOctet,fech,nbEchantillon,'NONE','not compressed')
son_fct_2=[]

# pour le graphe
longueur_graphe=300
longueur_onde=100
son_fct = []


amplitudes = [50.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
######### fonction pour jouer le son #####
def joue():
    global parametres, son_fct
    son = []
    creation_son_fct_2()
    son_fct_bis = son_fct_2
    max_son=max(son_fct_bis)
    if max_son>277:
        for i in son_fct_bis:
            son_fct_bis[i] = int(150+127*float((son_fct_bis[i]-150))/float(max_son-150))
    #print(max_son)
    #print(max(son_fct_bis))
    #print(min(son_fct_bis))
    for i in son_fct_bis:
        son.append(wave.struct.pack('B',int(278-son_fct_bis[i])))
    Monson = wave.open('son.wav','w') # instanciation de l'objet Monson
    Monson.setparams(parametres)
    sonbis = b''.join(son)
    Monson.writeframes(sonbis)
    Monson.close()
    winsound.PlaySound('son.wav',winsound.SND_FILENAME)
    

######### fonction creant la fonction son avec amplitudes harmoniques #######
def creation_son_fct():
    global son_fct, amplitudes, longueur_graphe, longueur_onde 
    son_fct = []
    for i in range(0,longueur_graphe+1):
        valeur = 128
        for j in range(0,10):
            valeur = valeur + amplitudes[j]*math.sin(2.0*math.pi*i*(j+1)/longueur_onde)
        son_fct.append(278-int(valeur))

######### fonction creant la fonction son avec amplitudes harmoniques et gros fichier #######
def creation_son_fct_2():
    global son_fct_2, amplitudes, nbEchantillon, nbPeriode 
    son_fct_2 = []
    periode = []
    for i in range(0,nbPeriode):
        valeur = 128
        for j in range(0,10):
            valeur = valeur + amplitudes[j]*math.sin(2.0*math.pi*frequence*i*(j+1)/fech)
        periode.append(278-int(valeur))
    for i in range(0,int(nbEchantillon/nbPeriode)):
        son_fct_2=son_fct_2+periode
        
############# mise à jour des valeurs par entree ###########
def mise_a_jour():
    global amplitudes, son_fct, ampli0_ech, ampli1_ech, ampli2_ech, ampli3_ech, ampli4_ech, ampli5_ech, ampli6_ech, ampli7_ech, ampli8_ech, ampli9_ech, Canevas
    amplitudes[0] = float(case0.get())*float(ampli0_check.get())
    amplitudes[1] = float(case1.get())*float(ampli1_check.get())
    amplitudes[2] = float(case2.get())*float(ampli2_check.get())
    amplitudes[3] = float(case3.get())*float(ampli3_check.get())
    amplitudes[4] = float(case4.get())*float(ampli4_check.get())
    amplitudes[5] = float(case5.get())*float(ampli5_check.get())
    amplitudes[6] = float(case6.get())*float(ampli6_check.get())
    amplitudes[7] = float(case7.get())*float(ampli7_check.get())
    amplitudes[8] = float(case8.get())*float(ampli8_check.get())
    amplitudes[9] = float(case9.get())*float(ampli9_check.get())
    ampli0_ech.set(int(case0.get()))
    ampli1_ech.set(int(case1.get()))
    ampli2_ech.set(int(case2.get()))
    ampli3_ech.set(int(case3.get()))
    ampli4_ech.set(int(case4.get()))
    ampli5_ech.set(int(case5.get()))
    ampli6_ech.set(int(case6.get()))
    ampli7_ech.set(int(case7.get()))
    ampli8_ech.set(int(case8.get()))
    ampli9_ech.set(int(case9.get()))
    creation_son_fct()

    Canevas.delete(ALL)
    Canevas.create_line(10, 150, 610, 150)
    for i in range(0,longueur_graphe):
        y1 = int(son_fct[i])
        y2 = int(son_fct[i+1])
        Canevas.create_line((10+2*i), y1, (12+2*i), y2, fill='red', width=2)

def mise_a_jour_bis(pif):
    mise_a_jour()


############# mise à jour des valeurs par echelle ###########
def mise_a_jour_ech(pif):
    global amplitudes, ampli0, ampli1, ampli2, ampli3, ampli4, ampli5, ampli6, ampli7, ampli8, ampli9, son_fct, Canevas
    amplitudes[0] = float(ampli0_ech.get())*float(ampli0_check.get())
    ampli0 = str(ampli0_ech.get())
    case0.delete(0,END)
    case0.insert(1,ampli0)
    amplitudes[1] = float(ampli1_ech.get())*float(ampli1_check.get())
    ampli1 = str(ampli1_ech.get())
    case1.delete(0,END)
    case1.insert(1,ampli1)
    amplitudes[2] = float(ampli2_ech.get())*float(ampli2_check.get())
    ampli2 = str(ampli2_ech.get())
    case2.delete(0,END)
    case2.insert(1,ampli2)
    amplitudes[3] = float(ampli3_ech.get())*float(ampli3_check.get())
    ampli3 = str(ampli3_ech.get())
    case3.delete(0,END)
    case3.insert(1,ampli3)
    amplitudes[4] = float(ampli4_ech.get())*float(ampli4_check.get())
    ampli4 = str(ampli4_ech.get())
    case4.delete(0,END)
    case4.insert(1,ampli4)
    amplitudes[5] = float(ampli5_ech.get())*float(ampli5_check.get())
    ampli5 = str(ampli5_ech.get())
    case5.delete(0,END)
    case5.insert(1,ampli5)
    amplitudes[6] = float(ampli6_ech.get())*float(ampli6_check.get())
    ampli6 = str(ampli6_ech.get())
    case6.delete(0,END)
    case6.insert(1,ampli6)
    amplitudes[7] = float(ampli7_ech.get())*float(ampli7_check.get())
    ampli7 = str(ampli7_ech.get())
    case7.delete(0,END)
    case7.insert(1,ampli7)
    amplitudes[8] = float(ampli8_ech.get())*float(ampli8_check.get())
    ampli8 = str(ampli8_ech.get())
    case8.delete(0,END)
    case8.insert(1,ampli8)
    amplitudes[9] = float(ampli9_ech.get())*float(ampli9_check.get())
    ampli9 = str(ampli9_ech.get())
    case9.delete(0,END)
    case9.insert(1,ampli9)
    
    
    creation_son_fct()

    Canevas.delete(ALL)
    Canevas.create_line(10, 150, 610, 150)
    for i in range(0,longueur_graphe):
        y1 = int(son_fct[i])
        y2 = int(son_fct[i+1])
        Canevas.create_line((10+2*i), y1, (12+2*i), y2, fill='red', width=2)
        
        
################## fonctions predefinies ################

def set_cercles():
    global amplitudes
    check0.select()
    check1.select()
    check2.select()
    check3.select()
    check4.select()
    check5.select()
    check6.select()
    check7.select()
    check8.select()
    check9.select()
    ampli0_ech.set(93)
    ampli1_ech.set(0)
    ampli2_ech.set(16)
    ampli3_ech.set(0)
    ampli4_ech.set(6)
    ampli5_ech.set(0)
    ampli6_ech.set(2)
    ampli7_ech.set(0)
    ampli8_ech.set(1)
    ampli9_ech.set(0)
    mise_a_jour_ech(0)


def set_creneaux():
    global amplitudes
    check0.select()
    check1.select()
    check2.select()
    check3.select()
    check4.select()
    check5.select()
    check6.select()
    check7.select()
    check8.select()
    check9.select()
    ampli0_ech.set(90)
    ampli1_ech.set(0)
    ampli2_ech.set(30)
    ampli3_ech.set(0)
    ampli4_ech.set(18)
    ampli5_ech.set(0)
    ampli6_ech.set(13)
    ampli7_ech.set(0)
    ampli8_ech.set(10)
    ampli9_ech.set(0)
    mise_a_jour_ech(0)
    
def set_triangles():
    global amplitudes
    check0.select()
    check1.select()
    check2.select()
    check3.select()
    check4.select()
    check5.select()
    check6.select()
    check7.select()
    check8.select()
    check9.select()
    ampli0_ech.set(100)
    ampli1_ech.set(0)
    ampli2_ech.set(-11)
    ampli3_ech.set(0)
    ampli4_ech.set(4)
    ampli5_ech.set(0)
    ampli6_ech.set(-2)
    ampli7_ech.set(0)
    ampli8_ech.set(1)
    ampli9_ech.set(0)
    mise_a_jour_ech(0)

def set_scie():
    global amplitudes
    check0.select()
    check1.select()
    check2.select()
    check3.select()
    check4.select()
    check5.select()
    check6.select()
    check7.select()
    check8.select()
    check9.select()
    ampli0_ech.set(80)
    ampli1_ech.set(-40)
    ampli2_ech.set(+27)
    ampli3_ech.set(-20)
    ampli4_ech.set(16)
    ampli5_ech.set(-13)
    ampli6_ech.set(11)
    ampli7_ech.set(-10)
    ampli8_ech.set(9)
    ampli9_ech.set(-8)
    mise_a_jour_ech(0)

def set_zero():
    global amplitudes
    ampli0_ech.set(0)
    ampli1_ech.set(0)
    ampli2_ech.set(0)
    ampli3_ech.set(0)
    ampli4_ech.set(0)
    ampli5_ech.set(0)
    ampli6_ech.set(0)
    ampli7_ech.set(0)
    ampli8_ech.set(0)
    ampli9_ech.set(0)
    mise_a_jour_ech(0)

######### harmosbas ########

def cochedecoche():
    if float(ampli1_check.get())==1:
        check0.deselect()
        check1.deselect()
        check2.deselect()
        check3.deselect()
        check4.deselect()
        check5.deselect()
        check6.deselect()
        check7.deselect()
        check8.deselect()
        check9.deselect()
    else:
        check0.select()
        check1.select()
        check2.select()
        check3.select()
        check4.select()
        check5.select()
        check6.select()
        check7.select()
        check8.select()
        check9.select()
    mise_a_jour_ech(0)
    
######### lancement interface ########
fenetre = Tk()

fenetre_droite = Frame(fenetre)

Canevas = Canvas(fenetre_droite,width = 620, height =300,borderwidth=3,relief="raised",background='white')
Canevas.pack(side=TOP)

harmos = Frame(fenetre, borderwidth=3,relief="raised")

text_harmos = Label(harmos,text= "Amplitudes (de -100 à 100)",font=("Arial",15),borderwidth=1,relief="solid")
text_harmos.pack(side=TOP)


### les harmoniques
harmos0 = Frame(harmos,borderwidth=1)
harmos1 = Frame(harmos,borderwidth=1)
harmos2 = Frame(harmos,borderwidth=1)
harmos3 = Frame(harmos,borderwidth=1)
harmos4 = Frame(harmos,borderwidth=1)
harmos5 = Frame(harmos,borderwidth=1)
harmos6 = Frame(harmos,borderwidth=1)
harmos7 = Frame(harmos,borderwidth=1)
harmos8 = Frame(harmos,borderwidth=1)
harmos9 = Frame(harmos,borderwidth=1)


ampli0_ech=IntVar()
ampli0_ech.set(50)
ampli0 = StringVar()
ampli0_check = IntVar()

ampli1_ech=IntVar()
ampli1_ech.set(0)
ampli1 = StringVar()
ampli1_check = IntVar()

ampli2_ech=IntVar()
ampli2_ech.set(0)
ampli2 = StringVar()
ampli2_check = IntVar()

ampli3_ech=IntVar()
ampli3_ech.set(0)
ampli3 = StringVar()
ampli3_check = IntVar()

ampli4_ech=IntVar()
ampli4_ech.set(0)
ampli4 = StringVar()
ampli4_check = IntVar()

ampli5_ech=IntVar()
ampli5_ech.set(0)
ampli5 = StringVar()
ampli5_check = IntVar()

ampli6_ech=IntVar()
ampli6_ech.set(0)
ampli6 = StringVar()
ampli6_check = IntVar()

ampli7_ech=IntVar()
ampli7_ech.set(0)
ampli7 = StringVar()
ampli7_check = IntVar()

ampli8_ech=IntVar()
ampli8_ech.set(0)
ampli8 = StringVar()
ampli8_check = IntVar()

ampli9_ech=IntVar()
ampli9_ech.set(0)
ampli9 = StringVar()
ampli9_check = IntVar()


echelle0=Scale(harmos0, variable=ampli0_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle0.pack(side=RIGHT)
echelle1=Scale(harmos1, variable=ampli1_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle1.pack(side=RIGHT)
echelle2=Scale(harmos2, variable=ampli2_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle2.pack(side=RIGHT)
echelle3=Scale(harmos3, variable=ampli3_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle3.pack(side=RIGHT)
echelle4=Scale(harmos4, variable=ampli4_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle4.pack(side=RIGHT)
echelle5=Scale(harmos5, variable=ampli5_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle5.pack(side=RIGHT)
echelle6=Scale(harmos6, variable=ampli6_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle6.pack(side=RIGHT)
echelle7=Scale(harmos7, variable=ampli7_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle7.pack(side=RIGHT)
echelle8=Scale(harmos8, variable=ampli8_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle8.pack(side=RIGHT)
echelle9=Scale(harmos9, variable=ampli9_ech,from_=-100,to=100,length=200,orient="horizontal",command=mise_a_jour_ech)
echelle9.pack(side=RIGHT)

case0 = Entry(harmos0, textvariable=ampli0, width=3)
case0.pack(side=RIGHT,padx=20)
case0.insert(1,'50')
case0.bind("<Return>",mise_a_jour_bis)
case1 = Entry(harmos1, textvariable=ampli1, width=3)
case1.pack(side=RIGHT,padx=20)
case1.insert(1,'0')
case1.bind("<Return>",mise_a_jour_bis)
case2 = Entry(harmos2, textvariable=ampli2, width=3)
case2.pack(side=RIGHT,padx=20)
case2.insert(1,'0')
case2.bind("<Return>",mise_a_jour_bis)
case3 = Entry(harmos3, textvariable=ampli3, width=3)
case3.pack(side=RIGHT,padx=20)
case3.insert(1,'0')
case3.bind("<Return>",mise_a_jour_bis)
case4 = Entry(harmos4, textvariable=ampli4, width=3)
case4.pack(side=RIGHT,padx=20)
case4.insert(1,'0')
case4.bind("<Return>",mise_a_jour_bis)
case5 = Entry(harmos5, textvariable=ampli5, width=3)
case5.pack(side=RIGHT,padx=20)
case5.insert(1,'0')
case5.bind("<Return>",mise_a_jour_bis)
case6 = Entry(harmos6, textvariable=ampli6, width=3)
case6.pack(side=RIGHT,padx=20)
case6.insert(1,'0')
case6.bind("<Return>",mise_a_jour_bis)
case7 = Entry(harmos7, textvariable=ampli7, width=3)
case7.pack(side=RIGHT,padx=20)
case7.insert(1,'0')
case7.bind("<Return>",mise_a_jour_bis)
case8 = Entry(harmos8, textvariable=ampli8, width=3)
case8.pack(side=RIGHT,padx=20)
case8.insert(1,'0')
case8.bind("<Return>",mise_a_jour_bis)
case9 = Entry(harmos9, textvariable=ampli9, width=3)
case9.pack(side=RIGHT,padx=20)
case9.insert(1,'0')
case9.bind("<Return>",mise_a_jour_bis)


check0 = Checkbutton(harmos0, variable=ampli0_check, command = mise_a_jour)
check0.pack(side=LEFT)
check0.select()
check1 = Checkbutton(harmos1, variable=ampli1_check, command = mise_a_jour)
check1.pack(side=LEFT)
check1.select()
check2 = Checkbutton(harmos2, variable=ampli2_check, command = mise_a_jour)
check2.pack(side=LEFT)
check2.select()
check3 = Checkbutton(harmos3, variable=ampli3_check, command = mise_a_jour)
check3.pack(side=LEFT)
check3.select()
check4 = Checkbutton(harmos4, variable=ampli4_check, command = mise_a_jour)
check4.pack(side=LEFT)
check4.select()
check5 = Checkbutton(harmos5, variable=ampli5_check, command = mise_a_jour)
check5.pack(side=LEFT)
check5.select()
check6 = Checkbutton(harmos6, variable=ampli6_check, command = mise_a_jour)
check6.pack(side=LEFT)
check6.select()
check7 = Checkbutton(harmos7, variable=ampli7_check, command = mise_a_jour)
check7.pack(side=LEFT)
check7.select()
check8 = Checkbutton(harmos8, variable=ampli8_check, command = mise_a_jour)
check8.pack(side=LEFT)
check8.select()
check9 = Checkbutton(harmos9, variable=ampli9_check, command = mise_a_jour)
check9.pack(side=LEFT)
check9.select()


text_ampli0 = Label(harmos0,text="Fondamentale",font=("Arial",15))
text_ampli0.pack(side=LEFT)
text_ampli1 = Label(harmos1,text="Harmonique 1",font=("Arial",15))
text_ampli1.pack(side=LEFT)
text_ampli2 = Label(harmos2,text="Harmonique 2",font=("Arial",15))
text_ampli2.pack(side=LEFT)
text_ampli3 = Label(harmos3,text="Harmonique 3",font=("Arial",15))
text_ampli3.pack(side=LEFT)
text_ampli4 = Label(harmos4,text="Harmonique 4",font=("Arial",15))
text_ampli4.pack(side=LEFT)
text_ampli5 = Label(harmos5,text="Harmonique 5",font=("Arial",15))
text_ampli5.pack(side=LEFT)
text_ampli6 = Label(harmos6,text="Harmonique 6",font=("Arial",15))
text_ampli6.pack(side=LEFT)
text_ampli7 = Label(harmos7,text="Harmonique 7",font=("Arial",15))
text_ampli7.pack(side=LEFT)
text_ampli8 = Label(harmos8,text="Harmonique 8",font=("Arial",15))
text_ampli8.pack(side=LEFT)
text_ampli9 = Label(harmos9,text="Harmonique 9",font=("Arial",15))
text_ampli9.pack(side=LEFT)

harmos0.pack(padx=2, pady=2,side=TOP)
harmos1.pack(padx=2, pady=2,side=TOP)
harmos2.pack(padx=2, pady=2,side=TOP)
harmos3.pack(padx=2, pady=2,side=TOP)
harmos4.pack(padx=2, pady=2,side=TOP)
harmos5.pack(padx=2, pady=2,side=TOP)
harmos6.pack(padx=2, pady=2,side=TOP)
harmos7.pack(padx=2, pady=2,side=TOP)
harmos8.pack(padx=2, pady=2,side=TOP)
harmos9.pack(padx=2, pady=2,side=TOP)

harmosbas = Frame(harmos)
coche = Button(harmosbas,font=("Arial",10),text="coche/décoche tout",command = cochedecoche)
coche.pack(side=LEFT)
zero = Button(harmosbas,font=("Arial",10),text="remise à zéro",command = set_zero)
zero.pack(padx=5,side=RIGHT)
harmosbas.pack(padx=2,pady=10,side=TOP)
harmos.pack(side=LEFT,padx=5, pady=5)

####


boutons = Frame(fenetre_droite)
boutons_predef = Frame(boutons,borderwidth=1,relief="solid")
predef_triangles = Button(boutons_predef,font=("Arial",15),text="Fonction triangles", command = set_triangles)
predef_triangles.pack(side=TOP,padx=5,pady=2)
predef_cercles = Button(boutons_predef,font=("Arial",15),text="Fonction cercles", command = set_cercles)
predef_cercles.pack(side=TOP,padx=5,pady=2)
predef_scie = Button(boutons_predef,font=("Arial",15),text="Fonction scie", command = set_scie)
predef_scie.pack(side=TOP,padx=5,pady=2)
predef_creneaux = Button(boutons_predef,font=("Arial",15),text="Fonction créneaux", command = set_creneaux)
predef_creneaux.pack(side=TOP,padx=5,pady=2)
bouton_joue = Button(boutons,font=("Arial",15), text="Jouer le son", command = joue)
bouton_quitter = Button(boutons,font=("Arial",15), text="Quitter", command = fenetre.destroy)
bouton_quitter.pack(side=RIGHT,padx=50,pady=2)
boutons_predef.pack(side=LEFT,padx=10, pady=5)
bouton_joue.pack(side=LEFT,padx=50,pady=10)
boutons.pack(pady=0,padx=0,side=BOTTOM)
fenetre_droite.pack(side=RIGHT,padx=5,pady=5)

fenetre.mainloop()





