Guest User

Untitled

a guest
Jul 20th, 2018
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.80 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. #-*- coding: utf8 -*-
  3.  
  4.  
  5. """
  6. guitar chords manager.py
  7. """
  8.  
  9.  
  10. """
  11. this is a stand-alone module that gives guitar chords (taking the postion
  12. of fingers) their notes and names.
  13.  
  14. Instructions :
  15. just call :
  16. -- GuitarChords(arg) --
  17. where arg is a list of your chords ie [0,0,2,2,1,0] for a Am
  18. """
  19.  
  20.  
  21. # import
  22.  
  23. import sys, logging
  24. from collections import Iterable
  25.  
  26.  
  27. # logging
  28.  
  29. l = logging.WARNING
  30. logging.basicConfig(level=l, format="%(levelname)s : %(message)s")
  31. info = logging.info
  32.  
  33.  
  34. # class
  35.  
  36. class GuitarChords(object) :
  37.  
  38.  
  39. # consts
  40.  
  41. __SCALE = { 0 : "C",
  42. 1 : "C#",
  43. 2 : "D",
  44. 3 : "D#",
  45. 4 : "E",
  46. 5 : "F",
  47. 6 : "F#",
  48. 7 : "G",
  49. 8 : "G#",
  50. 9 : "A",
  51. 10 : "A#",
  52. 11 : "B",
  53. 12 : "C",
  54. -1000 : "x" }
  55.  
  56.  
  57. __RSCALE = {j:i for i,j in __SCALE.items()}
  58.  
  59. __CORDS = ["E", "A", "D", "G", "B", "E"]
  60.  
  61. __RCORDS = [ 4, 9, 2, 7, 11, 4]
  62.  
  63. #-------------------------------------------
  64. # add banjo and ukulele chords
  65. #-------------------------------------------
  66.  
  67.  
  68. def __init__(self, *arg) :
  69.  
  70. # consts
  71. self.scale = GuitarChords.__SCALE
  72. self.rscale = GuitarChords.__RSCALE
  73. self.cords = GuitarChords.__CORDS
  74. self.rcords = GuitarChords.__RCORDS
  75.  
  76. info("self.cords : "+ str(self.cords))
  77.  
  78. # handle argument type
  79. if len(arg) == 1 :
  80. arg = arg[0]
  81.  
  82. # good length
  83. if len(arg) != 6 :
  84. raise ValueError("arg must be iterable of 6 elements")
  85.  
  86. self.init_arg = list(arg)
  87.  
  88. info("init_arg : "+ str(arg))
  89. info("len init_arg : "+str(len(arg)))
  90.  
  91. # good type
  92. self.convert_arg = [(i if isinstance(i, int) else -1) for i in arg]
  93.  
  94. # len
  95. try:
  96. arg = [int(i) for i in arg]
  97. except Exception as e:
  98. raise ValueError("arg must be iterable of 6 ints")
  99.  
  100. # if a cords is not played
  101. self.non_cords = [i for i,j in enumerate(self.convert_arg) if j == -1]
  102. info("non_cords : "+ str(self.non_cords))
  103.  
  104. self.chords = [i for i in arg if i != -1]
  105. info("chords : "+ str(self.chords))
  106.  
  107. for i in self.non_cords :
  108. self.cords.pop(i)
  109. self.rcords.pop(i)
  110.  
  111. info("cords : "+ str(self.cords))
  112. info("rcords : "+ str(self.rcords))
  113.  
  114. # attribute creator
  115. self.ints = self.cords_to_ints(self.chords)
  116. info("ints : "+ str(self.ints))
  117.  
  118. self.notes = self.ints_to_notes(self.ints)
  119. info("notes : "+ str(self.notes ))
  120.  
  121. self.acc = self.ints_to_acc(self.ints)
  122. info("acc : "+ str(self.acc))
  123.  
  124. self.order_notes = self.ordered_notes()
  125. info("order_notes : "+ str(self.order_notes))
  126.  
  127. self.name = self.acc_to_name(self.acc)
  128. info("name : "+ str(self.name))
  129.  
  130. print(self)
  131.  
  132.  
  133. def cords_to_ints(self, arg) :
  134.  
  135. info("arg : "+ str(arg))
  136. info("rcords : "+ str(self.rcords))
  137.  
  138. arg = [(i+j) for i,j in zip(self.rcords, arg)]
  139.  
  140. arg = [i% 12 for i in arg]
  141.  
  142. return arg
  143.  
  144.  
  145. def notes_to_ints(self, arg) :
  146.  
  147. if isinstance(arg, Iterable) :
  148. # add upper
  149. return self.__modulo([self.rscale[i] for i in arg])
  150. else :
  151. # add uper
  152. return self.rscale[self.self.__modulo(arg)]
  153.  
  154.  
  155. def ints_to_notes(self, arg) :
  156.  
  157. if isinstance(arg, Iterable) :
  158. return [self.scale[i] for i in self.__modulo(arg)]
  159. else :
  160. return self.scale[self.__modulo(arg)]
  161.  
  162.  
  163. def __unique(self, arg) :
  164.  
  165. return list(set(arg))
  166.  
  167.  
  168. def __modulo(self, arg) :
  169.  
  170. if isinstance(arg, Iterable) :
  171. return [i%12 for i in arg]
  172. else :
  173. return arg%12
  174.  
  175.  
  176. def ints_to_acc(self, arg) :
  177.  
  178. # __unique
  179. arg = self.__unique(arg)
  180. arg = sorted(arg)
  181.  
  182. # init default values
  183. tonic, sec, tierc, quart, quint, sixt, sept = [-1] * 7
  184. acc = tonic, sec, tierc, quart, quint, sixt, sept
  185.  
  186. # handle len of arg
  187. if len(arg)< 3 :
  188. raise ValueError("Min 3 notes for accord")
  189.  
  190. if len(arg) == 3 :
  191. a0, a1, a2 = arg
  192. _arg = [ (a0, a1, a2),
  193. (a1, a2, a0+12),
  194. (a2, a0+12, a1+12) ]
  195.  
  196. if len(arg) == 4 :
  197. a0, a1, a2, a3 = arg
  198. _arg = [ (a0, a1, a2, a3),
  199. (a1, a2, a3, a0+12),
  200. (a2, a3, a0+12, a1+12),
  201. (a3, a0+12, a1+12, a2+12) ]
  202.  
  203. if len(arg) == 5 :
  204. a0, a1, a2, a3, a4 = arg
  205. _arg = [ (a0, a1, a2, a3,a4),
  206. (a1, a2, a3, a4, a0+12),
  207. (a2, a3, a4, a0+12, a1+12),
  208. (a3, a4, a0+12, a1+12, a2+12),
  209. (a4, a0+12, a1+12, a2+12, a3+12) ]
  210.  
  211. # # tonic and quint JUST ONLY
  212. for a in _arg :
  213. tup = [(t,q) for t in a for q in a if q-t == 7 ]
  214.  
  215. if len(tup) == 1 :
  216.  
  217. tonic, quint = tup[0]
  218. arg = a
  219. break
  220.  
  221. info("acc : " + str(arg))
  222. # info("acc : " + str(ints_to_notes(__modulo(arg))))
  223.  
  224. # all others
  225. for note in arg :
  226. inter = int(note - tonic)
  227. if inter in [1, 2] : sec = note
  228. if inter in [3, 4] : tierc = note
  229. if inter in [6] : quart = note
  230. if inter in [8, 9] : sixt = note
  231. if inter in [10, 11] : sept = note
  232.  
  233. # regroup in acc
  234. acc = [tonic, sec, tierc, quart, quint, sixt, sept]
  235. # info("acc : " + str(acc))
  236.  
  237. # # delete notes if needed
  238. # acc = [i for i in acc if i>=0]
  239.  
  240. # acc = [i%12 for i in acc]
  241.  
  242. return acc
  243.  
  244.  
  245. def acc_to_name(self, arg) :
  246.  
  247. if len(arg) !=7:
  248. raise ValueError("call ints_to_acc() before")
  249.  
  250. # init default values
  251. str_tonic, str_tierc, str_sept = [""] * 3
  252.  
  253. # tonic
  254. str_tonic = self.ints_to_notes(self.__modulo(arg[0]))
  255.  
  256. # shift idexes to have arg[3] => Tierce
  257. arg = [-100] + arg
  258.  
  259. # ask for toniq == 0
  260. t = arg[1]
  261. arg = [i- t for i in arg]
  262.  
  263. # tierc
  264. if arg[3] == 3 : str_tierc = "m"
  265. elif arg[3] == 4 : str_tierc = " "
  266.  
  267. # sept
  268. if arg[7] == 10 : str_tierc = "7"
  269. elif arg[7] == 11 : str_tierc = "M7"
  270.  
  271. # -----------------------------------
  272. # add sus 2 sus4, dim, aug, 9, 11, 13
  273. # -----------------------------------
  274.  
  275. txt = str_tonic + str_tierc + str_sept
  276.  
  277. return txt
  278.  
  279.  
  280. def ordered_notes(self) :
  281.  
  282. if self.acc :
  283. acc = [i for i in self.acc if i !=-1]
  284. acc = self.__modulo(acc)
  285. acc = self.ints_to_notes(acc)
  286.  
  287. return acc
  288.  
  289. return None
  290.  
  291.  
  292. def __str__(self) :
  293.  
  294. return self.__repr__()
  295.  
  296.  
  297. def __repr__(self) :
  298.  
  299. txt =str(
  300. "init_arg : " + str(self.init_arg) +"\n"
  301. "notes : " + str(self.notes) +"\n"
  302. "order_notes : " + str(self.order_notes) +"\n"
  303. "name : " + str(self.name) +"\n" )
  304.  
  305. return txt
  306.  
  307.  
  308. # main
  309.  
  310. def main():
  311.  
  312. print(str( "\n"
  313. "-------------------------------------------\n"
  314. "exemple with g = GuitarChords(0,2,2,1,0,0) \n"
  315. "-------------------------------------------\n\n"))
  316.  
  317. g = GuitarChords(0,2,2,1,0,0)
  318.  
  319.  
  320. if __name__ == '__main__':
  321. main()
Add Comment
Please, Sign In to add comment