raspberry pi zero based drum machine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

test.py 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. from pygame import mixer
  2. import time
  3. import digitalio
  4. import board
  5. import adafruit_matrixkeypad
  6. import pygame
  7. from PIL import Image, ImageDraw, ImageFont
  8. import adafruit_rgb_display.st7789 as st7789
  9. import digitalio
  10. import board
  11. from adafruit_rgb_display.rgb import color565
  12. import adafruit_rgb_display.st7789 as st7789
  13. import lib.FSM
  14. from itertools import cycle
  15. import lib.observer
  16. from scikits.samplerate import resample
  17. from lib.configobj import ConfigObj
  18. #from configobj import ConfigObj
  19. cols = [digitalio.DigitalInOut(x) for x in (board.D21, board.D20, board.D16, board.D12)]
  20. rows = [digitalio.DigitalInOut(x) for x in (board.D26, board.D13, board.D6, board.D5)]
  21. # keys = ((3, 2, 1, 0),
  22. # (7, 6, 5, 4),
  23. # (11, 10, 9, 8),
  24. # (15, 14, 13, 12))
  25. keys = ((15, 14, 13, 12),
  26. (11, 10, 9, 8),
  27. (7, 6, 5, 4),
  28. (3, 2, 1, 0))
  29. keypad = adafruit_matrixkeypad.Matrix_Keypad(rows, cols, keys)
  30. # while True:
  31. # keys = keypad.pressed_keys
  32. # if keys:
  33. # print("Pressed: ", keys)
  34. # time.sleep(0.1)
  35. pygame.init()
  36. mixer.init()
  37. done = False
  38. clock = pygame.time.Clock()
  39. TIMER = pygame.USEREVENT + 1
  40. #pygame.time.set_timer(pygame.USEREVENT + 1, 444)
  41. #pygame.time.set_timer(TIMER, 161)
  42. playhead = 0
  43. timer = pygame.time.get_ticks
  44. start = now = timer()
  45. cs_pin = digitalio.DigitalInOut(board.CE0)
  46. dc_pin = digitalio.DigitalInOut(board.D25)
  47. reset_pin = None
  48. BAUDRATE = 64000000 # The pi can be very fast!
  49. # display = st7789.ST7789(
  50. # board.SPI(),
  51. # cs=cs_pin,
  52. # dc=dc_pin,
  53. # rst=reset_pin,
  54. # baudrate=BAUDRATE,
  55. # width=135,
  56. # height=240,
  57. # x_offset=53,
  58. # y_offset=40,
  59. # )
  60. backlight = digitalio.DigitalInOut(board.D22)
  61. backlight.switch_to_output()
  62. backlight.value = True
  63. buttonA = digitalio.DigitalInOut(board.D23)
  64. buttonB = digitalio.DigitalInOut(board.D24)
  65. buttonA.switch_to_input()
  66. buttonB.switch_to_input()
  67. spi = board.SPI()
  68. # Create blank image for drawing.
  69. # Make sure to create image with mode 'RGB' for full color.
  70. # Get drawing object to draw on image.
  71. # Draw a black filled box to clear the image.
  72. #draw.rectangle((0, 0, width, height), outline=0, fill=(0, 0, 0))
  73. #disp.image(image, rotation)
  74. # Draw some shapes.
  75. # First define some constants to allow easy resizing of shapes.
  76. # Move left to right keeping track of the current x position for drawing shapes.
  77. x = 0
  78. # Turn on the backlight
  79. backlight = digitalio.DigitalInOut(board.D22)
  80. backlight.switch_to_output()
  81. backlight.value = True
  82. class Prog:
  83. def __init__(self):
  84. self.FSM = FSM.ProgFSM(self)
  85. self.font = ImageFont.truetype("/home/pi/examples/HLM.ttf", 64)
  86. #self.h1 = ImageFont.truetype("/home/pi/examples/HLM.ttf", 26)
  87. self.h1 = ImageFont.truetype("/home/pi/Pixellari.ttf", 30)
  88. self.h2 = ImageFont.truetype("/home/pi/Pixellari.ttf", 20)
  89. self.h3 = ImageFont.truetype("/home/pi/Pixellari.ttf", 54)
  90. self.disp = st7789.ST7789(
  91. spi,
  92. cs=cs_pin,
  93. dc=dc_pin,
  94. rst=reset_pin,
  95. baudrate=BAUDRATE,
  96. width=135,
  97. height=240,
  98. x_offset=53,
  99. y_offset=40,
  100. )
  101. self.height = self.disp.width # we swap height/width to rotate it to landscape!
  102. self.width = self.disp.height
  103. self.rotation = 270
  104. self.padding = -2
  105. self.top = self.padding
  106. self.bottom = self.height - self.padding
  107. self.image = Image.new("RGB", (self.width, self.height))
  108. self.draw = ImageDraw.Draw(self.image)
  109. self.playhead = 0
  110. self.playing = False
  111. self.bpm = 90
  112. self.bpm_inc = 1
  113. self.note_bank = 0
  114. self.volume = 10
  115. self.note_vol = 16
  116. self.note_pitch = 0.0
  117. self.soundSlots = []
  118. self.keys = []
  119. self.keyState = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  120. #self.song = [2, 3, 0, 1, 0, 1, 0, 1, 0, 1]
  121. self.song = [0]
  122. self.songCycle = cycle(self.song)
  123. self.curPattern = next(self.songCycle)
  124. self.songStart = self.curPattern
  125. self.eSound = 0
  126. self.ePattern = 0
  127. self.black = "#000000"
  128. self.bg_color = "#336699"
  129. self.color_a = "#FFFFFF"
  130. self.color_b = "#929230"
  131. self.color_c = "#FFFF00"
  132. self.dark_grey = "#404040"
  133. self.grey = "#808080"
  134. self.light_grey = "#D3D3D3"
  135. self.blue = "#2A80D5"
  136. self.dark_blue = "#2A2AD5"
  137. self.pink = "#D52A80"
  138. self.red = "#D52A2A"
  139. self.olive = "#80D52A"
  140. self.green = "#2AD52A"
  141. self.pub = observer.Publisher(['beat', 'the joint'])
  142. self.song_file_name = "default.sng"
  143. self.config = ConfigObj("config.txt")
  144. self.config['title'] = "default"
  145. self.config['bpm'] = self.bpm
  146. self.config['volume'] = self.volume
  147. self.config.write()
  148. #self.save_song()
  149. class SoundSlot:
  150. def __init__(self, file, obj_id, o):
  151. self.file = file
  152. self.id = obj_id
  153. self.o = o
  154. self.mixerSound = pygame.mixer.Sound(self.file)
  155. self.pattern = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]
  156. self.notes = self.init_notes()
  157. self.pitch = 0.0
  158. self.volume = 16
  159. def play(self, vol, pitch):
  160. # snd_array = pygame.sndarray.array(self.mixerSound)
  161. # snd_resample = resample(snd_array, 2.5, "sinc_fastest").astype(snd_array.dtype)
  162. # snd_out = pygame.sndarray.make_sound(snd_resample)
  163. # snd_out.play()
  164. if vol != 0:
  165. vol = (vol / 16) * (self.volume / 16) * (self.o.volume / 16)
  166. self.mixerSound.set_volume(vol)
  167. pygame.mixer.Sound.play(self.mixerSound)
  168. def init_notes(self):
  169. outp = []
  170. _id = 0
  171. while _id < 64:
  172. outp2 = []
  173. _id2 = 0
  174. while _id2 < 64:
  175. outp2.append([0,16,0])
  176. _id2 += 1
  177. outp.append(outp2)
  178. _id += 1
  179. # for n in outp:
  180. # print('sound ', self.id, ' ', n)
  181. #print(outp)
  182. return outp
  183. def Execute(self):
  184. #print('doing the thing')
  185. #self.check_buttons()
  186. self.keys = keypad.pressed_keys
  187. #self.key_flip()
  188. self.update_keys()
  189. self.FSM.Execute()
  190. #self.disp.image(self.image, self.rotation)
  191. def update_keys(self):
  192. _id = 0
  193. for k in self.keyState:
  194. if k == 0:
  195. if _id in self.keys:
  196. self.keyState[_id] = 1
  197. elif k == 1:
  198. if _id in self.keys:
  199. self.keyState[_id] = 2
  200. else:
  201. self.keyState[_id] = 3
  202. elif k == 2:
  203. if _id in self.keys:
  204. self.keyState[_id] = 2
  205. else:
  206. self.keyState[_id] = 3
  207. else:
  208. self.keyState[_id] = 0
  209. _id += 1
  210. if buttonA.value == 0:
  211. #print('a on `', self.keyState[16])
  212. if self.keyState[16] == 0:
  213. self.keyState[16] = 1
  214. elif self.keyState[16] == 1:
  215. self.keyState[16] = 2
  216. else:
  217. self.keyState[16] = 2
  218. else:
  219. if self.keyState[16] == 3:
  220. self.keyState[16] = 4
  221. elif self.keyState[16] == 2:
  222. self.keyState[16] = 3
  223. elif self.keyState[16] == 4:
  224. self.keyState[16] = 0
  225. if buttonB.value == 0:
  226. #print('a on `', self.keyState[16])
  227. if self.keyState[17] == 0:
  228. self.keyState[17] = 1
  229. elif self.keyState[17] == 1:
  230. self.keyState[17] = 2
  231. else:
  232. self.keyState[17] = 2
  233. else:
  234. if self.keyState[17] == 3:
  235. self.keyState[17] = 4
  236. elif self.keyState[17] == 2:
  237. self.keyState[17] = 3
  238. elif self.keyState[17] == 4:
  239. self.keyState[17] = 0
  240. # if buttonB.value == 0:
  241. # #print('b on')
  242. # if self.keyState[17] == 0 or self.keyState[17] == 1:
  243. # self.keyState[17] += 1
  244. # else:
  245. # if self.keyState[17] == 2:
  246. # self.keyState[17] += 1
  247. # else:
  248. # self.keyState[17] = 0
  249. def update_bpm(self):
  250. bpm = (60000 / self.bpm) / 4
  251. pygame.time.set_timer(TIMER, int(bpm))
  252. def start_playback(self):
  253. self.playing = True
  254. self.playhead = -1
  255. self.curPattern = self.songStart
  256. bpm = (60000 / self.bpm) / 4
  257. pygame.time.set_timer(TIMER, int(bpm))
  258. def stop_playback(self):
  259. self.playing = False
  260. self.playhead = -1
  261. self.curPattern = self.songStart
  262. pygame.time.set_timer(TIMER, 0)
  263. def center_text(self, text, font, width, y, color):
  264. w,h = font.getsize(text)
  265. self.draw.text(((width-w)/2,(y-h)/2), text, font=font, fill=color)
  266. def center_block(self, message, font, bounding_box, color):
  267. x1, y1, x2, y2 = bounding_box # For easy reading
  268. w, h = self.draw.textsize(message, font=font)
  269. x = (x2 - x1 - w)/2 + x1
  270. y = (y2 - y1 - h)/2 + y1
  271. self.draw.text((x, y), message, align='center', font=font, fill=color)
  272. def save_song(self):
  273. base_dir = "/home/pi/zpc_ct/user/songs/"
  274. #self.song_file_name
  275. #file1 = open(base_dir + self.song_file_name,"w")#write mode
  276. #file1.write("Tomorrow \n")
  277. #file1.close()
  278. self.config = ConfigObj(base_dir + self.song_file_name)
  279. self.config['title'] = "default"
  280. self.config['bpm'] = self.bpm
  281. self.config['volume'] = self.volume
  282. sounds = []
  283. notes = []
  284. for x in self.soundSlots:
  285. sounds.append(x.file)
  286. notes.append(x.notes)
  287. self.config['sounds'] = sounds
  288. self.config['notes'] = notes
  289. self.config['volumes'] = ['this', 'that', 'the other']
  290. self.config.write()
  291. def load_song(self):
  292. base_dir = "/home/pi/zpc_ct/user/songs/"
  293. self.config = ConfigObj(base_dir + 'r100.sng')
  294. #self.config = ConfigObj(base_dir + self.song_file_name)
  295. #print('these sounds should get loaded ', self.config['sounds'])
  296. p = Prog()
  297. #while True:
  298. while not done:
  299. p.Execute()
  300. if pygame.event.get(pygame.USEREVENT + 1):
  301. p.playhead += 1
  302. if p.playhead == 16:
  303. p.playhead = 0
  304. #self.draw.text((0, 0), str(self.playhead), font=font, fill="#FFFFFF")
  305. #self.disp.image(self.image, self.rotation)
  306. p.curPattern = next(p.songCycle)
  307. print('pattern ', p.curPattern)
  308. p.pub.dispatch('beat', [p.curPattern, p.playhead])
  309. #clock.tick(240)
  310. clock.tick_busy_loop()
  311. #print(clock.get_fps())
  312. pygame.quit()
  313. # 1 main
  314. # 2 select pattern
  315. # 3 note edit
  316. # 6 song edit
  317. # 7 program load
  318. # 8 song load
  319. # 10 utility
  320. # 11 bpm+
  321. # 12 bpm-
  322. # 13 play
  323. # 14 stop
  324. # 15 vol+
  325. # 16 vol-