diff --git a/production/accompanist.py b/production/accompanist.py index 4f701fc..da3a503 100644 --- a/production/accompanist.py +++ b/production/accompanist.py @@ -6,11 +6,13 @@ from aubio import notes, onset, tempo from time import sleep from mido import Message, MidiFile, MidiTrack + from rtmidi import MidiOut from multiprocessing.dummy import Queue, Process, Value from structures import Note, Chord from listener import Listener from player import Player +from chord_predictor import * default_tempo = 124 max_time = sys.float_info.max @@ -30,11 +32,13 @@ class Accompanist: def __init__(self): self.queue_in = Queue() self.queue_out = Queue() + self.predictor_queue = Queue() self.runing = Value('i', False) self.tempo = Value('i', default_tempo) self.deadline = Value('f', max_time) self.player = Player(self.queue_out, self.runing, self.tempo, self.deadline) + self.predictor = ChordPredictor(self.predictor_queue, self.queue) self.listener = Listener(self.queue_in, self.runing, self.tempo, self.deadline) def run(self): @@ -43,11 +47,13 @@ def run(self): self.process.start() self.listener.run() self.player.run() + self.predictor.run() def stop(self): self.runing.value = False self.player.stop() - self.listener.stop() + self.listener.stop() + self.predictor.stop() self.queue_in = Queue() self.queue_out = Queue() self.process.join() @@ -60,8 +66,10 @@ def set_deadline(self, deadline=max_time): player = None listener = None + predictor = None queue_in = None queue_out = None + predictor_queue = None runing = None tempo = None deadline = None @@ -69,8 +77,9 @@ def set_deadline(self, deadline=max_time): if __name__ == '__main__': a = Accompanist() + start_time = time.time() a.run() - sleep(50) + sleep(10) a.stop() '''q = a.player start_time = time.time() @@ -94,4 +103,3 @@ def set_deadline(self, deadline=max_time): ''' - \ No newline at end of file diff --git a/production/chord_predictor.py b/production/chord_predictor.py index 74be610..4467f9a 100644 --- a/production/chord_predictor.py +++ b/production/chord_predictor.py @@ -33,16 +33,51 @@ def interval(start, interval): else: #major большая терция и чистая квинта return [first_note, interval(first_note, 4), interval(first_note, 7)] +def run_queue(predictor): + predictor.load_model("rf_nottingham.pkl") + + while predictor.running: + if not predictor.queue_in.empty(): + chord = predictor.try_predict() + if chord is not None: + queue_out.put(chord) # длительность аккорда выставлять тут + + class ChordPredictor: model = None - def __init__(self): - pass + def __init__(self, queue_in, queue_out): + self.queue_in = queue_in + self.queue_out = queue_out + self.running = False + self.chords_len = 0 + + def run(self): + self.running = True + self.process = Process(target=run_queue, args=(self)) + self.process.start() + + def stop(self): + self.running = False + self.process.join() def load_model(self, filename): with open(filename, 'rb') as fid: self.model = pickle.load(fid) + def try_predict(self): + chord = self.queue_in.get() + self.chords_list.append(chord) + self.chord_len += chord.duration + if self.chord_len > 128 * 2 * 7/8: + prediction = self.predict(self.chords_list) + self.chords_list.clear() + self.chord_len = 0 + return prediction + else: + return None + + def predict(self, chords_list): # передаётся два такта, кроме последней доли (то есть от двух тактов доступно 7/8 или 14/16 информации) numbers = np.array([]) # midi numbers! for chord in chords_list: @@ -67,4 +102,4 @@ def predict(self, chords_list): # передаётся два такта, кро list_notes = [] for note in notes: list_notes.append(Note(note + 12 * 4)) - return Chord(list_notes, 128, 1) + return Chord(list_notes)