├── Metallica_drums_midi ├── 2x4.mid ├── Damage.mid ├── Disposable Heroes.mid ├── Dyers Eve.mid ├── Four horsemen.mid ├── Frayed Ends of Sanity.mid ├── God that failed.mid ├── Haverster of sorrow.mid ├── Hero of the day.mid ├── Hit the lights.mid ├── Holier than thou.mid ├── House jack built.mid ├── King Nothing.mid ├── Lepper Messiah.mid ├── Master of puppets.mid ├── Metal Millitia.mid ├── Motor breath.mid ├── My friends of misery.mid ├── No remorse.mid ├── Nothing else matters.mid ├── Of wolf and man.mid ├── One.mid ├── Orion.mid ├── Outlaw torn.mid ├── Phantom lord.mid ├── Poor twisted me.mid ├── Ride the lightening.mid ├── Ronnie.mid ├── Sanitarium.mid ├── Seek n destory.mid ├── Struggle within.mid ├── The thing that should not be.mid ├── Thorn within.mid ├── Through the never.mid ├── Unforgiven.mid ├── Until sleeps.mid ├── Wherever I May Roam.mid ├── Whiplash.mid ├── aint my bitch.mid ├── and justice for all.mid ├── battery.mid ├── blackened.mid ├── bleeding me.mid ├── call of ktulu.mid ├── creeping death.mid ├── cure.mid ├── don't tread on me.mid ├── enter sandman.mid ├── escape.mid ├── eyes of beholder.mid ├── fade to black.mid ├── fight fire with fire.mid ├── for whom the bell tolls.mid ├── sad but true.mid ├── shortest straw.mid ├── trapped under ice.mid └── wasting my hates.mid ├── drum_note_processor.py ├── main_lstM_etallica.py ├── main_post_process.py ├── metallica_drums_text.txt └── readme.md /Metallica_drums_midi/2x4.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/2x4.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Damage.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Damage.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Disposable Heroes.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Disposable Heroes.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Dyers Eve.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Dyers Eve.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Four horsemen.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Four horsemen.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Frayed Ends of Sanity.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Frayed Ends of Sanity.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/God that failed.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/God that failed.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Haverster of sorrow.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Haverster of sorrow.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Hero of the day.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Hero of the day.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Hit the lights.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Hit the lights.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Holier than thou.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Holier than thou.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/House jack built.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/House jack built.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/King Nothing.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/King Nothing.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Lepper Messiah.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Lepper Messiah.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Master of puppets.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Master of puppets.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Metal Millitia.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Metal Millitia.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Motor breath.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Motor breath.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/My friends of misery.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/My friends of misery.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/No remorse.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/No remorse.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Nothing else matters.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Nothing else matters.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Of wolf and man.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Of wolf and man.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/One.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/One.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Orion.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Orion.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Outlaw torn.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Outlaw torn.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Phantom lord.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Phantom lord.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Poor twisted me.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Poor twisted me.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Ride the lightening.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Ride the lightening.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Ronnie.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Ronnie.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Sanitarium.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Sanitarium.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Seek n destory.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Seek n destory.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Struggle within.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Struggle within.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/The thing that should not be.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/The thing that should not be.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Thorn within.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Thorn within.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Through the never.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Through the never.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Unforgiven.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Unforgiven.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Until sleeps.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Until sleeps.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Wherever I May Roam.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Wherever I May Roam.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/Whiplash.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/Whiplash.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/aint my bitch.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/aint my bitch.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/and justice for all.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/and justice for all.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/battery.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/battery.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/blackened.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/blackened.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/bleeding me.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/bleeding me.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/call of ktulu.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/call of ktulu.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/creeping death.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/creeping death.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/cure.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/cure.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/don't tread on me.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/don't tread on me.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/enter sandman.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/enter sandman.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/escape.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/escape.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/eyes of beholder.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/eyes of beholder.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/fade to black.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/fade to black.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/fight fire with fire.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/fight fire with fire.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/for whom the bell tolls.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/for whom the bell tolls.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/sad but true.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/sad but true.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/shortest straw.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/shortest straw.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/trapped under ice.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/trapped under ice.mid -------------------------------------------------------------------------------- /Metallica_drums_midi/wasting my hates.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keunwoochoi/LSTMetallica/416af74371a2d4715ca1a2582a09077fe5e5f5bc/Metallica_drums_midi/wasting my hates.mid -------------------------------------------------------------------------------- /drum_note_processor.py: -------------------------------------------------------------------------------- 1 | import midi 2 | import pdb 3 | 4 | PPQ = 480 # Pulse per quater note 5 | event_per_bar = 16 # to quantise. 6 | min_ppq = PPQ / (event_per_bar/4) 7 | # ignore: 39 hand clap, 54 tambourine, 56 Cowbell, 58 Vibraslap, 60-81 8 | drum_conversion = {35:36, # acoustic bass drum -> bass drum (36) 9 | 37:38, 40:38, # 37:side stick, 38: acou snare, 40: electric snare 10 | 43:41, # 41 low floor tom, 43 ghigh floor tom 11 | 47:45, # 45 low tom, 47 low-mid tom 12 | 50:48, # 50 high tom, 48 hi mid tom 13 | 44:42, # 42 closed HH, 44 pedal HH 14 | 57:49, # 57 Crash 2, 49 Crash 1 15 | 59:51, 53:51, 55:51, # 59 Ride 2, 51 Ride 1, 53 Ride bell, 55 Splash 16 | 52:49 # 52: China cymbal 17 | } 18 | # k, sn,cHH,oHH,LFtom,ltm,htm,Rde,Crash 19 | allowed_pitch = [36, 38, 42, 46, 41, 45, 48, 51, 49] # 46: open HH 20 | cymbals_pitch = [49, 51] # crash, ride 21 | cymbals_pitch = [] # crash, ride 22 | # pitch_to_midipitch = {36:midi.C_2, # kick # for general MIDI Drum map 23 | # 38:midi.D_2, # Snare 24 | # 39:midi.Eb_2, # hand clap (it's alive by mistake..) 25 | # 41:midi.F_2, # Low floor tom 26 | # 42:midi.Gb_2, # Close HH 27 | # 45:midi.A_2, # Low tom 28 | # 46:midi.Bb_2, # Open HH 29 | # 48:midi.C_3, # Hi Mid Tom 30 | # 49:midi.Db_3, # Crash 31 | # 51:midi.Eb_3 # Ride 32 | # } 33 | 34 | pitch_to_midipitch = {36:midi.C_3, # for logic 'SoCal' drum mapping 35 | 38:midi.D_3, 36 | 39:midi.Eb_3, 37 | 41:midi.F_3, 38 | 42:midi.Gb_3, 39 | 45:midi.A_3, 40 | 46:midi.Bb_3, 41 | 48:midi.C_4, 42 | 49:midi.Db_4, 43 | 51:midi.Eb_4 44 | } 45 | 46 | class Note: 47 | def __init__(self, pitch, c_tick): 48 | self.pitch = pitch 49 | self.c_tick = c_tick # cumulated_tick of a midi note 50 | 51 | def add_index(self, idx): 52 | '''index --> 16-th note-based index starts from 0''' 53 | self.idx = idx 54 | 55 | class Note_List(): 56 | def __init__(self): 57 | '''''' 58 | self.notes = [] 59 | self.quantised = False 60 | self.max_idx = None 61 | 62 | def add_note(self, note): 63 | '''note: instance of Note class''' 64 | self.notes.append(note) 65 | 66 | def quantise(self, minimum_ppq): 67 | ''' 68 | e.g. if minimum_ppq=120, quantise by 16-th note. 69 | 70 | ''' 71 | if not self.quantised: 72 | for note in self.notes: 73 | note.c_tick = ((note.c_tick+minimum_ppq/2)/minimum_ppq)* minimum_ppq # quantise 74 | note.add_index(note.c_tick/minimum_ppq) 75 | 76 | self.max_idx = note.idx 77 | if (self.max_idx + 1) % event_per_bar != 0: 78 | self.max_idx += event_per_bar - ((self.max_idx + 1) % event_per_bar) # make sure it has a FULL bar at the end. 79 | self.quantised = True 80 | 81 | return 82 | 83 | def simplify_drums(self): 84 | ''' use only allowed pitch - and converted not allowed pitch to the similar in a sense of drums! 85 | ''' 86 | 87 | for note in self.notes: 88 | if note.pitch in drum_conversion: # ignore those not included in the key 89 | note.pitch = drum_conversion[note.pitch] 90 | 91 | self.notes = [note for note in self.notes if note.pitch in allowed_pitch] 92 | 93 | return 94 | 95 | def return_as_text(self): 96 | '''''' 97 | length = self.max_idx + 1 # of events in the track. 98 | event_track = [] 99 | for note_idx in xrange(length): 100 | event_track.append(['0']*len(allowed_pitch)) 101 | 102 | num_bars = length/event_per_bar# + ceil(len(event_texts_temp) % _event_per_bar) 103 | 104 | for note in self.notes: 105 | pitch_here = note.pitch 106 | note_add_pitch_index = allowed_pitch.index(pitch_here) # 0-8 107 | event_track[note.idx][note_add_pitch_index] = '1' 108 | # print note.idx, note.c_tick, note_add_pitch_index, ''.join(event_track[note.idx]) 109 | # pdb.set_trace() 110 | 111 | event_text_temp = ['0b'+''.join(e) for e in event_track] # encoding to binary 112 | 113 | event_text = [] 114 | # event_text.append('SONG_BEGIN') 115 | # event_text.append('BAR') 116 | for bar_idx in xrange(num_bars): 117 | event_from = bar_idx * event_per_bar 118 | event_to = event_from + event_per_bar 119 | event_text = event_text + event_text_temp[event_from:event_to] 120 | event_text.append('BAR') 121 | 122 | # event_text.append('SONG_END') 123 | 124 | return ' '.join(event_text) 125 | -------------------------------------------------------------------------------- /main_lstM_etallica.py: -------------------------------------------------------------------------------- 1 | ''' 2 | LSTMetallica by Keunwoo Choi 3 | - paper: https://arxiv.org/abs/1604.05358# 4 | - repo: https://github.com/keunwoochoi/LSTMetallica 5 | ''' 6 | from keras.models import Sequential 7 | from keras.layers.core import Dense, Activation, Dropout 8 | from keras.layers.recurrent import LSTM 9 | from keras.utils.data_utils import get_file 10 | import keras 11 | import numpy as np 12 | import random 13 | import sys 14 | import os 15 | import pdb 16 | 17 | def get_model(maxlen, num_chars, num_layers): 18 | print('Build model...') 19 | model = Sequential() 20 | for layer_idx in range(num_layers): 21 | if layer_idx == 0: 22 | model.add(LSTM(num_units, return_sequences=True, input_shape=(maxlen, num_chars))) 23 | else: 24 | model.add(LSTM(num_units, return_sequences=False)) 25 | model.add(Dropout(0.2)) 26 | 27 | model.add(Dense(num_chars)) 28 | model.add(Activation('softmax')) 29 | 30 | model.compile(loss='categorical_crossentropy', optimizer='adam') 31 | return model 32 | 33 | def sample(a, temperature=1.0): 34 | # helper function to sample an index from a probability array 35 | a = np.log(a) / temperature 36 | a = np.exp(a) / np.sum(np.exp(a)) 37 | return np.argmax(np.random.multinomial(1, a, 1)) 38 | 39 | def run(is_character=False, maxlen=None, num_units=None, model_prefix=''): 40 | 41 | character_mode = is_character 42 | 43 | if character_mode: 44 | if maxlen == None: 45 | maxlen = 1024 46 | if num_units == None: 47 | num_units = 32 48 | step = 2*17 # step to create training data for truncated-BPTT 49 | else: # word mode 50 | if maxlen == None: 51 | maxlen = 128 # 52 | if num_units == None: 53 | num_units = 512 54 | step = 8 55 | 56 | if character_mode: 57 | num_char_pred = maxlen*3/2 58 | else: 59 | num_char_pred = 17*30 60 | 61 | num_layers = 2 62 | # 63 | if character_mode: 64 | prefix = 'char' 65 | else: 66 | prefix = 'word' 67 | 68 | path = 'metallica_drums_text.txt' # Corpus file 69 | text = open(path).read() 70 | print('corpus length:', len(text)) 71 | 72 | if character_mode: 73 | chars = set(text) 74 | else: 75 | chord_seq = text.split(' ') 76 | chars = set(chord_seq) 77 | text = chord_seq 78 | 79 | char_indices = dict((c, i) for i, c in enumerate(chars)) 80 | indices_char = dict((i, c) for i, c in enumerate(chars)) 81 | num_chars = len(char_indices) 82 | print('total chars:', num_chars) 83 | 84 | # cut the text in semi-redundant sequences of maxlen characters 85 | 86 | sentences = [] 87 | next_chars = [] 88 | for i in range(0, len(text) - maxlen, step): 89 | sentences.append(text[i: i + maxlen]) 90 | next_chars.append(text[i + maxlen]) 91 | print('nb sequences:', len(sentences)) 92 | print('Vectorization...') 93 | X = np.zeros((len(sentences), maxlen, num_chars), dtype=np.bool) 94 | y = np.zeros((len(sentences), num_chars), dtype=np.bool) 95 | for i, sentence in enumerate(sentences): 96 | for t, char in enumerate(sentence): 97 | X[i, t, char_indices[char]] = 1 98 | y[i, char_indices[next_chars[i]]] = 1 99 | 100 | # build the model: 2 stacked LSTM 101 | model = get_model(maxlen, num_chars, num_layers) 102 | 103 | result_directory = 'result_%s_%s_%d_%d_units/' % (prefix, model_prefix, maxlen, num_units) 104 | filepath_model = '%sbest_model.hdf' % result_directory 105 | description_model = '%s, %d layers, %d units, %d maxlen, %d steps' % (prefix, num_layers, num_units, maxlen, step) 106 | checker = keras.callbacks.ModelCheckpoint(filepath_model, monitor='loss', verbose=0, save_best_only=True, mode='auto') 107 | early_stop = keras.callbacks.EarlyStopping(monitor='loss', patience=15, verbose=0, mode='auto') 108 | 109 | if not os.path.exists(result_directory): 110 | os.mkdir(result_directory) 111 | 112 | # write a description file. 113 | with open(result_directory+description_model, 'w') as f_description: 114 | pass 115 | 116 | # train the model, output generated text after each iteration 117 | batch_size = 128 118 | loss_history = [] 119 | pt_x = [1,29,30,40,100,100,200,300,400] 120 | nb_epochs = [np.sum(pt_x[:i+1]) for i in range(len(pt_x))] 121 | 122 | # not random seed, but the same seed for all. 123 | start_index = random.randint(0, len(text) - maxlen - 1) 124 | 125 | for iteration, nb_epoch in zip(pt_x,nb_epochs): 126 | if os.path.exists('stop_asap.keunwoo'): 127 | os.remove('stop_asap.keunwoo') 128 | break 129 | 130 | print('-' * 50) 131 | print('Iteration', iteration) 132 | 133 | result = model.fit(X, y, batch_size=batch_size, nb_epoch=nb_epoch, callbacks=[checker, early_stop]) 134 | loss_history = loss_history + result.history['loss'] 135 | 136 | print 'Saving model after %d epochs...' % nb_epoch 137 | model.save_weights('%smodel_after_%d.hdf'%(result_directory, nb_epoch), overwrite=True) 138 | 139 | for diversity in [0.9, 1.0, 1.2]: 140 | with open(('%sresult_%s_iter_%02d_diversity_%4.2f.txt' % (result_directory, prefix, iteration, diversity)), 'w') as f_write: 141 | 142 | print() 143 | print('----- diversity:', diversity) 144 | f_write.write('diversity:%4.2f\n' % diversity) 145 | if character_mode: 146 | generated = '' 147 | else: 148 | generated = [] 149 | sentence = text[start_index: start_index + maxlen] 150 | seed_sentence = text[start_index: start_index + maxlen] 151 | 152 | if character_mode: 153 | generated += sentence 154 | else: 155 | generated = generated + sentence 156 | 157 | 158 | print('----- Generating with seed:') 159 | 160 | if character_mode: 161 | print(sentence) 162 | sys.stdout.write(generated) 163 | else: 164 | print(' '.join(sentence)) 165 | 166 | for i in xrange(num_char_pred): 167 | # if generated.endswith('_END_'): 168 | # break 169 | x = np.zeros((1, maxlen, num_chars)) 170 | 171 | for t, char in enumerate(sentence): 172 | x[0, t, char_indices[char]] = 1. 173 | 174 | preds = model.predict(x, verbose=0)[0] 175 | next_index = sample(preds, diversity) 176 | next_char = indices_char[next_index] 177 | 178 | if character_mode: 179 | generated += next_char 180 | sentence = sentence[1:] + next_char 181 | else: 182 | generated.append(next_char) 183 | sentence = sentence[1:] 184 | sentence.append(next_char) 185 | 186 | if character_mode: 187 | sys.stdout.write(next_char) 188 | # else: 189 | # for ch in next_char: 190 | # sys.stdout.write(ch) 191 | 192 | sys.stdout.flush() 193 | 194 | if character_mode: 195 | f_write.write(seed_sentence + '\n') 196 | f_write.write(generated) 197 | else: 198 | f_write.write(' '.join(seed_sentence) + '\n') 199 | f_write.write(' ' .join(generated)) 200 | 201 | np.save('%sloss_%s.npy'%(result_directory, prefix), loss_history) 202 | 203 | print 'Done! You might want to run main_post_process.py to get midi files. ' 204 | print 'You need python-midi (https://github.com/vishnubob/python-midi) to run it.' 205 | 206 | if __name__=='__main__': 207 | 208 | for maxlen in [256]: # for wrod, 256 is about 32 bars. 209 | for num_units in [128,512]: 210 | run(is_character=False, maxlen=maxlen, num_units=num_units) 211 | 212 | -------------------------------------------------------------------------------- /main_post_process.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import pdb 4 | 5 | import midi 6 | 7 | from drum_note_processor import * 8 | 9 | 10 | def text_to_notes(encoded_drums, note_list=None): 11 | ''' 12 | 0b0000000000 0b10000000 ... -> corresponding note. 13 | ''' 14 | if note_list == None: 15 | note_list = Note_List() 16 | 17 | for word_idx, word in enumerate(encoded_drums): 18 | c_tick_here = word_idx*min_ppq 19 | 20 | for pitch_idx, pitch in enumerate(allowed_pitch): 21 | 22 | if word[pitch_idx+2] == '1': 23 | new_note = Note(pitch, c_tick_here) 24 | note_list.add_note(new_note) 25 | return note_list 26 | 27 | 28 | def conv_text_to_midi(filename): 29 | if os.path.exists(filename[:-4]+'.mid'): 30 | return 31 | f = open(filename, 'r') 32 | f.readline() # title 33 | f.readline() # seed sentence 34 | sentence = f.readline() 35 | encoded_drums = sentence.split(' ') 36 | 37 | #find the first BAR 38 | 39 | first_bar_idx = encoded_drums.index('BAR') 40 | 41 | encoded_drums = encoded_drums[first_bar_idx:] 42 | try: 43 | encoded_drums = [ele for ele in encoded_drums if ele not in ['BAR', 'SONG_BEGIN', 'SONG_END', '']] 44 | except: 45 | pdb.set_trace() 46 | 47 | # prepare output 48 | note_list = Note_List() 49 | pattern = midi.Pattern() 50 | track = midi.Track() 51 | #?? 52 | PPQ = 220 53 | min_ppq = PPQ / (event_per_bar/4) 54 | track.resolution = PPQ # ???? too slow. why?? 55 | # track.resolution = 192 56 | pattern.append(track) 57 | 58 | velocity = 84 59 | duration = min_ppq*9/10 # it is easier to set new ticks if duration is shorter than _min_ppq 60 | 61 | note_list = text_to_notes(encoded_drums, note_list=note_list) 62 | 63 | max_c_tick = 0 64 | not_yet_offed = [] # set of midi.pitch object 65 | for note_idx, note in enumerate(note_list.notes[:-1]): 66 | # add onset 67 | tick_here = note.c_tick - max_c_tick 68 | pitch_here = pitch_to_midipitch[note.pitch] 69 | # if pitch_here in cymbals_pitch: # "Lazy-off" for cymbals 70 | # off = midi.NoteOffEvent(tick=0, pitch=pitch_here) 71 | # track.append(off) 72 | 73 | on = midi.NoteOnEvent(tick=tick_here, velocity=velocity, pitch=pitch_here) 74 | track.append(on) 75 | max_c_tick = max(max_c_tick, note.c_tick) 76 | # add offset for something not cymbal 77 | 78 | # if note_list.notes[note_idx+1].c_tick == note.c_tick: 79 | # if pitch_here not in cymbals_pitch: 80 | # # not_yet_offed.append(pitch_here) 81 | 82 | # else: 83 | # check out some note that not off-ed. 84 | for off_idx, waiting_pitch in enumerate(not_yet_offed): 85 | if off_idx == 0: 86 | off = midi.NoteOffEvent(tick=duration, pitch=waiting_pitch) 87 | max_c_tick = max_c_tick + duration 88 | else: 89 | off = midi.NoteOffEvent(tick=0, pitch=waiting_pitch) 90 | track.append(off) 91 | not_yet_offed = [] # set of midi.pitch object 92 | 93 | # finalise 94 | if note_list.notes == []: 95 | print 'No notes in %s' % filename 96 | return 97 | pdb.set_trace() 98 | note = note_list.notes[-1] 99 | tick_here = note.c_tick - max_c_tick 100 | pitch_here = pitch_to_midipitch[note.pitch] 101 | on = midi.NoteOnEvent(tick=tick_here, velocity=velocity, pitch=pitch_here) 102 | off = midi.NoteOffEvent(tick=duration, pitch=pitch_here) 103 | 104 | for off_idx, waiting_pitch in enumerate(not_yet_offed): 105 | off = midi.NoteOffEvent(tick=0, pitch=waiting_pitch) 106 | 107 | # end of track event 108 | eot = midi.EndOfTrackEvent(tick=1) 109 | track.append(eot) 110 | # print pattern 111 | midi.write_midifile(filename[:-4]+'.mid', pattern) 112 | 113 | 114 | if __name__ == '__main__': 115 | 116 | result_dir = sys.argv[1] 117 | filenames = os.listdir(result_dir) # specify which folder result_*.txt files are stored in 118 | filenames = [f for f in filenames if f.startswith('result') and f.endswith('.txt')] 119 | filenames = [f for f in filenames if os.path.getsize(result_dir + '/' + f) != 0] 120 | for filename in filenames: 121 | conv_text_to_midi(result_dir + '/' + filename) 122 | 123 | print 'Texts -> midi done! for %d files' % len(filenames) 124 | 125 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # LSTMetallica 2 | 3 | A LSTM network that learns from the drum tracks of Metallica and generates new tracks. 4 | 5 | #### Prequisite 6 | * Python 2.7. Some of the codes would mis-behave with Python 3. 7 | * [keras](https://github.com/fchollet/keras), a deeplearning framework 8 | * [python-midi](https://github.com/vishnubob/python-midi), to get midi file 9 | * numpy, probably you already have it. 10 | 11 | #### Usage 12 | * Clone the repo 13 | * `$ python main_lstM_etallica.py` to get generated drum track in text file 14 | * text->midi: `$ python main_post_process.py` - this is when you need [python-midi](https://github.com/vishnubob/python-midi) 15 | * Use [this text file](https://github.com/keunwoochoi/LSTMetallica/blob/master/metallica_drums_text.txt), an aggregated-and-encoded text file for Metallica's drum tracks, to do something more 16 | * [This folder](https://github.com/keunwoochoi/LSTMetallica/tree/master/Metallica_drums_midi) contains the original drum midi tracks. 17 | 18 | #### External links 19 | * Details in my [blog post](https://keunwoochoi.wordpress.com/2016/02/23/lstmetallica/) 20 | * [Results on soundcloud](https://soundcloud.com/kchoi-research/sets/lstmetallica-drums) and [+1 more result](https://soundcloud.com/kchoi-research/00-24-100-bonus-for-score) 21 | * Similar work on jazz chord progression: [github repository](https://github.com/keunwoochoi/lstm_real_book), [blog post](https://keunwoochoi.wordpress.com/2016/02/19/lstm-realbook/), [soundcloud](https://soundcloud.com/kchoi-research/sets/lstm-realbook-1-5) 22 | 23 | ### Citation 24 | **Text-based LSTM networks for Automatic Music Composition**, Keunwoo Choi, George Fazekas, Mark Sandler, *1st Conference on Computer Simulation of Musical Creativity*, Huddersfield, UK, 2016, [arXiv](https://arxiv.org/abs/1604.05358#), [pdf](https://arxiv.org/pdf/1604.05358v1), [bib](https://scholar.googleusercontent.com/citations?view_op=export_citations&user=ZrqdSu4AAAAJ&s=ZrqdSu4AAAAJ:MXK_kJrjxJIC&citsig=AMstHGQAAAAAWIjj06BhKkBaBGcqMR__UBSLuabfKgOR&hl=en&cit_fmt=0) 25 | 26 | --------------------------------------------------------------------------------