anason.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # -*-coding:Latin-1 -*
  2. """Analyse du micro et stockage des parametres pour le chat vocal"""
  3. import audioop
  4. import time
  5. from math import fabs
  6. import cPickle as pickle #lecture/ecriture d'objets dans un fichier
  7. #modules complémentaires
  8. import pymedia.audio.sound as sound
  9. class AnaSon():
  10. """analyse et stocke les parametres d'entree du son (version pymedia)"""
  11. def __init__(self):
  12. """initialisation des parametres par defauts"""
  13. #puissance moyenne du son en silence
  14. self.pMoy_silence = 1800
  15. #ecarts liees aux parasites
  16. self.ecartSilence = 500
  17. #puissance moyenne du son en parlant
  18. self.pMoy_parle = 16000
  19. #coeff de puissance
  20. self.coeffP = 1.00
  21. #puissance de reference
  22. self.pRef = 20000
  23. #forme d'onde (liste des puissances) en silence et en parlant
  24. self.formeS = []
  25. self.formeP = []
  26. #duree des tests
  27. self.duree = 5
  28. #peripheriques par defaut:
  29. self.IDmicro = 0
  30. #pour le traitement du son:
  31. self.compte = 0
  32. #affiche des infos
  33. self.affichage = True
  34. #fichier de sauvegarde
  35. self.fichier = "param_micro"
  36. self.ecoute = False
  37. #pour enregistrement de la reception
  38. #self.enregistrement = open( "ResultatAnalyse.mp3", 'wb' )
  39. def recup(self):
  40. """recupere si possible les parametres enregistres"""
  41. try:
  42. with open(self.fichier, 'rb') as f:
  43. tmp = pickle.load(f)
  44. f.close()
  45. print("Parametres récupérés")
  46. except IOError:
  47. tmp = self
  48. print("Pas de parametres enregistres, parametres par defaut utilises")
  49. return tmp
  50. def sauver(self):
  51. """sauvegarde les parametres analyses"""
  52. with open(self.fichier, 'wb') as f:
  53. pickle.dump(self, f, -1)
  54. f.close()
  55. print("Parametres sauvegardes.")
  56. def analyser(self):
  57. """lance l'analyse du son"""
  58. print("\n*** Analyse du micro ***\n")
  59. #phase 1: quel micro?
  60. print(sound.getIDevices())
  61. self.IDmicro = input("\nMicro par defaut? (id) > ")
  62. micro = sound.Input( 16000, 1, sound.AFMT_S16_LE, self.IDmicro )
  63. micro.start()
  64. sortie = sound.Output( 16000, 1, sound.AFMT_S16_LE )
  65. enregistrement = open( "ResultatsAnaSon.mp3", 'wb' )
  66. # phase 2 : parasites
  67. #liste des donnees recues au cours de l'analyse
  68. frames_test = []
  69. #boucle de reception
  70. print("Test des parasites: ne parlez pas (env. {} sec)\n".format(self.duree+1))
  71. pause = raw_input("Appuyez sur Entree pour lancer: \n")
  72. t0 = time.time()
  73. while time.time() - t0 < self.duree:
  74. son = micro.getData()
  75. if son and len(son):
  76. frames_test.append(son)
  77. #audioop.rms renvoie la puissance moyenne du son
  78. self.formeS.append(audioop.rms(son,2))
  79. #on enleve la premiere valeur qui n'est generalement pas representative:
  80. del frames_test[0]
  81. del self.formeS[0]
  82. print("{}\n".format(self.formeS))
  83. #donnees utilisees pour l'attenuation du son lors des silences:
  84. self.pMoy_silence = audioop.rms(b''.join(frames_test),2)
  85. self.ecartMax = 0
  86. ecart_mesure = 0
  87. for son in frames_test:
  88. if fabs(audioop.rms(son,2) - self.pMoy_silence) > ecart_mesure:
  89. ecart_mesure = fabs(audioop.rms(son,2) - self.pMoy_silence)
  90. if ecart_mesure > 10:
  91. self.ecartSilence = ecart_mesure
  92. # phase 3 : parle
  93. frames_test = []
  94. print("Test de la voix: parlez normalement (env. {} sec)\n ".format(self.duree+1))
  95. pause = raw_input("Appuyez sur Entree pour lancer: \n")
  96. t0 = time.time()
  97. while time.time() - t0 < self.duree:
  98. son = micro.getData()
  99. if son and len(son):
  100. self.formeP.append(audioop.rms(son,2))
  101. if audioop.rms(son,2) > (self.pMoy_silence + self.ecartSilence):
  102. frames_test.append(son)
  103. #on enleve la premiere valeur qui n'est generalement pas representative:
  104. del self.formeP[0]
  105. print("{}\n".format(self.formeP))
  106. if len(frames_test)>0:
  107. del frames_test[0]
  108. self.pMoy_parle = audioop.rms(b''.join(frames_test),2)
  109. #mise a jour du coeff de puissance:
  110. if self.pMoy_parle != 0:
  111. self.coeffP = self.pRef / self.pMoy_parle
  112. if self.coeffP < 0.2:
  113. self.coeffP = 0.20
  114. elif self.coeffP > 4:
  115. self.coeffP = 4.00
  116. else:
  117. print("\n (!) Erreur: la puissance de la voix est insuffisante pour etre detectee")
  118. print("\n*** Fin de l'analyse ***\n")
  119. micro.stop()
  120. enregistrement.close()
  121. self.sauver()
  122. def traitement(self, data):
  123. """renvoie la donnee sonore traitee selon les parametres utilises"""
  124. #est-on dans la 'zone de silence'?
  125. kS = 1
  126. retour = None
  127. seuil_iterations = 3
  128. if audioop.rms(data,2) <= self.pMoy_silence + self.ecartSilence:
  129. #on ne diminue la puissance du son qu'apres un certain nombre d'iterations (4 ici)
  130. self.compte += 1
  131. if self.compte > seuil_iterations:
  132. if self.affichage and self.compte == seuil_iterations + 1:
  133. print("\n-> silence")
  134. kS = 0.2
  135. else:
  136. if self.affichage and self.compte != 0:
  137. print("\n-> parle")
  138. self.compte = 0
  139. #retour = audioop.mul(data, 2, (self.coeffP))
  140. kS = 1
  141. retour = audioop.mul(data, 2, (kS * self.coeffP))
  142. return retour
  143. def ecouterMicro(self):
  144. """ecouter son micro"""
  145. micro = sound.Input( 16000, 1, sound.AFMT_S16_LE, self.IDmicro )
  146. micro.start()
  147. sortie = sound.Output( 16000, 1, sound.AFMT_S16_LE )
  148. t0 = time.time()
  149. #while time.time() - t0 < self.duree:
  150. while True:
  151. son = micro.getData()
  152. if son and len(son):
  153. son_traite = self.traitement(son)
  154. #print("{} - {}".format(audioop.rms(son,2), audioop.rms(son_traite,2)))
  155. sortie.play(son_traite)
  156. micro.stop()
  157. def __repr__(self):
  158. """affiche les parametres utilises"""
  159. chaine = "\n*** Parametres utilises ***\n"\
  160. "\n Puissance moyenne en silence: {} "\
  161. "\n Amplitude parasites: {} "\
  162. "\n Puissance moyenne en parlant: {} "\
  163. "\n Multiplicateur applique: {} "\
  164. "".format(self.pMoy_silence, self.ecartSilence, self.pMoy_parle, self.coeffP)
  165. return chaine
  166. ######### si lancement direct ########
  167. if __name__ == "__main__":
  168. a = AnaSon()
  169. a.analyser()
  170. #a = None
  171. #a = AnaSon()
  172. #a = a.recup()
  173. print(a)
  174. #a.ecouterMicro()
  175. #a.analyser()
  176. pause = raw_input("appuyez sur entree")