pico2wave.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import os
  2. import subprocess
  3. from kalliope.core.TTS.TTSModule import TTSModule, MissingTTSParameter
  4. import sox
  5. import logging
  6. import sys
  7. logging.basicConfig()
  8. logger = logging.getLogger("kalliope")
  9. class Pico2wave(TTSModule):
  10. def __init__(self, **kwargs):
  11. super(Pico2wave, self).__init__(**kwargs)
  12. self.samplerate = kwargs.get('samplerate', None)
  13. self.path = kwargs.get('path', None)
  14. self._check_parameters()
  15. def _check_parameters(self):
  16. """
  17. Check parameters are ok, raise MissingTTSParameters exception otherwise.
  18. :return: true if parameters are ok, raise an exception otherwise
  19. .. raises:: MissingTTSParameterException
  20. """
  21. if self.language == "default" or self.language is None:
  22. raise MissingTTSParameter("[pico2wave] Missing parameters, check documentation !")
  23. return True
  24. def say(self, words):
  25. """
  26. :param words: The sentence to say
  27. """
  28. self.generate_and_play(words, self._generate_audio_file)
  29. def _generate_audio_file(self):
  30. """
  31. Generic method used as a Callback in TTSModule
  32. - must provided the audio file and write it on the disk
  33. .. raises:: FailToLoadSoundFile
  34. """
  35. if self.path is None:
  36. # we try to get the path from the env
  37. self.path = self._get_pico_path()
  38. # if still None, we set a default value
  39. if self.path is None:
  40. self.path = "/usr/bin/pico2wave"
  41. # pico2wave needs that the file path ends with .wav
  42. tmp_path = self.file_path+".wav"
  43. pico2wave_options = ["-l=%s" % self.language, "-w=%s" % tmp_path]
  44. final_command = list()
  45. final_command.extend([self.path])
  46. final_command.extend(pico2wave_options)
  47. final_command.append(self.words)
  48. logger.debug("[Pico2wave] command: %s" % final_command)
  49. # generate the file with pico2wav
  50. subprocess.call(final_command)
  51. # convert samplerate
  52. if self.samplerate is not None:
  53. tfm = sox.Transformer()
  54. tfm.rate(samplerate=self.samplerate)
  55. tfm.build(str(tmp_path), str(tmp_path) + "tmp_name.wav")
  56. os.rename(str(tmp_path) + "tmp_name.wav", tmp_path)
  57. # remove the extension .wav
  58. os.rename(tmp_path, self.file_path)
  59. @staticmethod
  60. def _get_pico_path():
  61. prog = "pico2wave"
  62. for path in os.environ["PATH"].split(os.pathsep):
  63. path = path.strip('"')
  64. exe_file = os.path.join(path, prog)
  65. if os.path.isfile(exe_file):
  66. return exe_file
  67. return None