Skip to content

Instantly share code, notes, and snippets.

@freejoe76
Last active December 26, 2015 12:09
Show Gist options
  • Save freejoe76/7149133 to your computer and use it in GitHub Desktop.
Save freejoe76/7149133 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from pymarkov import markov
from random import choice
import doctest
import argparse
class Generate:
""" A song generator. Generate takes input (musician, album) and returns
a version of that musician's songs.
It expects songs in a text file, in a directory structure such as:
./music
/artist_name
album_title <-- that's the text-file, no extension
It requires pymarkov, via https://pypi.python.org/pypi/PyMarkov/0.1.0
This version of pymarkov prints all input out, removing that print
statement increases sanity.
TODOs:
* Build out a whole song
* Build in song variance (self.attributes)
* How build a rhyme?
>>> generate = Generate('elliott_smith')
>>> song = generate.build_song('either_or')
>>> print song['title']
Elliott Smith, Either Or
"""
def __init__(self, artist, phrase_length=2):
self.artist = artist
self.phrase_length = phrase_length
self.attributes = {
'song': ['no-rhyme', 'no-chorus'],
'stanza': [],
'chorus': ['one-line'],
'verse': []
}
def build_line(self, markov_dict, length):
return markov.generate(markov_dict, length, self.phrase_length)
def build_stanza(self, markov_dict, lines):
i = 0
line = []
pattern_types = {
2: ['aa', 'ab'],
3: ['aaa', 'aba', 'aab', 'abb'],
4: ['aaaa', 'aaab', 'aabb', 'abbb', 'abba', 'aaba', 'abaa']
}
#seed_lengths = [3, 4, 5, 6, 7, 8]
length_patterns = {
2: [[6, 6], [4,6], [4,8]],
3: [[6, 4, 6], [8, 4, 8]],
4: [[6, 4, 4, 6], [4, 4, 4, 4], [7, 2, 2, 7], [5, 5, 7, 7], [3, 3, 3, 3]]
}
length_pattern = choice(length_patterns[lines])
while i < lines:
line += [self.build_line(markov_dict, length_pattern[i])]
i += 1
return line
def build_song(self, album):
fp = 'music/%s/%s' % (self.artist, album)
try:
with open(fp, 'rb') as f:
text = f.read()
f.closed
except:
print 'Could not open album'
return False
markov_dict = markov.train([text], self.phrase_length)
return self.build_stanza(markov_dict, 4)
def main(args):
pass
def build_parser():
""" This method handles command-line arguments.
"""
parser = argparse.ArgumentParser(usage='$ python generate.py',
description='',
epilog='')
parser.add_argument("-v", "--verbose", dest="verbose", default=False, action="store_true")
parser.add_argument("-a", "--artist", dest="artist", default="lana-del-rey")
parser.add_argument("-s", "--song", dest="song", default="all")
return parser
if __name__ == '__main__':
parser = build_parser()
args = parser.parse_args()
generate = Generate(args.artist, 3)
song = { 'body': generate.build_song(args.song) }
print '\n'.join(song['body'])
PyMarkov==0.1.0
wsgiref==0.1.2
@freejoe76
Copy link
Author

Current example output:
separate from the victim of
images stuck in love with
nobody broke your heart you
throwing out now like it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment