-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarkovex
executable file
·142 lines (116 loc) · 4.54 KB
/
markovex
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
#!/usr/bin/python
# markovex - Markov chain generative music
#
# Copyright (c) 2010-2011 Alessio Degani <alessio.degani@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
import sys
import os.path
root_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(root_dir + "/include/")
sys.path.append(root_dir + "/include/midi/")
sys.path.append(root_dir + "/include/markovex")
sys.path.append(root_dir + "/lib/")
import argparse
import string
import midi
import markov_synthesis as mks
import markov_analysis as mka
from pyalsa import alsaseq
#Defining default parameter
defaultCH='0'
defaultSEQPORT='0'
defaultBPM='100'
def allNoteOff(sequencer):
for n in range(1,127):
event = alsaseq.SeqEvent(alsaseq.SEQ_EVENT_NOTEOFF)
event.set_data({'note.note' : n, 'note.velocity' : 64})
sequencer.output_event(event)
sequencer.drain_output()
def initSequencer(sequencer):
sequencer.clientname = 'MarkovEX'
sequencer.mode = alsaseq.SEQ_BLOCK
port_id = sequencer.create_simple_port("MIDI out", alsaseq.SEQ_PORT_TYPE_APPLICATION,alsaseq.SEQ_PORT_CAP_READ | alsaseq.SEQ_PORT_CAP_SUBS_READ)
try:
#Argument definition and parsing
parser = argparse.ArgumentParser(description='Markov chain generative music.')
parser.add_argument('-b', '--bpm', help='Override original BPM (ONLY in play mode)', default=defaultBPM, type=int)
parser.add_argument('-c', '--channel', help='Specify midi channel in play mode', default=defaultCH, type=int)
parser.add_argument('-p', '--port', help='Connect to ALSA sequencer port PORT', default=defaultSEQPORT, type=int)
parser.add_argument('-v', '--verbose', help='Verbose output',action='store_const', const=True,default=False)
parser.add_argument('filename', help='Filename (.mid|.mch)' , type=file)
parser.add_argument('-o', '--outfile', help='Output file name (.mch), if you want to save the chain to file instead of playing it', default=0, type=str)
args = parser.parse_args()
#Arguments to constants
CH=args.channel
BPM=args.bpm
SEQPORT=args.port
VERBOSE=args.verbose
#... and global vars VERBOSE on others modules
mka.VERBOSE=VERBOSE
mks.VERBOSE=VERBOSE
sequencer = alsaseq.Sequencer()
print "Markovex begins. Welcome to the world of chaos.\n"
try:
filetype=args.filename.name.split(".")[-1]
except IndexError:
print "File type not allowed"
sys.exit(1)
if (filetype=="mch"):
#Is a chain... read and play it!
print "I'm reading the Markov Chain..."
if (VERBOSE):
print "Midi channel",CH
#Read table from file
(pitchTbl,pitchFirstState,durationTbl,durationFirstState,bpm)=mks.readTable(args.filename)
#Init ALSA sequencer interface and writable client
print "Init sequencer interface..."
initSequencer(sequencer)
if (BPM): bpm=BPM
mks.playTable(pitchTbl,pitchFirstState,durationTbl,durationFirstState,bpm,sequencer,CH)
elif (filetype=="mid"):
#Midi file: try to extimate the 2nd order markov chain
print "I'm parsing the midi file to grab the Markov Chain..."
#Parse midi file
(noteList, songName, trackName, bpm)=mka.parseMidi(args.filename)
#Create transition probability matrix
(pitchFirstState, pitchTbl, durationFirstState, durationTbl)=mka.createTable(noteList, songName, bpm, CH)
if (args.outfile):
#if outfile provided, write table to file
mka.writeTableToFile(args.outfile,songName,trackName,bpm,pitchTbl,pitchFirstState,durationTbl,durationFirstState)
else:
#otherwise play markov chain
print "Chaos begin..."
#Init ALSA sequencer interface and writable client
print "Init sequencer interface..."
initSequencer(sequencer)
if (BPM): bpm=BPM
mks.playTable(pitchTbl,pitchFirstState,durationTbl,durationFirstState,bpm,sequencer,CH)
else:
#File not allowed
print "File type not allowed"
sys.exit(1)
sys.exit(0)
except IOError:
#Error reading File
print "Unable to open file."
sys.exit(1)
except KeyboardInterrupt:
#CTRL+C interrupt
print "\nKeyboard interrupt. Exiting...\n"
#ALLNOTEOF
allNoteOff(sequencer)
#Stop sequencing
del sequencer
sys.exit(0)