コード例 #1
0
ファイル: player.py プロジェクト: sharfiky/accompaniator
class Player:
    def __init__(self,
                 queue=Queue(),
                 running=Value('i', False),
                 tempo=Value('i', default_tempo),
                 deadline=Value('f', 0)):
        self.midiout = MidiOut()
        self.midi_for_file = MidiFile()
        self.last_chord = empty_chord

        self.queue_out = queue
        self.running = running
        self.tempo = tempo
        self.deadline = deadline
        self.start_peak = Value('f', 0)
        self.start_chord = 0

    def play_peak(self,
                  number=default_peak_number,
                  velocity=default_peak_velocity):
        note_on = Message('note_on',
                          note=number,
                          velocity=velocity,
                          channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(note_on)
        sleep(default_peak_time)
        note_off = Message('note_off',
                           note=number,
                           velocity=min_velocity,
                           channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(note_off)

    def play_chord_same_time(self):
        chord = self.queue_out.get()
        # print("player get", chord, "vel", chord.velocity, "queue", self.queue_out.qsize(), "time", time.monotonic())
        if chord.velocity > 127:
            chord.velocity = 127
        if chord.duration == 0:
            return
        for note in chord.notes:
            if note.number > 127:
                print("an incorrect note in player")
                return

        if self.last_chord != empty_chord:
            for note in self.last_chord.notes:
                note_off = Message('note_off',
                                   note=note.number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)

        for note in chord.notes:
            note_on = Message('note_on',
                              note=note.number,
                              velocity=chord.velocity,
                              channel=default_channel).bytes()
            self.midiout.send_message(note_on)

        self.last_chord = chord

        sleep(len_in_s(chord.duration, self.tempo.value))

        if self.last_chord == chord:
            for note in chord.notes:
                note_off = Message('note_off',
                                   note=note.number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)

    def play_chord_arpeggio(self, track=np.array([])):
        chord = self.queue_out.get()
        print("player get", chord, "vel", chord.velocity, "queue",
              self.queue_out.qsize(), "time", time.monotonic())
        if chord.velocity > 127:
            chord.velocity = 127
        if chord.duration == 0:
            return
        for note in chord.notes:
            if note.number > 127:
                print("an incorrect note in player")
                return
        chord.notes = sorted(chord.notes)
        if len(chord.notes) == 3:
            chord.notes.append(Note(chord.notes[0].number + 12))
        if track == np.array([]):
            notes_numbers = np.arange(len(chord.notes))
            notes_durations = np.array(
                [int(128 / len(chord.notes)) for i in range(len(chord.notes))])
            track = np.column_stack((notes_numbers, notes_durations))

        notes_sum_durations = np.cumsum(track.transpose(), axis=1)[1]
        if self.last_note_number is not None:
            note_off = Message('note_off',
                               note=self.last_note_number,
                               velocity=min_velocity,
                               channel=default_channel).bytes()
            self.midiout.send_message(note_off)
        self.start_chord = time.monotonic()
        pair = 0
        note_number = track[pair][0]
        note_on = Message('note_on',
                          note=chord.notes[note_number].number,
                          velocity=chord.velocity,
                          channel=default_channel).bytes()
        self.midiout.send_message(note_on)
        while (pair < len(track) - 1):
            # TODO
            if time.monotonic() > self.start_chord + max(
                (self.deadline.value - self.start_chord) *
                    notes_sum_durations[pair] / notes_sum_durations[-1],
                    len_in_s(notes_sum_durations[pair], self.tempo.value)):
                note_off = Message('note_off',
                                   note=chord.notes[note_number].number,
                                   velocity=min_velocity,
                                   channel=default_channel).bytes()
                self.midiout.send_message(note_off)
                pair += 1
                note_number = track[pair][0]
                note_on = Message('note_on',
                                  note=chord.notes[note_number].number,
                                  velocity=chord.velocity,
                                  channel=default_channel).bytes()
                self.midiout.send_message(note_on)
                self.last_note_number = chord.notes[note_number].number
            time.sleep(0.01)

    def put(self, chord):
        if type(chord) == Chord:
            self.queue_out.put(chord)
            return True
        return False

    def set_up_ports(self):
        """ This is necessary to HEAR the music """
        available_ports = self.midiout.get_ports()
        if available_ports:
            self.midiout.open_port(default_port)
        else:
            self.midiout.open_virtual_port("Tmp virtual output")

    def set_up_instrument(self, program=default_instrument):
        program_change = Message('program_change',
                                 program=program,
                                 channel=default_channel).bytes()
        self.midiout.send_message(program_change)

    def set_up_ultrasound_instrument(self,
                                     program=default_ultrasound_instrument):
        program_change = Message('program_change',
                                 program=program,
                                 channel=default_ultrasound_channel).bytes()
        self.midiout.send_message(program_change)

    def set_up_midi_for_file(self):
        self.midi_for_file.tracks.append(MidiTrack())

    def set_tempo(self, tempo=default_tempo):
        self.tempo.value = tempo

    def set_deadline(self, deadline=0):
        self.deadline.value = deadline

    def set_start_peak(self, start=max_time):
        self.start_peak.value = start

    def get_sleeping_time(self):
        return self.deadline.value - time.monotonic()

    def get_track(self):
        return self.midi_for_file.tracks[0]

    def save_file(self, filename='my track.mid'):
        self.midi_for_file.save(filename)
        return filename

    def run(self):
        self.running.value = True
        self.set_up_ports()
        self.set_up_midi_for_file()
        self.set_up_instrument()
        self.set_up_ultrasound_instrument()

        self.queue_process = Process(target=run_queue_out, args=(self, ))
        self.queue_process.start()

        self.queue_process = Process(target=run_peak, args=(self, ))
        self.queue_process.start()

    def stop(self):
        """ All chords that already sound will continue to sound """
        self.running.value = False
        self.queue_process.join()
        self.queue_process.join()
        self.queue_out = Queue()

    queue_out = None
    running = None
    tempo = None
    deadline = None
    start_peak = None
    start_chord = None
    queue_process = None
    peak_process = None
    midiout = None
    midi_for_file = None
    last_chord = None
    last_note_number = None
コード例 #2
0
from music21 import midi, instrument, stream, note, chord
from rtmidi import MidiOut
from rtmidi.midiutil import open_midiinput
from rtmidi.midiconstants import NOTE_ON, NOTE_OFF

seq_len = 32
bpm = 120 / 60
instru = instrument.Piano()

# MIDI Setup
midiout = MidiOut()
available_ports = midiout.get_ports()
if available_ports:
    midiout.open_port(0)
else:
    midiout.open_virtual_port("My virtual output")

log = logging.getLogger('midiin_callback')
logging.basicConfig(level=logging.DEBUG)

# Load data from training
print("\nLoading, please wait...\n", flush=True)

vocab_file = "Piano_50.npy"
vocab = np.load(os.path.join("vocab_save", vocab_file), allow_pickle=True)
notes_vocab = vocab[0]
durations_vocab = vocab[1]
offsets_vocab = vocab[2]
velocities_vocab = vocab[3]

print("\nVocab loaded\n", flush=True)