mktune.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from xml.etree import ElementTree as ET
  2. import optparse
  3. parser = optparse.OptionParser()
  4. parser.add_option('-t', '--tempo', dest='tempo', type='float', help='Tempo (in BPM)')
  5. parser.add_option('-r', '--resolution', dest='resolution', type='float', help='Approximate resolution in seconds (overrides tempo)')
  6. parser.add_option('-f', '--float', dest='float', action='store_true', help='Allow floating point representations on output')
  7. parser.add_option('-T', '--transpose', dest='transpose', type='float', help='Transpose by this many semitones')
  8. parser.set_defaults(tempo=60000, resolution=None, transpose=0)
  9. options, args = parser.parse_args()
  10. maybe_int = int
  11. if options.float:
  12. maybe_int = float
  13. class Note(object):
  14. def __init__(self, time, dur, pitch, ampl):
  15. self.time = time
  16. self.dur = dur
  17. self.pitch = pitch
  18. self.ampl = ampl
  19. if options.resolution is not None:
  20. options.tempo = 60.0 / options.resolution
  21. options.tempo = maybe_int(options.tempo)
  22. def to_beats(tm):
  23. return options.tempo * tm / 60.0
  24. for fname in args:
  25. try:
  26. iv = ET.parse(fname).getroot()
  27. except IOError:
  28. import traceback
  29. traceback.print_exc()
  30. print fname, ': Bad file'
  31. continue
  32. print options.tempo,
  33. ns = iv.find('./streams/stream[@type="ns"]')
  34. prevn = None
  35. for note in ns.findall('note'):
  36. n = Note(
  37. float(note.get('time')),
  38. float(note.get('dur')),
  39. float(note.get('pitch')) + options.transpose,
  40. float(note.get('ampl', float(note.get('vel', 127.0)) / 127.0)),
  41. )
  42. if prevn is not None:
  43. rtime = to_beats(n.time - (prevn.time + prevn.dur))
  44. if rtime >= 1:
  45. print 0, maybe_int(rtime),
  46. ntime = to_beats(prevn.dur)
  47. if ntime < 1 and not options.float:
  48. ntime = 1
  49. print maybe_int(440.0 * 2**((prevn.pitch-69)/12.0)), maybe_int(ntime),
  50. prevn = n
  51. ntime = to_beats(n.dur)
  52. if ntime < 1 and not options.float:
  53. ntime = 1
  54. print int(440.0 * 2**((n.pitch-69)/12.0)), int(ntime),