Exemplo n.º 1
0
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!'
Exemplo n.º 3
0
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 []
Exemplo n.º 4
0
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