-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.py
152 lines (114 loc) · 4.01 KB
/
app.py
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
import random
import markovify #uses markov models to generate new sentences
import ast
from rhyme import rhyme_finder #uses cmudict to find rhyming words based on phonetics
from sylco import sylco #to find number of syllables
""" Preprocessing_Stage
Includes cleaning text files,
removing punctuations
and demarking lines clearly
"""
# Open and model lyrics
with open('lavigne_verse.txt') as f:
verse_text = f.read()
with open('lavigne_chorus.txt') as f:
chorus_text = f.read()
with open('lyrics_tokenize.txt') as f:
tokenized_text = f.read()
verse_model = markovify.NewlineText(verse_text, state_size=2) #to demark new lines in verse raw text
chorus_model = markovify.NewlineText(chorus_text, state_size=2) #to demark new lines in chorus raw text
# Evaluate tokenized_text as a list
tokenized_text = ast.literal_eval(tokenized_text)
# Specify then remove punctuation
punc = set([',','.','"','?','!'])
def clean(str):
if str[-1] in punc:
return str[:-1]
return str
# Generate line that rhymes with stem of verse line 1
def match_rhyme(stem, verse_model):
# Check if rhymes exist
try:
ls = rhyme_finder(stem, tokenized_text)
except KeyError:
return None
if not ls:
return None
# If rhymes exist generate lines
for n in range(100):
while True:
rhyme_line = verse_model.make_sentence() #make random sentence with proper syntax and semantics from verse model
if rhyme_line is not None:
# Keep syllables within range
syl_count = sylco(rhyme_line)
if syl_count > 16 or syl_count < 6:
continue
# Get stem of rhyme_line
rhyme_stem = clean(rhyme_line.rsplit(None, 1)[-1])
# Check for rhyme
if rhyme_stem in ls:
return rhyme_line
break
return None
# Generate 4-line verse
def make_verse(verse_model):
verse = ''
stem = None
# Markovify for each line
for _ in range(4):
while True:
# Try to find rhyming match between lines 1 and 3
if _ == 2:
match = match_rhyme(stem, verse_model)
# If match, add to verse.
if match is not None:
verse += (match + '\n')
break
# Otherwise add non-random markovify line
line = verse_model.make_sentence()
if line is not None:
# Keep syllables within range
syl_count = sylco(line)
if syl_count > 16 or syl_count < 6:
continue
# Cache line for rhyming
if _ == 0:
stem = clean(line.rsplit(None, 1)[-1])
verse += (line + '\n')
break
return verse
# Construct chorus
def make_chorus(chorus_model):
chorus = '[Chorus]' + '\n'
# Two short lines
for _ in range(2):
while True:
line = chorus_model.make_sentence()
if line is not None:
# Keep syllables less than 11
syl_count = sylco(line)
if syl_count > 10:
continue
chorus += (line + '\n')
break
# Two line reprieve
while True:
repeat = chorus_model.make_sentence()
if repeat is not None:
chorus += (repeat + '\n')
chorus += (repeat + '\n')
break
return chorus
# Construct song
def make_song(chorus_model, verse_model):
song_chorus = make_chorus(chorus_model)
"""can change according to the structure
needed for the song
(this one has a verse followed by a chorus
followed by 2 verses and then a the same chorus twice)
"""
song = make_verse(verse_model) + '\n' + song_chorus + '\n' \
+ make_verse(verse_model) + '\n' + make_verse(verse_model) + '\n'\
+ (2 * (song_chorus + '\n'))
return song
print (make_song(chorus_model, verse_model))