PageRenderTime 164ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/ARCHIVE/Metronome.py

https://github.com/litdream/Metronome
Python | 143 lines | 134 code | 8 blank | 1 comment | 2 complexity | a731d23171638e2ede8d494c08271aa1 MD5 | raw file
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import struct
  5. import getopt
  6. empty_sound = struct.pack('bbbbbbbb', *( 4,0,0,0,6,0,6,0 ))
  7. dryrun = False
  8. class WavHeader(object):
  9. def __init__(self, rawdata):
  10. self.tup = struct.unpack("iiiiihhiihhii", rawdata)
  11. self.chunk_id = self.tup[0]
  12. self.chunk_sz = self.tup[1]
  13. self.format = self.tup[2]
  14. self.sub_chunk1_id = self.tup[3]
  15. self.sub_chunk1_sz = self.tup[4]
  16. self.audio_format = self.tup[5]
  17. self.num_channel = self.tup[6]
  18. self.sample_rate = self.tup[7]
  19. self.byte_rate = self.tup[8]
  20. self.block_align = self.tup[9]
  21. self.bits_per_sample = self.tup[10]
  22. self.sub_chunk2_id = self.tup[11]
  23. self.sub_chunk2_sz = self.tup[12]
  24. def pack(self):
  25. return struct.pack("iiiiihhiihhii", self.chunk_id, self.chunk_sz,
  26. self.format , self.sub_chunk1_id,
  27. self.sub_chunk1_sz , self.audio_format,
  28. self.num_channel , self.sample_rate ,
  29. self.byte_rate , self.block_align ,
  30. self.bits_per_sample, self.sub_chunk2_id,
  31. self.sub_chunk2_sz )
  32. ONE_SEC = 88200
  33. def bytes_for_beat(bpm):
  34. ratio = bpm/60.0
  35. bytes_per_beep = ONE_SEC / ratio
  36. return int(bytes_per_beep)
  37. def make_section(fh, sample_hdr, tempo, dura, sample_data):
  38. tot_beats = dura * (tempo/60.0);
  39. bps = bytes_for_beat(tempo);
  40. tot_bytes = 0;
  41. for i in range( int(tot_beats)):
  42. fh.write( sample_data )
  43. tot_bytes += sample_hdr.sub_chunk2_sz;
  44. for j in range( (bps - sample_hdr.sub_chunk2_sz)/8):
  45. fh.write( empty_sound )
  46. tot_bytes += len(empty_sound)
  47. return tot_bytes
  48. def usage():
  49. print( '''\
  50. %s [Options]
  51. Options:
  52. -h, --help Help screen
  53. --dryrun Don't make wav, but print the action.
  54. -s, --sample=FILENAME Sample file name
  55. Default s3.wav
  56. -t, --tempo=INT Metronome Tempo
  57. -d, --duration=INT Total Duration
  58. ''')
  59. def main():
  60. global dryrun
  61. sample_fname = "s3.wav"
  62. tempo = 999
  63. dura = -1
  64. filename = None
  65. sa = "hs:t:d:f:"
  66. la = ('help', 'dryrun', 'sample=', 'tempo=', 'duration=', 'file=' )
  67. o,a = getopt.getopt(sys.argv[1:], sa, la)
  68. if len(o) + len(a) == 0:
  69. usage()
  70. sys.exit(1)
  71. for k,v in o:
  72. if k in ('-h', '--help') : usage(); sys.exit(0)
  73. elif k in ('-s', '--sample') : sample_fname = v.strip()
  74. elif k in ('-t', '--tempo') : tempo = int(v)
  75. elif k in ('-d', '--duration') : dura = int(v)
  76. elif k in ('-f', '--file') : filename = v.strip()
  77. elif k == '--dryrun' : dryrun = True
  78. if tempo < 40 or tempo > 250:
  79. print( "Invalid tempo (%d): Make it between 40 - MAX" % tempo, file=sys.stderr)
  80. print( " * longer the sample length, smaller the MAX", file=sys.stderr)
  81. sys.exit(1)
  82. # Reading sample header
  83. if sys.platform == 'win32':
  84. rd = open(sample_fname, "rb")
  85. else:
  86. rd = open(sample_fname, "r")
  87. sample_hdr = WavHeader(rd.read(44))
  88. sample_data = rd.read()
  89. rd.close()
  90. # Generating Beat data as WAV, storing temp file 't.wav'
  91. if sys.platform == 'win32':
  92. bdata = open("t.wav", "wb")
  93. else:
  94. bdata = open("t.wav", "w")
  95. tot_bytes = 0
  96. if dura == -1:
  97. dura = 60
  98. if dryrun:
  99. print("will make section of (tempo=%d)" % (tempo))
  100. else:
  101. tot_bytes += make_section(bdata, sample_hdr, tempo, dura, sample_data)
  102. bdata.close()
  103. if dryrun:
  104. sys.exit(0)
  105. # Overwrite new size, and Generate output wav file 'a.wav'
  106. sample_hdr.sub_chunk2_sz = tot_bytes
  107. if sys.platform == 'win32':
  108. outf = open("a.wav", 'wb')
  109. else:
  110. outf = open("a.wav", 'w')
  111. outf.write( sample_hdr.pack() )
  112. if sys.platform == 'win32':
  113. outf.write( open('t.wav', 'rb').read() )
  114. else:
  115. outf.write( open('t.wav').read() )
  116. outf.close()
  117. print("a.wav is made")
  118. os.system("rm -f t.wav")
  119. os.system("mplayer a.wav")
  120. if __name__ == '__main__':
  121. main()