# -*-coding:Latin-1 -* """Analyse du micro et stockage des parametres pour le chat vocal""" import audioop import time from math import fabs import cPickle as pickle #lecture/ecriture d'objets dans un fichier #modules complémentaires import pymedia.audio.sound as sound class AnaSon(): """analyse et stocke les parametres d'entree du son (version pymedia)""" def __init__(self): """initialisation des parametres par defauts""" #puissance moyenne du son en silence self.pMoy_silence = 1800 #ecarts liees aux parasites self.ecartSilence = 500 #puissance moyenne du son en parlant self.pMoy_parle = 16000 #coeff de puissance self.coeffP = 1.00 #puissance de reference self.pRef = 20000 #forme d'onde (liste des puissances) en silence et en parlant self.formeS = [] self.formeP = [] #duree des tests self.duree = 5 #peripheriques par defaut: self.IDmicro = 0 #pour le traitement du son: self.compte = 0 #affiche des infos self.affichage = True #fichier de sauvegarde self.fichier = "param_micro" self.ecoute = False #pour enregistrement de la reception #self.enregistrement = open( "ResultatAnalyse.mp3", 'wb' ) def recup(self): """recupere si possible les parametres enregistres""" try: with open(self.fichier, 'rb') as f: tmp = pickle.load(f) f.close() print("Parametres récupérés") except IOError: tmp = self print("Pas de parametres enregistres, parametres par defaut utilises") return tmp def sauver(self): """sauvegarde les parametres analyses""" with open(self.fichier, 'wb') as f: pickle.dump(self, f, -1) f.close() print("Parametres sauvegardes.") def analyser(self): """lance l'analyse du son""" print("\n*** Analyse du micro ***\n") #phase 1: quel micro? print(sound.getIDevices()) self.IDmicro = input("\nMicro par defaut? (id) > ") micro = sound.Input( 16000, 1, sound.AFMT_S16_LE, self.IDmicro ) micro.start() sortie = sound.Output( 16000, 1, sound.AFMT_S16_LE ) enregistrement = open( "ResultatsAnaSon.mp3", 'wb' ) # phase 2 : parasites #liste des donnees recues au cours de l'analyse frames_test = [] #boucle de reception print("Test des parasites: ne parlez pas (env. {} sec)\n".format(self.duree+1)) pause = raw_input("Appuyez sur Entree pour lancer: \n") t0 = time.time() while time.time() - t0 < self.duree: son = micro.getData() if son and len(son): frames_test.append(son) #audioop.rms renvoie la puissance moyenne du son self.formeS.append(audioop.rms(son,2)) #on enleve la premiere valeur qui n'est generalement pas representative: del frames_test[0] del self.formeS[0] print("{}\n".format(self.formeS)) #donnees utilisees pour l'attenuation du son lors des silences: self.pMoy_silence = audioop.rms(b''.join(frames_test),2) self.ecartMax = 0 ecart_mesure = 0 for son in frames_test: if fabs(audioop.rms(son,2) - self.pMoy_silence) > ecart_mesure: ecart_mesure = fabs(audioop.rms(son,2) - self.pMoy_silence) if ecart_mesure > 10: self.ecartSilence = ecart_mesure # phase 3 : parle frames_test = [] print("Test de la voix: parlez normalement (env. {} sec)\n ".format(self.duree+1)) pause = raw_input("Appuyez sur Entree pour lancer: \n") t0 = time.time() while time.time() - t0 < self.duree: son = micro.getData() if son and len(son): self.formeP.append(audioop.rms(son,2)) if audioop.rms(son,2) > (self.pMoy_silence + self.ecartSilence): frames_test.append(son) #on enleve la premiere valeur qui n'est generalement pas representative: del self.formeP[0] print("{}\n".format(self.formeP)) if len(frames_test)>0: del frames_test[0] self.pMoy_parle = audioop.rms(b''.join(frames_test),2) #mise a jour du coeff de puissance: if self.pMoy_parle != 0: self.coeffP = self.pRef / self.pMoy_parle if self.coeffP < 0.2: self.coeffP = 0.20 elif self.coeffP > 4: self.coeffP = 4.00 else: print("\n (!) Erreur: la puissance de la voix est insuffisante pour etre detectee") print("\n*** Fin de l'analyse ***\n") micro.stop() enregistrement.close() self.sauver() def traitement(self, data): """renvoie la donnee sonore traitee selon les parametres utilises""" #est-on dans la 'zone de silence'? kS = 1 retour = None seuil_iterations = 3 if audioop.rms(data,2) <= self.pMoy_silence + self.ecartSilence: #on ne diminue la puissance du son qu'apres un certain nombre d'iterations (4 ici) self.compte += 1 if self.compte > seuil_iterations: if self.affichage and self.compte == seuil_iterations + 1: print("\n-> silence") kS = 0.2 else: if self.affichage and self.compte != 0: print("\n-> parle") self.compte = 0 #retour = audioop.mul(data, 2, (self.coeffP)) kS = 1 retour = audioop.mul(data, 2, (kS * self.coeffP)) return retour def ecouterMicro(self): """ecouter son micro""" micro = sound.Input( 16000, 1, sound.AFMT_S16_LE, self.IDmicro ) micro.start() sortie = sound.Output( 16000, 1, sound.AFMT_S16_LE ) t0 = time.time() #while time.time() - t0 < self.duree: while True: son = micro.getData() if son and len(son): son_traite = self.traitement(son) #print("{} - {}".format(audioop.rms(son,2), audioop.rms(son_traite,2))) sortie.play(son_traite) micro.stop() def __repr__(self): """affiche les parametres utilises""" chaine = "\n*** Parametres utilises ***\n"\ "\n Puissance moyenne en silence: {} "\ "\n Amplitude parasites: {} "\ "\n Puissance moyenne en parlant: {} "\ "\n Multiplicateur applique: {} "\ "".format(self.pMoy_silence, self.ecartSilence, self.pMoy_parle, self.coeffP) return chaine ######### si lancement direct ######## if __name__ == "__main__": a = AnaSon() a.analyser() #a = None #a = AnaSon() #a = a.recup() print(a) #a.ecouterMicro() #a.analyser() pause = raw_input("appuyez sur entree")