chromatic_texture_generator.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #!/usr/bin/env python3
  2. from itertools import cycle
  3. from itertools import chain
  4. from recipes import take
  5. import os
  6. import webbrowser
  7. import uuid
  8. import random
  9. import shutil
  10. import argparse
  11. from iterlib import *
  12. #from gooey import Gooey
  13. def flip_tuple(t):
  14. (a, b) = t
  15. return (b, a)
  16. def list_index(l):
  17. "Make index for l that maps the item value to its position in l"
  18. return dict(map(flip_tuple, enumerate(l)))
  19. octaves = [r" ", r"'", r"''", r"'''"]
  20. octave_to_number = list_index(octaves)
  21. num_octaves = len(octaves)
  22. def choose_octaves(number_of_them):
  23. os = take(number_of_them, cycle(octaves))
  24. random.shuffle(os)
  25. return os
  26. def choose_chromatics(number_of_them):
  27. notes = take(number_of_them, cycle(scales))
  28. # scale or scales above?
  29. return notes
  30. def octave_inc_wrapping(o):
  31. n = octave_to_number[o] + 1
  32. if n >= num_octaves:
  33. n2 = 0
  34. else:
  35. n2 = n
  36. return octaves[n2]
  37. scales = ["c", "cs", "d", "ds", "e", "f", "fs", "g", "gs", "a", "as", "b"]
  38. scale_to_number = list_index(scales)
  39. num_scales = len(scales)
  40. def scale_and_octave_to_number(so):
  41. (s, o) = so
  42. return scale_to_number[s] + octave_to_number[o] * num_scales
  43. def wrapping_number_to_scale_and_octave(num):
  44. (onum, snum) = divmod(num, num_scales)
  45. if onum >= num_octaves:
  46. onum = onum % num_octaves
  47. return (scales[snum], octaves[onum])
  48. def fix_octave(previous, current):
  49. if previous:
  50. if scale_and_octave_to_number(current) - scale_and_octave_to_number(previous) == 1:
  51. return wrapping_number_to_scale_and_octave(scale_and_octave_to_number(current) + 12)
  52. else:
  53. return current
  54. else:
  55. return current
  56. def concatenate_notes_and_octaves(amount):
  57. noters = choose_chromatics(amount)
  58. number = choose_octaves(amount)
  59. return map_with_previous_result(fix_octave, None, zip(noters, number))
  60. # return map_with_previous(fix_octave, zip(noters, number), [("c", "'"), ("c", "'")])
  61. #@Gooey
  62. def main():
  63. my_parser = argparse.ArgumentParser()
  64. my_parser.add_argument("--chroma", action="store", type=int, required=True)
  65. my_parser.add_argument("--rhythm", action="store", type=int, required=True)
  66. # my_parser.add_argument("--id", action="store", type=int)
  67. args = my_parser.parse_args()
  68. amount = args.chroma
  69. timer = args.rhythm
  70. result = concatenate_notes_and_octaves(amount)
  71. print_notes(result, timer)
  72. def print_notes(result, timer):
  73. res = ["".join(tup) for tup in result]
  74. timer2 = str(timer)
  75. filename = uuid.uuid4().hex + ".ly"
  76. f = open(filename,"a+")
  77. f.write(r'\language "english"')
  78. f.write(r'\version "2.19.82"')
  79. f.write(r'\include "lit.ily"')
  80. f.write("\n")
  81. f.write(r"\score")
  82. f.write(r"{")
  83. f.write("\n")
  84. f.write(r"\new PianoStaff <<")
  85. f.write(r'\new Staff = "up" {')
  86. f.write(r"\time 3/4")
  87. f.write("\n")
  88. f.write(r'\clef "treble"')
  89. for n in res:
  90. if r"'" in n:
  91. f.write(r'\change Staff = "up"')
  92. f.write(n + timer2)
  93. elif r"''" in n:
  94. f.write(r'\change Staff = "up"')
  95. f.write(n + timer2)
  96. elif r"'''" in n:
  97. f.write(n + timer2)
  98. elif r"," in n:
  99. f.write(r'\change Staff = "down"')
  100. f.write(n + timer2)
  101. elif r",," in n:
  102. f.write(r'\change Staff = "down"')
  103. f.write(n + timer2)
  104. elif r",,," in n:
  105. f.write(r'\change Staff = "down"')
  106. f.write(n + timer2)
  107. else:
  108. f.write(r'\change Staff = "down"')
  109. f.write(n + timer2)
  110. f.write("\n")
  111. f.write(r"}")
  112. f.write("\n")
  113. f.write(r'\new Staff = "down" {')
  114. f.write(r"\time 3/4")
  115. f.write(r'\clef "bass"')
  116. for n in res:
  117. f.write("s" + timer2)
  118. f.write(r"}")
  119. f.write(r">>")
  120. f.write("\n")
  121. f.write(r"\layout { }")
  122. f.write(r"\midi { }")
  123. f.write(r"}")
  124. f.close()
  125. lilypond = "lilypond " + filename
  126. os.system(lilypond)
  127. webbrowser.open_new(filename[:-3] + ".pdf")
  128. # pdf_viewer = "zathura " + "*.pdf"
  129. # os.system(pdf_viewer)
  130. # midi_player = "mscore " + "*.midi"
  131. # os.system(midi_player)
  132. #os.mkdir(filename[:-3])
  133. #shutil.move(filename, filename[:-3])
  134. #shutil.move(filename[:-3] + ".pdf", filename[:-3])
  135. #shutil.move(filename[:-3] + ".midi", filename[:-3])
  136. #shutil.move(filename[:-3], "generations/")
  137. if __name__ == "__main__":
  138. main()