def CreateDroneMidiFile(data_array, name): print("creating Drone " + name + " midi file") midiObj = MIDIFile(3) # create one track midiObj.addTempo(0, 0, 150) # track, channel, pitch, time , duration , volume midiObj.addNote(0, 0, 48, 0, len(data_array) / 4, 100) midiObj.addNote(1, 0, 55, 0, len(data_array) / 4, 100) midiObj.addNote(2, 0, 60, 0, len(data_array) / 4, 100) for i, pitch in enumerate(data_array): forward = i / 4 ######## HIGH TONIC NOTE PITCHBEND #################### midiObj.addPitchWheelEvent(0, 0, forward, scale_and_randomize(pitch, 7000)) ######## DOMINANT NOTE PITCHBEND ###################### midiObj.addPitchWheelEvent(1, 0, forward, scale_and_randomize(pitch, 6000)) ####### LOW TONIC NOTE PITCHBEND ##################### # midiObj.addPitchWheelEvent(2, 0, note_division, scale_and_randomize(pitch)) with open("midiFiles/" + name + ".mid", "wb") as midiFile: midiObj.writeFile(midiFile)
def createArpegiatedMidiFile(data_array, name): midiObj = MIDIFile(3) # create one track midiObj.addTempo(0, 0, 150) for i, pitch in enumerate(data_array): forward = i * 2 ######## HIGH TONIC NOTE #################### # track, channel, pitch, time , duration , volume midiObj.addNote(0, 0, 48, (forward + i) / 4, SIXTEEN_NOTE, 100) midiObj.addPitchWheelEvent(0, 0, (forward + i) / 4, scale_and_randomize(pitch, 7000)) ######## DOMINANT NOTE ###################### midiObj.addNote(1, 0, 55, (forward + i + 1) / 4, SIXTEEN_NOTE, 100) midiObj.addPitchWheelEvent(1, 0, (forward + i + 1) / 4, scale_and_randomize(pitch, 6000)) ####### LOW TONIC NOTE ##################### midiObj.addNote(2, 0, 60, (forward + i + 2) / 4, SIXTEEN_NOTE, 100) # midiObj.addPitchWheelEvent(2, 0, note_division, scale_and_randomize(pitch)) with open("midiFiles/" + name + ".mid", "wb") as midiFile: midiObj.writeFile(midiFile)
def create_midi_with_melody(clean_data, alert_data, name, arpegiation): midiObj = MIDIFile(4) # create one track midiObj.addTempo(0, 0, 150) #################################################################### ################## CREATE ARPEGGIATION ########################### #################################################################### if (arpegiation == True): clean_rhythm_length = round(len(clean_data) / 16) note_cutoff = 0.02 for i in range(clean_rhythm_length): forward = i * 4 # track, channel, pitch, time , duration , volume midiObj.addNote(0, 0, note["c1"], forward, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(2, 0, note["c3"], forward + SIXTEEN_NOTE * 2, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 3, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(0, 0, note["c1"], forward + SIXTEEN_NOTE * 4, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 5, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(2, 0, note["c3"], forward + SIXTEEN_NOTE * 6, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 7, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(0, 0, note["c1"], forward + SIXTEEN_NOTE * 8, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 9, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(2, 0, note["c3"], forward + SIXTEEN_NOTE * 10, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 11, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(0, 0, note["c1"], forward + SIXTEEN_NOTE * 12, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 13, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(2, 0, note["c3"], forward + SIXTEEN_NOTE * 14, SIXTEEN_NOTE - note_cutoff, 100) midiObj.addNote(1, 0, note["g2"], forward + SIXTEEN_NOTE * 15, SIXTEEN_NOTE - note_cutoff, 100) #################################################################### ################## CREATE DRONE ################################### #################################################################### else: duration = len(clean_data) / 4 # track, channel, pitch, time , duration , volume midiObj.addNote(0, 0, note["c2"], 0, duration, 100) midiObj.addNote(1, 0, note["g2"], 0, duration, 100) midiObj.addNote(2, 0, note["c1"], 0, duration, 100) #################################################################### ################## CREATE PTICH BEND ############################## #################################################################### pitch_bend_ceiling = [0, 0, 0] max_shift = 8192 previous_data_point = 0 for i, data_point in enumerate(clean_data): note_position = i / 4 if (previous_data_point == 0.0 and data_point > 0.0): pitch_bend_ceiling[0] = int( round(max_shift * random.uniform(-1.0, 1.0))) pitch_bend_ceiling[1] = int( round(max_shift * random.uniform(-1.0, 1.0))) pitch_bend_ceiling[2] = int( round(max_shift * random.uniform(-1.0, 1.0))) elif (previous_data_point > 0 and data_point == 0.0): pitch_bend_ceiling = [0, 0, 0] ######## HIGH TONIC NOTE PITCHBEND #################### # track, channel, time , pitchWheelValue midiObj.addPitchWheelEvent(0, 0, note_position, pitch_bend_ceiling[0]) midiObj.addPitchWheelEvent(1, 0, note_position, pitch_bend_ceiling[1]) midiObj.addPitchWheelEvent(2, 0, note_position, pitch_bend_ceiling[2]) previous_data_point = data_point #################################################################### ################## CREATE MELODY ################################## #################################################################### melody_pitches1 = [ note["c5"], note["c5"], note["c5"], note["c5"], note["c5"], note["c5"], note["c5"], note["c5"], note["c6"], note["c6"], note["c6"], note["c6"], note["c6"], note["c6"], note["c6"], note["c6"], ] melody_rhythm1 = [ SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, ] melody_pitches2 = [ note["c5"], note["cs5"], note["d5"], note["ds5"], note["e5"], note["f5"], note["fs5"], note["c6"], note["cs6"], note["d6"], note["ds6"], note["e6"], note["f6"], note["fs6"], note["c5"], note["cs5"], note["d5"], note["ds5"], note["e5"], note["f5"], note["fs5"], note["c6"], note["cs6"], note["d6"], note["ds6"], note["e6"], note["f6"], note["fs6"], ] melody_rhythm2 = [ SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, SIXTEEN_NOTE, ] melody_pitches3 = [ note["c5"], note["fs5"], note["cs6"], note["gs6"], note["ds7"], note["as7"], note["ds7"], note["gs6"], note["cs6"], note["gs5"], note["c5"], note["f4"] ] melody_rhythm3 = [ EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, EIGHTH_NOTE, ] midiObj = createMelody(melody_pitches2, melody_rhythm2, alert_data, midiObj, 3) # midiObj = createMelody(melody_pitches2, melody_rhythm2, alert_data, midiObj, 3) # midiObj = createMelody(melody_pitches3, melody_rhythm3, alert_data, midiObj, 3) with open("midiFiles/" + name + ".mid", "wb") as midiFile: midiObj.writeFile(midiFile)
pb = 0 pb = (pb << 7) + (thisEvent.valueA & 0x7F) pb = (pb << 7) + (thisEvent.valueB & 0x7F) pitchWheelValue = -8192 + pb if (bOverridePitchBend): pitchWheelValue *= pitchBendMultiplier # Correct any overshoot if (pitchWheelValue < -8192): pitchWheelValue = -8192 if (pitchWheelValue > 8191): pitchWheelValue = 8191 debugPrint( "Adjusted pitchWheelValue is: {}({})".format( pitchWheelValue, hex(pitchWheelValue))) midiFileData.addPitchWheelEvent(0, midiChl, thisEvent.time - baseTime, pitchWheelValue) midiSection.bHasMIDI = True elif (midiCmd == 0xF1): debugPrint("Found end of buffer") break elif ((midiCmd >= 0x30 and midiCmd <= 0x3F) or midiCmd == 0x60 or midiCmd == 0x11 or midiCmd == 0x12): # These tend to be at the start of blocks we are not interested in debugPrint("Unknown bytes: {}".format(hex(midiCmd))) break else: # Not seen this command byte before so dump some context for debugging # purposes then exit s.pos -= (64 * 8) dumphex(68, s)
class Pat2Midi: """ class to convert Pattern to Midi """ def __init__(self, num_tracks: int = 1, remove_duplicates: bool = True, deinterleave: bool = True, file_format: int = 1): """ :param num_tracks: number of tracks (default: 1) :param remove_duplicates: remove notes if they start at the same time on the same channel if they have the same pitch (default: True) :param deinterleave: clean up two note-ons with no note-off in between (default: True) :param file_format: 1 or 2 (default: 1) """ self.midiFile = MIDIFile(numTracks=num_tracks, removeDuplicates=remove_duplicates, deinterleave=deinterleave, adjust_origin=False, file_format=file_format) self.last_set_tempo = [Defaults.tempo for _ in range(16) ] # set every track to default tempo self.set_tempo(Defaults.tempo, 0) self.last_set_cc = [[None for _ in range(NO_OF_CONTROLLERS)] for _ in range(NO_OF_TRACKS)] self.note2midi = Note2Midi() def set_tempo(self, tempo=100, time=0): """ :param tempo: bpm (default: 100) :param time: time at which the tempo change should be inserted in the midi stream (default: 0) """ self.midiFile.addTempo(track=0, time=time, tempo=tempo) self.last_set_tempo[0] = tempo self.last_set_cc = [[None for _ in range(NO_OF_CONTROLLERS)] for _ in range(NO_OF_TRACKS)] def add_phrase(self, phrase: Phrase, track=0, channel=0, start_time=0): """ :param phrase: a Phrase containing patterns and animations :param track: default: 0 :param channel: default: 0 :param start_time: time at which the phrase should be inserted default: 0 :return: total duration of the inserted phrase """ for event in phrase: # set tempo events only if they changed since last time # handle note events if PP.NOTE in event: if event[PP.TEMPO] != self.last_set_tempo[track]: self.midiFile.addTempo( track, start_time + phrase.generated_duration(), event[PP.TEMPO]) self.last_set_tempo[track] = event[PP.TEMPO] # set notes always if isinstance(event[PP.NOTE], Pchord): for n in event[PP.NOTE].notes: try: intnote = int(n) except ValueError: intnote = self.note2midi.lookup(n) if intnote == REST: continue self.midiFile.addNote( track=track, channel=channel, pitch=intnote, time=start_time + phrase.generated_duration() + event[PP.LAG], duration=event[PP.DUR] * event[PP.PLAYEDDUR], volume=int(event[PP.VOL]), annotation=None) else: try: intnote = int(event[PP.NOTE]) except ValueError: intnote = self.note2midi.lookup(event[PP.NOTE]) if intnote == REST: continue self.midiFile.addNote( track=track, channel=channel, pitch=intnote, time=start_time + phrase.generated_duration() + event[PP.LAG], duration=event[PP.DUR] * event[PP.PLAYEDDUR], volume=int(event[PP.VOL]), annotation=None) self.handle_control_changes(channel, event, phrase, start_time, track) # handle controller events (only if they changed since last time) else: self.handle_control_changes(channel, event, phrase, start_time, track) return phrase.generated_duration() def handle_control_changes(self, channel, event, phrase, start_time, track): """ iterate over all control changes in the phrase and add them to the midi file :param channel: midi channel :param event: python dict containing phrase properties :param phrase: :param start_time: time offset :param track: midi track id :return: """ for cc in range(NO_OF_OFFICIAL_CONTROLLERS): if PP.ctrl_dur_key(cc) in event: time = start_time + phrase.generated_ctrl_duration(cc) value = event[PP.ctrl_val_key(cc)] if value is not None: self.midiFile.addControllerEvent(track=track, channel=channel, time=time, controller_number=cc, parameter=value) for cc in [MidiControlChanges.PitchWheel]: if PP.ctrl_dur_key(cc) in event: time = start_time + phrase.generated_ctrl_duration(cc) pwvalue = event[PP.ctrl_val_key(cc)] if pwvalue is not None: self.midiFile.addPitchWheelEvent(track=track, channel=channel, time=time, pitchWheelValue=pwvalue) def add_phrases(self, list_of_phrase, track=0, channel=0, start_time=0): """ :param list_of_phrase: a list of Phrase :param track: default: 0 :param channel: midi channel, deafult: 0 :param start_time: default: 0 :return: total duration of piece from begin until end of list of phrases """ time_delta = 0 for phrase in list_of_phrase: duration = self.add_phrase(phrase, track, channel, start_time + time_delta) time_delta += duration return start_time + time_delta def write(self, filename): """ write to midi file :param filename: filename """ try: with open(filename, "wb") as f: self.midiFile.writeFile(fileHandle=f) except Exception as e: print("we hit a SNAFU while writing to {0}: {1}".format( filename, e))