/utils/make_sounds.py

http://eyes-free.googlecode.com/ · Python · 88 lines · 75 code · 1 blank · 12 comment · 2 complexity · aa9a9ff26b685d32a13ad4bf71b3ad48 MD5 · raw file

  1. #!/usr/bin/python2.4
  2. # Copyright 2008 Google Inc. All Rights Reserved.
  3. """ Script to generate wav files for a bunch of letters, numbers,
  4. and short phrases using the Mac's built-in "say" command and the open-source"sndfile-convert" program (part of "libsndfile")
  5. On a big-endian machine (PPC Mac), replace '-s2 01' with '-s2 10', below
  6. """
  7. import sys, os
  8. def exists(filename):
  9. return os.access(filename, os.F_OK)
  10. def run(cmd):
  11. print " %s" % cmd
  12. status = os.system(cmd)
  13. if status != 0:
  14. sys.exit(status)
  15. lexicon = [
  16. "button",
  17. "clear",
  18. "cleared",
  19. "dial",
  20. "dialing mode",
  21. "disabled",
  22. "edit text",
  23. "list item",
  24. "phone number",
  25. "text view",
  26. "you are about to dial"]
  27. # alphabet
  28. lexicon += [chr(i) for i in range(ord('a'), ord('z') + 1)]
  29. # digits
  30. lexicon += [chr(i) for i in range(ord('0'), ord('9') + 1)]
  31. def main ():
  32. "Generate the samples we need."
  33. # create a 200-ms silent file to append
  34. num_silent_samples = 4410
  35. fp = open('silent_padding.raw', 'w')
  36. fp.write('\0' * num_silent_samples * 2)
  37. fp.close()
  38. for word in lexicon:
  39. filename = (word + '.wav').replace(' ', '_')
  40. if len(word) == 1 and ord(word) >= ord('0') and ord(word) <= ord('9'):
  41. filename = 'num' + filename
  42. if not exists(filename):
  43. print '%s -> %s' % (word, filename)
  44. # Execute TTS and get an AIFF file
  45. run('echo "[[rate 280]] %s" | say -f - -o tmp.aiff' % word)
  46. # Convert to RAW
  47. run('sndfile-convert tmp.aiff tmp.raw')
  48. # Get its length
  49. num_samples = len(open('tmp.raw').read()) / 2
  50. # Create a NIST header (easy text format for audio header)
  51. fp = open('header.nist', 'w')
  52. header_text = (
  53. 'NIST_1A\n 1024\nchannel_count -i 1\nsample_rate -i 22050\n'
  54. 'sample_n_bytes -i 2\nsample_sig_bits -i 16\n'
  55. 'sample_coding -s3 pcm\nsample_byte_format -s2 01\n'
  56. 'sample_count -i %d\n'
  57. 'end_head') % (num_samples + num_silent_samples)
  58. # Write the header, padded to exactly 1024 bytes
  59. fp.write(header_text + ('\0' * (1024 - len(header_text))))
  60. fp.close()
  61. # Append header and silence
  62. run('cat header.nist tmp.raw silent_padding.raw > combined.nist')
  63. # Convert final result to WAV
  64. run('sndfile-convert combined.nist %s' % filename)
  65. else:
  66. print '%s -> %s (already exists)' % (word, filename)
  67. print "Cleaning up"
  68. run('rm -f header.nist')
  69. run('rm -f tmp.aiff')
  70. run('rm -f tmp.raw')
  71. run('rm -f silent_padding.raw')
  72. run('rm -f combined.nist')
  73. if __name__ == '__main__':
  74. main()