praca-magisterska/project/generate.py

97 lines
3.0 KiB
Python
Raw Normal View History

2019-06-19 13:40:35 +02:00
#!python3
#!/usr/bin/env python3
2019-06-19 13:40:35 +02:00
''' This module generates a sample, and create a midi file.
Usage:
>>> ./generate.py [trained_model_path] [output_path]
'''
import settings
import sys
import random
import pickle
2019-05-28 12:40:26 +02:00
import numpy as np
import tensorflow as tf
import pypianoroll as roll
2019-06-19 13:40:35 +02:00
import matplotlib.pyplot as plt
from tqdm import trange, tqdm
from music21 import converter, instrument, note, chord, stream
2019-05-28 12:40:26 +02:00
from keras.layers import Input, Dense, Conv2D
from keras.models import Model
from keras.layers import Input, Dense, Conv2D, Flatten, LSTM, Dropout, TimeDistributed, RepeatVector
from keras.models import Model, Sequential
2019-06-19 13:40:35 +02:00
def choose_by_prob(list_of_probs):
''' This functions a list of values and assumed
that if the value is bigger it should by returned often
It was crated to give more options to choose than argmax function,
thus is more than one way that you can develop a melody.
Returns a index of choosen value from given list.
'''
sum_prob = np.array(list_of_probs).sum()
prob_normalized = [x/sum_prob for x in list_of_probs]
cumsum = np.array(prob_normalized).cumsum()
prob_cum = cumsum.tolist()
random_x = random.random()
for i, x in enumerate(prob_cum):
if random_x < x:
return i
trained_model_path = sys.argv[1]
output_path = sys.argv[2]
2019-06-19 13:40:35 +02:00
# load model and dictionary that can translate back index_numbers to notes
# this dictionary is generated with model
print('Loading... {}'.format(trained_model_path))
model = pickle.load(open(trained_model_path, 'rb'))
2019-06-19 15:48:39 +02:00
int_to_note, n_vocab, seq_len = pickle.load(open('{}_dict'.format(trained_model_path), 'rb'))
2019-06-19 15:48:39 +02:00
seed = [random.randint(0,n_vocab) for x in range(seq_len)]
music = []
print('Generating...')
2019-06-19 13:40:35 +02:00
for i in trange(124):
2019-06-19 15:48:39 +02:00
predicted_vector = model.predict(np.array(seed).reshape(1,seq_len,1))
2019-06-19 13:40:35 +02:00
# using best fitted note
# predicted_index = np.argmax(predicted_vector)
# using propability distribution for choosing note
# to prevent looping
predicted_index = choose_by_prob(predicted_vector)
music.append(int_to_note[predicted_index])
seed.append(predicted_index)
2019-06-19 15:48:39 +02:00
seed = seed[1:1+seq_len]
print('Saving...')
offset = 0
output_notes = []
2019-06-19 15:48:39 +02:00
for _event in tqdm(music):
event, note_len = _event.split(';')
if (' ' in event) or event.isdigit():
notes_in_chord = event.split(' ')
notes = []
for current_note in notes_in_chord:
new_note = note.Note(current_note)
new_note.storedInstrument = instrument.Piano()
notes.append(new_note)
new_chord = chord.Chord(notes)
new_chord.offset = offset
output_notes.append(new_chord)
else:
new_note = note.Note(event)
new_note.offset = offset
new_note.storedInstrument = instrument.Piano()
output_notes.append(new_note)
2019-06-19 15:48:39 +02:00
offset += float(note_len)
midi_stream = stream.Stream(output_notes)
midi_stream.write('midi', fp='{}.mid'.format(output_path))
print('Done!')