def build_note_off(channel,note,velocity,time): m = Message("note_off") m.channel = channel m.note = note m.velocity = velocity m.time = time return m
def toMIDI(filename, ch, notes, rms, onset_start_times, onset_end_times, nOnsets): print 'Transcribing to MIDI in ' + filename delta = 0 with MidiFile() as outfile: track = MidiTrack() outfile.tracks.append(track) for i in range(nOnsets): stime = int((onset_start_times[i] - delta) * 1000) message = Message('note_on', note=int(notes[i]), velocity=int(rms[i] * 127), time=stime) message.channel = ch track.append(message) etime = int((onset_end_times[i] - delta) * 1000) off_message = Message('note_off', note=int(notes[i]), velocity=int(rms[i] * 127), time=etime) off_message.channel = ch track.append(off_message) delta = onset_end_times[i] outfile.print_tracks() outfile.save('/media/sf_VMshare/' + filename) print 'Transcription successfull!'
def encoding_to_message(encoding, decodings, defaults=master_defaults): message = decodings[encoding] if message == "START_TRACK": #header defaults time_signature = MetaMessage("time_signature") time_signature.numerator = defaults["time_signature.numerator"] time_signature.denominator = defaults["time_signature.denominator"] time_signature.clocks_per_click = defaults[ "time_signature.clocks_per_click"] time_signature.notated_32nd_notes_per_beat = defaults[ "time_signature.notated_32nd_notes_per_beat"] key_signature = MetaMessage("key_signature") key_signature.key = defaults["key_signature.key"] set_tempo = MetaMessage("set_tempo") set_tempo.tempo = defaults["set_tempo.tempo"] return [time_signature, key_signature, set_tempo] if message == "END_TRACK": return [MetaMessage('end_of_track')] if message == "WAIT_A_BEAT": return [message] if message.startswith("note"): parts = message.split("-") res = Message(parts[0]) res.note = int(parts[1]) res.time = int(parts[2]) # defaults res.channel = defaults["note.channel"] res.velocity = defaults["note.velocity"] return [res] return []
def split_music(notes,melody,chords,instruments_list,dont_add_melody=False): if len(instruments_list) == 0: return [] groups = [] #e.g. [[0,1,2,3],[4],[5,6]] tracks = [] patches = [] averages = [] ranges = [] max_amounts = [] arpeggios = [] for instrument in instruments_list: #Prepare patches patches.append(instrument[0]) #Prepare output tracks tracks.append([]) #Get range averages averages.append(int(round((instrument[4][0]+instrument[4][1])/2))) #Prepare ranges ranges.append(instrument[4]) #Prepare max amounts (stt) max_amounts.append(instrument[2]) #Arpeggios arpeggios.append(instrument[3]) channels = Tools.get_channels(patches) #Create instrument change messages and add them to the output tracks for x in range(0,len(channels)): _new_msg = Message('program_change') _new_msg.channel = channels[x] _new_msg.program = patches[x]-1 _event = Event(type='event',msg=_new_msg,index=0) tracks[x].append(_event) #0.) Find Groups groups = get_groups(patches) #List of sets #0b.) Combine notes notes = copy.copy(Tools.combine_tracks(notes)[0]) #1.) Distribute all fitting tones, duplicates allowed - only depending on range and tone lists for note in notes: if note.type == 'event': continue found = False #Found any fitting instrument for inil,instrument in enumerate(instruments_list): if note.note >= instrument[4][0] and note.note <= instrument[4][1]: #in range found = True _note = copy.copy(note) _note.channel = channels[inil] tracks[inil].append(_note) if not found: #Give it to all voices, in their respective range for inil,instrument in enumerate(instruments_list): while abs(note.note - averages[inil]) > 6: dir = -(note.note - averages[inil]) / abs(note.note - averages[inil]) note.note += int(dir*12) _note = copy.copy(note) _note.channel = channels[inil] tracks[inil].append(_note) #2.) For each voice with too few tones (per time index), copy tones from the nearest neighbor that has too many tones # Choose tones that the voice does not have yet # Repeat this once per group. #2.1) Get amount of segments (each 1/16th note long) final_index = notes[-1].index segments = int(math.ceil(final_index / (FileIO.ticks_per_beat/4) )) #beat/4 = 1/16th segment_size = FileIO.ticks_per_beat/4 #2.2) Collect all notes per segment across all tracks all_segments = get_segment_data(tracks,segments,segment_size) #2.3.1) Redistribute Notes for segment in all_segments: for inse,note_list in enumerate(segment): if len(note_list) < instruments_list[inse][2]: #allowed stt #has not enough tones, now find a donor unique_tones = get_unique_tones(note_list) for inse2,note_list2 in enumerate(segment): if inse2 == inse: continue if len(note_list2) > instruments_list[inse][2]: #Try to get an unique new tone first new_list = copy.copy(note_list2) #Randomize which tones to choose shuffle(new_list) for note in new_list: val = note.note % 12 if not val in unique_tones: unique_tones.add(val) new_note = copy_into(tracks,channels,averages,ranges,inse,note) if len(note_list) >= instruments_list[inse][2]: break if len(note_list) >= instruments_list[inse][2]: break if len(note_list) >= instruments_list[inse][2]: continue #Could not find enough tones #print (str(instruments_list[inse][2] - len(note_list))+" notes missing.") #Update segment data all_segments = get_segment_data(tracks, segments, segment_size) #3.) Remix output instruments tracks = arrange(all_segments,tracks,melody,instruments_list,groups, averages,ranges,channels,dont_add_melody) #Update segment data all_segments = get_segment_data(tracks, segments, segment_size) #3.2) Remove tones in groups (First stage removing related to group tones - midi_combine will clean up the result of this.) #Save all the tones that got removed, so that midi_combine can add back arpeggio if needed tones_for_arpeggio = [] #dimensions: 1.segment, 2.instrument, 3.tones between 0-11 (midi_combine will decide on the order) save_until = [0 for z in instruments_list] #Keeping melody tone save until this index for inas,segment in enumerate(all_segments): already_added_instruments = False for group in groups: _tones_for_arpeggio = [] for inse,instr in enumerate(segment): _arpeggio_instrument = set() if not patches[inse] in group: _tones_for_arpeggio.append(_arpeggio_instrument) continue played_in_group = get_played_in_group(segment,group,patches) #list of all currently played notes in this group amount_list = [] #how often each tone appears in the group for note in instr: amount_list.append(played_in_group.count(note.note % 12)) while len(instr) > max_amounts[inse]: found_non_melody_tone = False while found_non_melody_tone == False: index_of_highest = max(range(len(amount_list)), key=amount_list.__getitem__) if instr[index_of_highest] in melody and amount_list[index_of_highest] != -1: amount_list[index_of_highest] = -1 #keep melody tones safe as long as possible #Remember that a melody tone is currently playing -> all other tones that start now should be removed if instr[index_of_highest] in melody: save_until[inse] = instr[index_of_highest].index + instr[index_of_highest].duration else: found_non_melody_tone = True #Delete the note from all lists and from the output track _arpeggio_instrument.add(instr[index_of_highest].note % 12) tracks[inse].remove(instr[index_of_highest]) del instr[index_of_highest] del amount_list[index_of_highest] #for z in range(0,len(instr)): z = 0 while z < len(instr): if instr[z].index < save_until[inse] and not (instr[z] in melody): del instr[z] del amount_list[z] z += 1 _tones_for_arpeggio.append(_arpeggio_instrument) if already_added_instruments == False: tones_for_arpeggio.append(_tones_for_arpeggio) else: tones_for_arpeggio[-1] = integrate_into(_tones_for_arpeggio,tones_for_arpeggio[-1],set()) already_added_instruments = True print(tones_for_arpeggio) _tracks = [] for intr,track in enumerate(tracks): if instruments_list[intr][6] == []: _tracks.append(combine_music(track,patches[intr],channels[intr],arpeggios[intr],max_amounts[intr],ranges[intr],tones_for_arpeggio,intr)) else: _tracks.append(Create_Guitar.combine_guitar_music(track,patches[intr],channels[intr],instruments_list[intr][6])) if chords != [] and 2 == 3: #To be used for the entire song (if only melody), or as a little alternative chord_tracks = create_chord_tracks(chords,tracks,averages,max_amounts,ranges,groups,instruments_list,len(all_segments),segment_size) print (chord_tracks) #delete for inil,instrument in enumerate(instruments_list): tracks[inil] = tracks[inil][:1] current_index = 0 for inct,chord in enumerate(chord_tracks): measure_width = get_measure_width_in_segments(current_index, segment_size) chord_distance = measure_width / 2 #in segments if chord == []: current_index += int(chord_distance) continue for inch, instrument in enumerate(chord): for inin,tone in enumerate(instrument): #Check if the tone appears also in the next chords (then play this one longer, delete the next ones) cnt = inct+1 duration = chord_distance * segment_size found = True _index = current_index while cnt < len(chord_tracks) and found: found = False if len(chord_tracks[cnt]) == 0: break #no-chord section if tone in chord_tracks[cnt][inch]: found = True chord_tracks[cnt][inch].remove(tone) cnt+=1 _measure_width = get_measure_width_in_segments(_index, segment_size) _chord_distance = measure_width / 2 #in segments _index += int(_chord_distance) duration += _chord_distance * segment_size cnt -= 1 #cnt = inct, wenn nix tracks[inch].append(Event(type='note',msg=Message('note_on'),index=current_index*segment_size,duration=duration, note=tone, octave = int(tone / 12),channel = channels[inch], velocity = 100)) current_index += int(chord_distance) return tracks