CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
amanchadha

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: amanchadha/coursera-deep-learning-specialization
Path: blob/master/C5 - Sequence Models/Week 1/Jazz improvisation with LSTM/qa.py
Views: 4819
1
'''
2
Author: Ji-Sung Kim, Evan Chow
3
Project: deepjazz
4
Purpose: Provide pruning and cleanup functions.
5
6
Code adapted from Evan Chow's jazzml, https://github.com/evancchow/jazzml
7
with express permission.
8
'''
9
from itertools import zip_longest
10
import random
11
12
from music21 import *
13
14
#----------------------------HELPER FUNCTIONS----------------------------------#
15
16
''' Helper function to down num to the nearest multiple of mult. '''
17
def __roundDown(num, mult):
18
return (float(num) - (float(num) % mult))
19
20
''' Helper function to round up num to nearest multiple of mult. '''
21
def __roundUp(num, mult):
22
return __roundDown(num, mult) + mult
23
24
''' Helper function that, based on if upDown < 0 or upDown >= 0, rounds number
25
down or up respectively to nearest multiple of mult. '''
26
def __roundUpDown(num, mult, upDown):
27
if upDown < 0:
28
return __roundDown(num, mult)
29
else:
30
return __roundUp(num, mult)
31
32
''' Helper function, from recipes, to iterate over list in chunks of n
33
length. '''
34
def __grouper(iterable, n, fillvalue=None):
35
args = [iter(iterable)] * n
36
return zip_longest(*args, fillvalue=fillvalue)
37
38
#----------------------------PUBLIC FUNCTIONS----------------------------------#
39
40
''' Smooth the measure, ensuring that everything is in standard note lengths
41
(e.g., 0.125, 0.250, 0.333 ... ). '''
42
def prune_grammar(curr_grammar):
43
pruned_grammar = curr_grammar.split(' ')
44
45
for ix, gram in enumerate(pruned_grammar):
46
terms = gram.split(',')
47
terms[1] = str(__roundUpDown(float(terms[1]), 0.250,
48
random.choice([-1, 1])))
49
pruned_grammar[ix] = ','.join(terms)
50
pruned_grammar = ' '.join(pruned_grammar)
51
52
return pruned_grammar
53
54
''' Remove repeated notes, and notes that are too close together. '''
55
def prune_notes(curr_notes):
56
for n1, n2 in __grouper(curr_notes, n=2):
57
if n2 == None: # corner case: odd-length list
58
continue
59
if isinstance(n1, note.Note) and isinstance(n2, note.Note):
60
if n1.nameWithOctave == n2.nameWithOctave:
61
curr_notes.remove(n2)
62
63
return curr_notes
64
65
''' Perform quality assurance on notes '''
66
def clean_up_notes(curr_notes):
67
removeIxs = []
68
for ix, m in enumerate(curr_notes):
69
# QA1: ensure nothing is of 0 quarter note len, if so changes its len
70
if (m.quarterLength == 0.0):
71
m.quarterLength = 0.250
72
# QA2: ensure no two melody notes have same offset, i.e. form a chord.
73
# Sorted, so same offset would be consecutive notes.
74
if (ix < (len(curr_notes) - 1)):
75
if (m.offset == curr_notes[ix + 1].offset and
76
isinstance(curr_notes[ix + 1], note.Note)):
77
removeIxs.append((ix + 1))
78
curr_notes = [i for ix, i in enumerate(curr_notes) if ix not in removeIxs]
79
80
return curr_notes
81