Hi :) I am programming an independent multi-metronome and need to run the funciont beat() on a while loop for every instances of my class Metronome(), starting at the same time.
import time
import mido
from numpy import interp
from IPython.display import clear_output
inport = mido.open_input() #my MIDI is a KORG nanoKontrol 2
class Metronome():
#A dict for my MIDI controller
metronomes_controls = {
'inst_number':[n 0 for n in range(0,7)],
'vol_slide':[n 0 for n in range(0,7)],
'tempo_knob': [n 16 for n in range(0,7)],
'play_stop': [n 32 for n in range(0,7)],
'sync_selected': [n 48 for n in range(0,7)],
'tap_button': [n 64 for n in range(0,7)]}
def __init__(self, inport, inst_number = 0, tempo=60, active=True,
on_off_list = ['ON','OFF','ON','OFF'], selector = 0):
self.inport = inport
self.inst_number = inst_number
self.tempo = tempo
self.active = active
self.on_off_list = on_off_list #The controller is not so precise
self.selector = selector
self.controls = dict(zip(list(metronomes_controls.keys()),
[val[self.inst_number] for val in metronomes_controls.values()]))
def beat(self):
if self.active == True:
print('Tick', self.tempo) #this is going to be a sound
time.sleep(int(round(60/self.tempo)))
clear_output()
self.update()
else:
self.update()
def update(self):
msg = self.inport.receive(block=False)
for msg in inport.iter_pending():
if msg.control == self.controls['tempo_knob']:
self.tempo = int(interp(msg.value,[0,127],[20,99]))
if msg.control == self.controls['play_stop']:
self.selector = 1
if self.selector >3:
self.selector = 0
if 'ON' in self.on_off_list[self.selector]:
print('ON')
self.active = True
if 'OFF' in self.on_off_list[self.selector]:
print('OFF')
self.active = False
#Creating two instances of my class
m0 = Metronome(inport = inport, inst_number = 0)
m1 = Metronome(inport = inport,inst_number = 1)
m2 = Metronome(inport = inport,inst_number = 1)
m3 = Metronome(inport = inport,inst_number = 1)
#They run on a while loop. All should start at the same time.
while True:
m0.beat()
m1.beat()
m2.beat()
m3.beat()
I read about threading but it seems to create some starting delay. Then I got into barries, but I couldn't imagine how to implement it :/ or maybe should I try something with multiprocess? I got really lost! Any advice is highly appreciated
Thanks for the help!!!
CodePudding user response:
Create one thread per metronome and start them at (almost) the same time:
from threading import Thread
# Previous code...
...
def create_thread(inport, inst_number):
# The function the thread is going to execute
def inner():
m = Metronome(inport, inst_number)
m.beat()
return Thread(target=inner)
if __name__ == "__main__":
inport = mido.open_input()
# Create the threads
threads = [
create_thread(inport, i) for i in (0, 1, 1, 1)
]
# Start them at (almost) the same time
for t in threads:
t.start()
# Wait for them to finish execution
for t in threads:
t.join()