Spaces:
Running
Running
File size: 7,006 Bytes
e849e3b 1d4f575 d020229 1d4f575 e849e3b 1d4f575 eada2cd 7f54642 eada2cd 1d4f575 3b240b2 824146a 3b240b2 eada2cd 3b240b2 eada2cd 1d4f575 eada2cd e849e3b 824146a 1d4f575 824146a 61aa7f2 7f54642 e08994d e849e3b eada2cd 1d4f575 eada2cd 3b240b2 eada2cd 5a2d25b eada2cd fad2ef7 eada2cd 824146a eada2cd 824146a eada2cd 2a6e99c eada2cd 2a6e99c eada2cd 8f37861 d020229 eada2cd 824146a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
from distutils.log import debug
import os, sys
import random
import datetime
import glob
# from xml.dom.minidom import Document
import markov
import pickle
import subprocess
import gradio as gr
import time
from MC.markov_chain import get_pngs
#TODO: convert these into inputs
# lengthofsong = 10 Should we control this? Setting it to random now
timesignature = ['3/4','4/4','1/8','6/8','2/4'] #Sometimes the letter “C” (meaning common time) will be used in place of 4/4.
#Both C and 4/4 indicate that there are four quarter note beats in each measure.
keysignature = ["C","G","D","No selection"]
difficulty = ["beginner","intermediate","expert"]
key_enforced = False
key_enforced = True #Set to true if user wants in specific key
# get the list of filenames (abc files downloaded from http://www.norbeck.nu/abc/)
# getdirs = []
# dirs = ["hn201612/i/*.abc", "hn201612/s/*.abc"]
# dirs = ["data/*.abc"]
# dirs = ["data"]
# for dir1 in dirs:
# for filename in glob.iglob(dir1):
# getdirs += [filename]
selected_timeSign = '3/4' #Default values
selected_keySign = 'C' #Default Values
deployed = True
GlobalUIGallery = False
#Finds all absolute paths in directory
#https://stackoverflow.com/questions/9816816/get-absolute-paths-of-all-files-in-a-directory
def abs_paths(dir):
for dir_path,_,filenames in os.walk(dir):
for f in filenames:
yield os.path.abspath(os.path.join(dir_path, f))
def time_sigFinder(time_Signature):
if time_Signature == "4/4":
return 'M:4/4',4
elif time_Signature == "3/4":
return 'M:3/4',3
elif time_Signature == "2/4":
return 'M:2/4',2
elif time_Signature == "1/8":
pass
elif time_Signature == "2/4":
return 'M:2/4',2
elif time_Signature == "2/2":
return 'M:2/2',2
# def get_pngs(path):
# filelist=os.listdir(path)
# for fichier in filelist[:]: # filelist[:] makes a copy of filelist.
# if not(fichier.endswith(".png")):
# filelist.remove(fichier)
# newlist = [path+'/'+x for x in filelist] #making it cwd
# return newlist
def music_gen(difficulty,time_Signature, Key_Signature):
if deployed:
#delete all files stored in gen_songs_abc
command = "rm -r gen_songs_abc/*"
subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
corpus = []
song = []
selected_timeSign = time_Signature
selected_keySign = Key_Signature
data_path = "data/"+str(difficulty)
# ex_filename = "hn201612/i/hnsong1.abc"
# parsing on file to extract songs and add them to corpus
for filename in abs_paths(data_path):
with open(filename) as f:
lines = f.readlines()
last = len(lines)
accepted = False
for index, line in enumerate(lines):
if (line.find("|") < 0 and index - 1 == last):
# if the next line does not have pipes add song to corpus and then set song variable empty again
if accepted and key_enforced and key_accepted:
corpus.append(song)
accepted = False
key_accepted = False
if accepted:
corpus.append(song)
accepted = False
song = []
else:
if line.find("|") > -1:
# a line should be split on "|" and copied to the corpus if it has pipes
sline = line.split("|")
# add the list of measures to the song
song += [x.strip("\r\n") for x in sline if len(x.strip("\r\n")) > 0]
last = index
elif "M:" in line:
#time signature
if selected_timeSign == "4/4":
if "4/4" in line or "C|" in line:
accepted = True
elif selected_timeSign in line:
accepted = True
elif line.find("K:") and key_enforced:
#key signature
if selected_keySign in line:
key_accepted = True
# print("Training on {} songs...".format(len(corpus)))
# MARKOV PART
# n-gram length for markov model
n = 1
model = markov.generate_model_from_token_lists(corpus, n)
# save pickle
# with open('markov_chain.pickle', 'wb') as handle:
# pickle.dump(model, handle)
def nextword(word):
return markov.generate(model, 3, seed=word, max_iterations=1)
def writesong(songlength, first):
song = [first]
for i in range(songlength):
song += nextword(str(song[-1]))
return song
# choose a random song length from list of song lengths in corpus
lengthofsong = random.choice([len(x) for x in corpus if len(x) > 10])
song_len = [len(x) for x in corpus if len(x)>10]
song_len.sort()
firstnote = markov.generate(model, n, max_iterations=3)[0]
# print "first note: {}".format(firstnote)
print("Here is the song in abc format:")
song = writesong(lengthofsong, firstnote)
dob = datetime.datetime.now().strftime('%H%M%S')
modifier = format(dob)
path = "gen_songs_abc/song_"+modifier
# make song file
# songname = "./gen_songs_abc/gen_song_{}.abc".modifier
song_path = path+"/gen_song_"+modifier #without extension
songname = path+"/gen_song_"+modifier+".abc"
print("\n\nYou can find the song in {}".format(songname))
lastpart = lengthofsong - lengthofsong%4
# hack to include dictionary at the beginning of every abc file
# will add a more sophisticated way to generate the values in the future
title = "Markov Song {}".format(dob)
final_timeS,numOfnotes = time_sigFinder(time_Signature)
songbeginning = ['X:1','T:' + title, 'R:song', 'C:Visakh Ajith', 'Z:id:hn-song-111', final_timeS, 'L:1/8', 'Q:1/4=120', 'K:G'
]
songbeginning = [x+"\n" for x in songbeginning]
# convert song to abc format and write to file
if not os.path.exists(path):
os.makedirs("gen_songs_abc/song_"+modifier)
newsong = open(os.path.abspath(songname), 'w')
newsong.writelines(songbeginning)
for i in range(lastpart):
newsong.write(" | ".join(song[i:i+numOfnotes]) + "\n")
newsong.write(" | ".join(song[lastpart:lengthofsong]))
newsong.close()
#abc2ly markov.abc
# lilypond -fpng markov.ly
#convert abc to markov
#create folder with that name and push .ly, midi and abc there?
f = open(song_path+".ly","w")
# subprocess.Popen(['/usr/bin/abc2midi',songname],stdout=subprocess.PIPE).communicate()
command = "abc2ly "+"-o "+song_path+".ly"+" "+songname
# cmd1 = subprocess.Popen(['/usr/bin/abc2ly','-o',song_path+".ly",songname],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# cmd1 = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
# os.system(command)
f.close()
# out, err = cmd1.communicate()
# # time.sleep(2)
cmd2 = subprocess.Popen(['lilypond','-fpng','-o',path,song_path+".ly"]).communicate()
# cmd2.wait()
#fluidsynth() dependency
# subprocess.Popen(['midi2audio',song_path+'.midi',song_path+'.wav']).communicate()
subprocess.Popen(['timidity',song_path+'.midi','-Ow','-o',song_path+'.wav']).communicate()
# output = str(temp.communicate())
#Introduces this wait time as we were returning file path even before lilypond converted the abc file
# final_path = os.path.abspath(song_path+".png")
png_list = get_pngs(path)
return png_list,song_path+".wav"
|