From 35300f3344af933341a69577ea9f6db62469e910 Mon Sep 17 00:00:00 2001 From: Matthias Neeracher Date: Sun, 29 Apr 2007 06:47:40 +0000 Subject: [PATCH] merging mma-1.1 --- mma/MMA/alloc.py | 111 +- mma/MMA/auto.py | 294 +- mma/MMA/chords.py | 630 ++-- mma/MMA/chordtable.py | 544 +-- mma/MMA/common.py | 164 +- mma/MMA/docs.py | 281 +- mma/MMA/file.py | 373 +- mma/MMA/gbl.py | 112 +- mma/MMA/harmony.py | 144 +- mma/MMA/lyric.py | 572 +-- mma/MMA/macro.py | 914 ++--- mma/MMA/main.py | 244 +- mma/MMA/mdefine.py | 72 +- mma/MMA/midi.py | 722 ++-- mma/MMA/midiC.py | 219 +- mma/MMA/midiIn.py | 693 ++-- mma/MMA/midiM.py | 30 +- mma/MMA/miditables.py | 166 + mma/MMA/notelen.py | 166 +- mma/MMA/options.py | 262 +- mma/MMA/parse.py | 2846 +++++++-------- mma/MMA/pat.py | 2946 ++++++++-------- mma/MMA/patAria.py | 228 ++ mma/MMA/patArpeggio.py | 184 +- mma/MMA/patBass.py | 182 +- mma/MMA/patChord.py | 464 ++- mma/MMA/patDrum.py | 131 +- mma/MMA/patScale.py | 300 +- mma/MMA/patSolo.py | 802 ++--- mma/MMA/patWalk.py | 238 +- mma/MMA/translate.py | 275 +- mma/MMA/volume.py | 238 +- mma/cp-install | 32 +- mma/docs/html/lib/index.html | 129 +- mma/docs/html/lib/kara/K50s_rock.html | 17 +- mma/docs/html/lib/kara/Kfunk1.html | 10 +- mma/docs/html/lib/kara/twi.html | 10 +- mma/docs/html/lib/stdlib/50srock.html | 8 +- mma/docs/html/lib/stdlib/60srock.html | 7 +- mma/docs/html/lib/stdlib/8beat.html | 26 +- mma/docs/html/lib/stdlib/ballad.html | 36 +- mma/docs/html/lib/stdlib/ballad128.html | 113 + mma/docs/html/lib/stdlib/basicrock.html | 7 +- mma/docs/html/lib/stdlib/beguine.html | 30 +- mma/docs/html/lib/stdlib/bigband.html | 35 +- mma/docs/html/lib/stdlib/bluegrass.html | 8 +- mma/docs/html/lib/stdlib/blues.html | 10 +- mma/docs/html/lib/stdlib/boggiewoggie.html | 7 +- mma/docs/html/lib/stdlib/bolero.html | 14 +- mma/docs/html/lib/stdlib/bossanova.html | 60 +- mma/docs/html/lib/stdlib/broadway.html | 8 +- mma/docs/html/lib/stdlib/calypso.html | 7 +- mma/docs/html/lib/stdlib/chacha.html | 79 +- mma/docs/html/lib/stdlib/countryblues.html | 15 +- mma/docs/html/lib/stdlib/countryswing.html | 10 +- mma/docs/html/lib/stdlib/countrywaltz.html | 15 +- mma/docs/html/lib/stdlib/desert.html | 6 +- mma/docs/html/lib/stdlib/dixie.html | 8 +- mma/docs/html/lib/stdlib/dixiemarch.html | 8 +- mma/docs/html/lib/stdlib/easyswing.html | 25 +- mma/docs/html/lib/stdlib/fastblues.html | 9 +- mma/docs/html/lib/stdlib/folk.html | 7 +- mma/docs/html/lib/stdlib/foxtrot.html | 12 +- mma/docs/html/lib/stdlib/frenchwaltz.html | 312 +- mma/docs/html/lib/stdlib/guitarballad.html | 8 +- mma/docs/html/lib/stdlib/hillcountry.html | 9 +- mma/docs/html/lib/stdlib/jazz-54.html | 5 +- mma/docs/html/lib/stdlib/jazzguitar.html | 320 ++ mma/docs/html/lib/stdlib/jazzwaltz.html | 11 +- mma/docs/html/lib/stdlib/jive.html | 16 +- mma/docs/html/lib/stdlib/lfusion.html | 8 +- mma/docs/html/lib/stdlib/lighttango.html | 28 +- mma/docs/html/lib/stdlib/lullaby.html | 125 + mma/docs/html/lib/stdlib/mambo.html | 12 +- mma/docs/html/lib/stdlib/march.html | 11 +- mma/docs/html/lib/stdlib/merengue.html | 10 +- mma/docs/html/lib/stdlib/metronome.html | 5 +- mma/docs/html/lib/stdlib/metronome3.html | 3 +- mma/docs/html/lib/stdlib/modernjazz.html | 22 +- mma/docs/html/lib/stdlib/pianoballad.html | 8 +- mma/docs/html/lib/stdlib/polka.html | 12 +- mma/docs/html/lib/stdlib/popballad.html | 49 +- mma/docs/html/lib/stdlib/quickstep.html | 10 +- mma/docs/html/lib/stdlib/rb.html | 6 +- mma/docs/html/lib/stdlib/rhumba.html | 19 +- mma/docs/html/lib/stdlib/rock-128.html | 6 +- mma/docs/html/lib/stdlib/rockballad.html | 79 +- mma/docs/html/lib/stdlib/samba.html | 10 +- mma/docs/html/lib/stdlib/shuffleboggie.html | 137 + mma/docs/html/lib/stdlib/ska.html | 8 +- mma/docs/html/lib/stdlib/slowblues.html | 14 +- mma/docs/html/lib/stdlib/slowbolero.html | 6 +- mma/docs/html/lib/stdlib/slowcountry.html | 10 +- mma/docs/html/lib/stdlib/slowjazz.html | 17 +- mma/docs/html/lib/stdlib/softrock.html | 9 +- mma/docs/html/lib/stdlib/softshoe.html | 22 +- mma/docs/html/lib/stdlib/son.html | 6 +- mma/docs/html/lib/stdlib/swing.html | 30 +- mma/docs/html/lib/stdlib/tango.html | 5 +- mma/docs/html/lib/stdlib/vienesewaltz.html | 7 +- mma/docs/html/lib/stdlib/waltz.html | 13 +- mma/docs/html/lib/stdlib/zydeco.html | 9 +- mma/docs/html/lib/yamaha/mambo.html | 309 ++ mma/docs/html/lib/yamaha/quando-g.s280.html | 332 ++ mma/docs/html/lib/yamaha/w-rock.html | 165 + mma/docs/html/lib/yamaha/western.html | 236 ++ mma/docs/html/mma.html | 2 +- mma/docs/html/ref/img1.png | Bin 231 -> 212 bytes mma/docs/html/ref/img10.png | Bin 155 -> 136 bytes mma/docs/html/ref/img11.png | Bin 273 -> 213 bytes mma/docs/html/ref/img12.png | Bin 232 -> 254 bytes mma/docs/html/ref/img13.png | Bin 448 -> 454 bytes mma/docs/html/ref/img14.png | Bin 231 -> 298 bytes mma/docs/html/ref/img15.png | Bin 226 -> 429 bytes mma/docs/html/ref/img16.png | Bin 248 -> 212 bytes mma/docs/html/ref/img17.png | Bin 297 -> 207 bytes mma/docs/html/ref/img18.png | Bin 290 -> 229 bytes mma/docs/html/ref/img19.png | Bin 277 -> 278 bytes mma/docs/html/ref/img2.png | Bin 302 -> 283 bytes mma/docs/html/ref/img20.png | Bin 295 -> 271 bytes mma/docs/html/ref/img21.png | Bin 233 -> 258 bytes mma/docs/html/ref/img22.png | Bin 237 -> 276 bytes mma/docs/html/ref/img23.png | Bin 252 -> 214 bytes mma/docs/html/ref/img24.png | Bin 238 -> 218 bytes mma/docs/html/ref/img25.png | Bin 287 -> 233 bytes mma/docs/html/ref/img26.png | Bin 0 -> 219 bytes mma/docs/html/ref/img27.png | Bin 0 -> 268 bytes mma/docs/html/ref/img3.png | Bin 241 -> 222 bytes mma/docs/html/ref/img4.png | Bin 207 -> 188 bytes mma/docs/html/ref/img5.png | Bin 234 -> 215 bytes mma/docs/html/ref/img6.png | Bin 213 -> 194 bytes mma/docs/html/ref/img7.png | Bin 270 -> 251 bytes mma/docs/html/ref/img8.png | Bin 176 -> 157 bytes mma/docs/html/ref/img9.png | Bin 224 -> 205 bytes mma/docs/html/ref/index.html | 626 ++-- mma/docs/html/ref/mma.html | 626 ++-- mma/docs/html/ref/mupex/arp4s.png | Bin 2763 -> 3535 bytes mma/docs/html/ref/mupex/bassb8.png | Bin 3643 -> 4836 bytes mma/docs/html/ref/mupex/chord43.png | Bin 3770 -> 5474 bytes mma/docs/html/ref/mupex/cmajor.png | Bin 4179 -> 6218 bytes mma/docs/html/ref/mupex/fermata.png | Bin 3367 -> 4634 bytes mma/docs/html/ref/mupex/fermata2.png | Bin 5883 -> 8269 bytes mma/docs/html/ref/mupex/repeat.png | Bin 3723 -> 5437 bytes mma/docs/html/ref/mupex/soloeg.png | Bin 5357 -> 8291 bytes mma/docs/html/ref/mupex/swingconv.png | Bin 9094 -> 12937 bytes mma/docs/html/ref/mupex/swingdrum8-3.png | Bin 2466 -> 3682 bytes mma/docs/html/ref/mupex/swingdrum8.png | Bin 1773 -> 2388 bytes mma/docs/html/ref/mupex/tilde.png | Bin 4588 -> 6619 bytes mma/docs/html/ref/mupex/tilde2.png | Bin 5031 -> 7205 bytes mma/docs/html/ref/mupex/trip1.png | Bin 3880 -> 5299 bytes mma/docs/html/ref/mupex/trip3.png | Bin 4032 -> 5550 bytes mma/docs/html/ref/node1.html | 227 +- mma/docs/html/ref/node10.html | 317 +- mma/docs/html/ref/node11.html | 1330 +------ mma/docs/html/ref/node12.html | 1449 ++++++-- mma/docs/html/ref/node13.html | 1056 ++---- mma/docs/html/ref/node14.html | 1022 ++++-- mma/docs/html/ref/node15.html | 937 +---- mma/docs/html/ref/node16.html | 1026 +++++- mma/docs/html/ref/node17.html | 1498 +------- mma/docs/html/ref/node18.html | 2615 +++++++------- mma/docs/html/ref/node19.html | 1801 ++++++++-- mma/docs/html/ref/node2.html | 189 +- mma/docs/html/ref/node20.html | 1717 +++------ mma/docs/html/ref/node21.html | 1510 +++++++- mma/docs/html/ref/node22.html | 210 +- mma/docs/html/ref/node23.html | 1087 +----- mma/docs/html/ref/node24.html | 1113 +++++- mma/docs/html/ref/node25.html | 303 +- mma/docs/html/ref/node26.html | 3237 +---------------- mma/docs/html/ref/node27.html | 3461 ++++++++++++++++++- mma/docs/html/ref/node28.html | 462 +-- mma/docs/html/ref/node29.html | 428 ++- mma/docs/html/ref/node3.html | 101 +- mma/docs/html/ref/node30.html | 73 + mma/docs/html/ref/node4.html | 604 ++-- mma/docs/html/ref/node5.html | 333 +- mma/docs/html/ref/node6.html | 266 +- mma/docs/html/ref/node7.html | 96 +- mma/docs/html/ref/node8.html | 179 +- mma/docs/html/ref/node9.html | 255 +- mma/docs/html/tut/index.html | 8 +- mma/docs/html/tut/mma-tutorial.html | 8 +- mma/docs/html/tut/mup/bass.png | Bin 2134 -> 2788 bytes mma/docs/html/tut/mup/deep.png | Bin 24804 -> 37196 bytes mma/docs/html/tut/mup/drums.png | Bin 2315 -> 3162 bytes mma/docs/html/tut/mup/fella.png | Bin 19244 -> 28213 bytes mma/docs/html/tut/mup/piano.png | Bin 3317 -> 4538 bytes mma/docs/html/tut/node1.html | 17 +- mma/docs/html/tut/node2.html | 4 +- mma/docs/html/tut/node3.html | 109 +- mma/docs/html/tut/node4.html | 211 +- mma/docs/html/tut/node5.html | 220 +- mma/docs/html/tut/node6.html | 8 +- mma/egs/README | 2 +- mma/egs/aria/aria.txt | 202 ++ mma/egs/aria/barb.mid | Bin 0 -> 14888 bytes mma/egs/aria/barb.mma | 114 + mma/egs/aria/girl.mid | Bin 0 -> 5785 bytes mma/egs/aria/girl.mma | 62 + mma/egs/harmony/harmony.mid | Bin 3307 -> 3112 bytes mma/egs/lyrics/twinkle.mid | Bin 5632 -> 5566 bytes mma/egs/lyrics/twinkle1.mid | Bin 5724 -> 5553 bytes mma/egs/lyrics/twinkle2.mid | Bin 5689 -> 5525 bytes mma/egs/lyrics/twinkle3.mid | Bin 3533 -> 3332 bytes mma/egs/midi-inc/frankie.mid | Bin 7899 -> 7799 bytes mma/egs/misc/cascade.mid | Bin 669 -> 518 bytes mma/egs/misc/extended-voice.mid | Bin 397 -> 246 bytes mma/egs/misc/grooves.mid | Bin 13516 -> 13283 bytes mma/egs/misc/macros.mid | Bin 978 -> 827 bytes mma/egs/misc/volumes.mid | Bin 3732 -> 3581 bytes mma/egs/riffs/riffs.mid | Bin 2084 -> 1922 bytes mma/egs/rndset/rndchords.mid | Bin 4416 -> 4319 bytes mma/egs/rndset/tempo.mid | Bin 5428 -> 5336 bytes mma/egs/scales/scales.mid | Bin 3437 -> 3286 bytes mma/egs/simple/bill-bailey.mid | Bin 19140 -> 18692 bytes mma/egs/simple/marine-hymn.mid | Bin 4483 -> 4214 bytes mma/egs/tutorial/README | 3 + mma/egs/tutorial/deep-river.mid | Bin 0 -> 12257 bytes mma/egs/tutorial/deep-river.mma | 68 + mma/egs/tutorial/fella1.mid | Bin 0 -> 3704 bytes mma/egs/tutorial/fella1.mma | 23 + mma/egs/tutorial/fella2.mid | Bin 0 -> 7060 bytes mma/egs/tutorial/fella2.mma | 42 + mma/lib/README | 4 +- mma/lib/stdlib/.mmaDB | Bin 9613 -> 11092 bytes mma/lib/stdlib/8beat.mma | 24 +- mma/lib/stdlib/ballad.mma | 27 + mma/lib/stdlib/ballad128.mma | 157 + mma/lib/stdlib/beguine.mma | 48 +- mma/lib/stdlib/bigband.mma | 23 + mma/lib/stdlib/bossanova.mma | 35 +- mma/lib/stdlib/chacha.mma | 66 +- mma/lib/stdlib/frenchwaltz.mma | 356 +- mma/lib/stdlib/jazzguitar.mma | 244 ++ mma/lib/stdlib/lighttango.mma | 19 + mma/lib/stdlib/lullaby.mma | 130 + mma/lib/stdlib/modernjazz.mma | 15 +- mma/lib/stdlib/popballad.mma | 78 +- mma/lib/stdlib/rockballad.mma | 38 +- mma/lib/stdlib/shuffleboggie.mma | 204 ++ mma/lib/stdlib/slowcountry.mma | 9 +- mma/lib/stdlib/softshoe.mma | 14 +- mma/lib/yamaha/.mmaDB | Bin 0 -> 253 bytes mma/lib/yamaha/README | 16 + mma/lib/yamaha/mambo.mma | 1730 +++++++++ mma/lib/yamaha/quando-g.s280.mma | 2108 +++++++++++ mma/lib/yamaha/w-rock.mma | 597 ++++ mma/lib/yamaha/western.mma | 1176 +++++++ mma/ln-install | 74 +- mma/mma.py | 2 +- mma/text/ANNOUNCE | 19 +- mma/text/CHANGES-1.0 | 55 + mma/text/CHANGES-1.0.rc1 | 2 + mma/text/CHANGES-1.0.rc2 | 24 + mma/text/INSTALL | 9 +- mma/text/README | 2 +- mma/text/TIMIDITY | 98 + mma/text/TODO | 3 - mma/util/README.mmatabs | 11 + mma/util/README.timsplit | 16 + mma/util/mklibdoc.py | 164 +- mma/util/mma-renum.py | 72 + mma/util/mmatabs.py | 82 + mma/util/mup2mma.py | 256 ++ mma/util/timsplit.py | 55 + 266 files changed, 34821 insertions(+), 23252 deletions(-) create mode 100644 mma/MMA/miditables.py create mode 100644 mma/MMA/patAria.py create mode 100644 mma/docs/html/lib/stdlib/ballad128.html create mode 100644 mma/docs/html/lib/stdlib/jazzguitar.html create mode 100644 mma/docs/html/lib/stdlib/lullaby.html create mode 100644 mma/docs/html/lib/stdlib/shuffleboggie.html create mode 100644 mma/docs/html/lib/yamaha/mambo.html create mode 100644 mma/docs/html/lib/yamaha/quando-g.s280.html create mode 100644 mma/docs/html/lib/yamaha/w-rock.html create mode 100644 mma/docs/html/lib/yamaha/western.html create mode 100644 mma/docs/html/ref/img26.png create mode 100644 mma/docs/html/ref/img27.png create mode 100644 mma/docs/html/ref/node30.html create mode 100644 mma/egs/aria/aria.txt create mode 100644 mma/egs/aria/barb.mid create mode 100644 mma/egs/aria/barb.mma create mode 100644 mma/egs/aria/girl.mid create mode 100644 mma/egs/aria/girl.mma create mode 100644 mma/egs/tutorial/README create mode 100644 mma/egs/tutorial/deep-river.mid create mode 100644 mma/egs/tutorial/deep-river.mma create mode 100644 mma/egs/tutorial/fella1.mid create mode 100644 mma/egs/tutorial/fella1.mma create mode 100644 mma/egs/tutorial/fella2.mid create mode 100644 mma/egs/tutorial/fella2.mma create mode 100644 mma/lib/stdlib/ballad128.mma create mode 100644 mma/lib/stdlib/jazzguitar.mma create mode 100644 mma/lib/stdlib/lullaby.mma create mode 100644 mma/lib/stdlib/shuffleboggie.mma create mode 100644 mma/lib/yamaha/.mmaDB create mode 100644 mma/lib/yamaha/README create mode 100644 mma/lib/yamaha/mambo.mma create mode 100644 mma/lib/yamaha/quando-g.s280.mma create mode 100644 mma/lib/yamaha/w-rock.mma create mode 100644 mma/lib/yamaha/western.mma create mode 100644 mma/text/CHANGES-1.0 create mode 100644 mma/text/CHANGES-1.0.rc2 create mode 100644 mma/text/TIMIDITY create mode 100644 mma/util/README.mmatabs create mode 100644 mma/util/README.timsplit create mode 100755 mma/util/mma-renum.py create mode 100755 mma/util/mmatabs.py create mode 100755 mma/util/mup2mma.py create mode 100755 mma/util/timsplit.py diff --git a/mma/MMA/alloc.py b/mma/MMA/alloc.py index 2ec1045..05bbf27 100644 --- a/mma/MMA/alloc.py +++ b/mma/MMA/alloc.py @@ -2,7 +2,7 @@ # alloc.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ - + import MMA.patChord import MMA.patWalk import MMA.patBass @@ -30,74 +30,77 @@ import MMA.patDrum import MMA.patScale import MMA.patArpeggio import MMA.patSolo +import MMA.patAria import gbl from MMA.common import * trkClasses = { - 'BASS' : MMA.patBass.Bass, - 'CHORD' : MMA.patChord.Chord, - 'ARPEGGIO' : MMA.patArpeggio.Arpeggio, - 'SCALE' : MMA.patScale.Scale, - 'DRUM' : MMA.patDrum.Drum, - 'WALK' : MMA.patWalk.Walk, - 'MELODY' : MMA.patSolo.Melody, - 'SOLO' : MMA.patSolo.Solo } + 'BASS' : MMA.patBass.Bass, + 'CHORD' : MMA.patChord.Chord, + 'ARPEGGIO' : MMA.patArpeggio.Arpeggio, + 'SCALE' : MMA.patScale.Scale, + 'DRUM' : MMA.patDrum.Drum, + 'WALK' : MMA.patWalk.Walk, + 'MELODY' : MMA.patSolo.Melody, + 'SOLO' : MMA.patSolo.Solo, + 'ARIA' : MMA.patAria.Aria +} def trackAlloc(name, err): - """ Check existence of track and create if possible. + """ Check existence of track and create if possible. - If 'err' is set, the function will 'error out' if - it's not possible to create the track. Otherwise, - it is content to return without creation taking place. - """ + If 'err' is set, the function will 'error out' if + it's not possible to create the track. Otherwise, + it is content to return without creation taking place. + """ - # If the track already exists, just return - - if name in gbl.tnames: - return + # If the track already exists, just return - # Get the trackname. Can be just a type, or type-name. - - if '-' in name: - base, ext = name.split('-',1) - else: - ext = None - base = name + if name in gbl.tnames: + return + + # Get the trackname. Can be just a type, or type-name. + + if '-' in name: + base, ext = name.split('-',1) + else: + ext = None + base = name - """ See if there is a track class 'base'. If there is, then - 'f' points to the initialization function for the class. - If not, we either error (err==1) or return (err==0). - """ + """ See if there is a track class 'base'. If there is, then + 'f' points to the initialization function for the class. + If not, we either error (err==1) or return (err==0). + """ - if trkClasses.has_key(base): - f = trkClasses[base] - else: - if err: - error("There is no track class '%s' for trackname '%s'" % (base, name) ) - else: - return + if trkClasses.has_key(base): + f = trkClasses[base] + else: + if err: + error("There is no track class '%s' for trackname '%s'" % (base, name) ) + else: + return - # Now attempt to allocate the track - - gbl.tnames[name] = newtk = f(name) + # Now attempt to allocate the track - # Set the sequence size of new track - - newtk.setSeqSize() + gbl.tnames[name] = newtk = f(name) - # Update current grooves to reflect new track. - - for slot in gbl.settingsGroove.keys(): - newtk.saveGroove(slot) + # Set the sequence size of new track - - if gbl.debug: - print "Creating new track", name + newtk.setSeqSize() + + # Update current grooves to reflect new track. + + for slot in gbl.settingsGroove.keys(): + newtk.saveGroove(slot) + + + if gbl.debug: + print "Creating new track", name + + return - return - diff --git a/mma/MMA/auto.py b/mma/MMA/auto.py index 370049f..f8deb05 100644 --- a/mma/MMA/auto.py +++ b/mma/MMA/auto.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -34,7 +34,7 @@ import MMA.parse from MMA.common import * grooveDir = {} -mmadir = ".mmaDB" # constant, name of the lib database file +mmadir = ".mmaDB" # constant, name of the lib database file fileCount = 0 grooveCount = 0 gdDate = None @@ -42,161 +42,160 @@ processedFiles = [] mkGrooveList = [] def updateGrooveList(n): - """ Called from parse when new grooves are defined in a -g. """ + """ Called from parse when new grooves are defined in a -g. """ - global mkGrooveList + global mkGrooveList - mkGrooveList.append(n) + mkGrooveList.append(n) def libUpdate(): - """ Update the mma library database file(s) with -g or -G option. + """ Update the mma library database file(s) with -g or -G option. - This is called from the main program after the initialization - and other option parsing. No RETURN. - """ + This is called from the main program after the initialization + and other option parsing. No RETURN. + """ - global fileCount, gdDate, grooveDir, processedfiles + global fileCount, gdDate, grooveDir, processedfiles - print "Creating MMA groove directory database(s). Standby..." + print "Creating MMA groove directory database(s). Standby..." - """ gbl.libPath points to one main directory tree which should include - gbl.autoLib (defaults to 'stdlib'). We create a separate .mmaDB - file for each directory found in the main tree. IE. if we have the - directories stdlib and bvstuff we end up with stdlib/.mmaDB and - bvstuff/.mmaDB. + """ gbl.libPath points to one main directory tree which should include + gbl.autoLib (defaults to 'stdlib'). We create a separate .mmaDB + file for each directory found in the main tree. IE. if we have the + directories stdlib and bvstuff we end up with stdlib/.mmaDB and + bvstuff/.mmaDB. - """ + """ - for d in os.listdir(gbl.libPath): - libpath = os.path.join(gbl.libPath, d) + for d in os.listdir(gbl.libPath): + libpath = os.path.join(gbl.libPath, d) - if not os.path.isdir(libpath): # skip files, just process directories - continue + if not os.path.isdir(libpath): # skip files, just process directories + continue - """ Attempt to read existing database - There is a flag gbl.makeGrvDefs set to 0, 1, 2 - 0 - there was no -g or -G so we're not here - 1 - -g - read existing database and update - 2 - -G - don't read existing, create new - """ + """ Attempt to read existing database + There is a flag gbl.makeGrvDefs set to 0, 1, 2 + 0 - there was no -g or -G so we're not here + 1 - -g - read existing database and update + 2 - -G - don't read existing, create new + """ - grooveDir = {} - gdDate = None + grooveDir = {} + gdDate = None - if gbl.makeGrvDefs == 1: - try: - infile = os.path.join(libpath, mmadir) - f=file(infile, "rb") - f.readline() # Read/discard comment line - grooveDir = pickle.load(f) - f.close() - gdDate = os.path.getmtime(infile) - except: - pass + if gbl.makeGrvDefs == 1: + try: + infile = os.path.join(libpath, mmadir) + f=file(infile, "rb") + f.readline() # Read/discard comment line + grooveDir = pickle.load(f) + f.close() + gdDate = os.path.getmtime(infile) + except: + pass - dolibupdate(libpath, '') + dolibupdate(libpath, '') - # Strip out defs of deleted (not found) files. + # Strip out defs of deleted (not found) files. - for f in grooveDir.keys(): - if f not in processedFiles: - print " Deleting: %s" % f - del grooveDir[f] + for f in grooveDir.keys(): + if f not in processedFiles: + print " Deleting: %s" % f + del grooveDir[f] - try: - outpath = file(os.path.join(libpath, mmadir), 'wb') - except: - error("Error creating lib-database file '%s'. CRITICAL!" - % libpath) + try: + outpath = file(os.path.join(libpath, mmadir), 'wb') + except: + error("Error creating lib-database file '%s'. CRITICAL!" % libpath) - outpath.write("### mmaDB ... AUTOGENERATED BINARY DATA. " - "DO NOT EDIT!!!\n") - pickle.dump(grooveDir, outpath, pickle.HIGHEST_PROTOCOL ) - outpath.close() + outpath.write("### mmaDB ... AUTOGENERATED BINARY DATA. " + "DO NOT EDIT!!!\n") + pickle.dump(grooveDir, outpath, pickle.HIGHEST_PROTOCOL ) + outpath.close() - print - print "Database update complete." - print " Files processed: %s" % fileCount - print " Total number of grooves: %s" % grooveCount + print + print "Database update complete." + print " Files processed: %s" % fileCount + print " Total number of grooves: %s" % grooveCount - sys.exit(0) + sys.exit(0) def dolibupdate(root, subdir): - """ Recursive function to read groove files in a directory. """ + """ Recursive function to read groove files in a directory. """ - global fileCount, grooveCount, gdDate, grooveDir, processedFiles, mkGrooveList + global fileCount, grooveCount, gdDate, grooveDir, processedFiles, mkGrooveList - if subdir == '.': - print "Skipping: '.'" - return + if subdir == '.': + print "Skipping: '.'" + return - if subdir: - print " Processing library directory '%s'." % subdir + if subdir: + print " Processing library directory '%s'." % subdir - """ Get a list of the files in this directory. If the list - includes a file called 'MMAIGNORE' the entire directory - (and subdirs) is ignored. Otherwise, each file in the - directory ending in 'mma' is parsed for groove defs. - """ + """ Get a list of the files in this directory. If the list + includes a file called 'MMAIGNORE' the entire directory + (and subdirs) is ignored. Otherwise, each file in the + directory ending in 'mma' is parsed for groove defs. + """ - p = os.path.join(root,subdir) - dirfiles = os.listdir(p) + p = os.path.join(root,subdir) + dirfiles = os.listdir(p) - if "MMAIGNORE" in dirfiles: - print "Skipping: %s" % p - return + if "MMAIGNORE" in dirfiles: + print "Skipping: %s" % p + return - for fn in sorted(dirfiles): + for fn in sorted(dirfiles): - # Ignore hidden files and emacs auto-save and dead. + # Ignore hidden files and emacs auto-save and dead. - if fn.startswith('.') or fn.startswith('#'): - continue + if fn.startswith('.') or fn.startswith('#'): + continue - # Create full path name + # Create full path name - f=os.path.join(root, subdir, fn) + f=os.path.join(root, subdir, fn) - if os.path.isdir(f): - dolibupdate(root, os.path.join(subdir,fn)) # recursive! + if os.path.isdir(f): + dolibupdate(root, os.path.join(subdir,fn)) # recursive! - elif f.endswith(gbl.ext): - ename = os.path.join(subdir, fn) + elif f.endswith(gbl.ext): + ename = os.path.join(subdir, fn) - processedFiles.append(ename) + processedFiles.append(ename) - if gdDate and grooveDir.has_key(ename) and \ - os.path.getmtime(f) < gdDate: - print " Existing: %s" % f - grooveCount += len(grooveDir[ename]) - continue + if gdDate and grooveDir.has_key(ename) and \ + os.path.getmtime(f) < gdDate: + print " Existing: %s" % f + grooveCount += len(grooveDir[ename]) + continue - if grooveDir.has_key(ename): - print " Updating: %s" % f - else: - print " Creating: %s" % f - mkGrooveList = [] - gbl.mtrks = {} - for c in gbl.midiAssigns.keys(): - gbl.midiAssigns[c]=[] - for a,v in enumerate(gbl.midiAvail): - gbl.midiAvail[a]=0 - gbl.mtrks[0]=MMA.midi.Mtrk(0) - gbl.tnames = {} - MMA.parse.parseFile(f) # read current file, grab grooves + if grooveDir.has_key(ename): + print " Updating: %s" % f + else: + print " Creating: %s" % f + mkGrooveList = [] + gbl.mtrks = {} + for c in gbl.midiAssigns.keys(): + gbl.midiAssigns[c]=[] + for a,v in enumerate(gbl.midiAvail): + gbl.midiAvail[a]=0 + gbl.mtrks[0]=MMA.midi.Mtrk(0) + gbl.tnames = {} + MMA.parse.parseFile(f) # read current file, grab grooves - fileCount += 1 # just so we can report to user - grooveCount += len(mkGrooveList) + fileCount += 1 # just so we can report to user + grooveCount += len(mkGrooveList) - grooveDir[ename]=mkGrooveList + grooveDir[ename]=mkGrooveList - else: - if not f.endswith(mmadir): - print " Ignoring: %s" % f + else: + if not f.endswith(mmadir): + print " Ignoring: %s" % f @@ -204,52 +203,53 @@ def dolibupdate(root, subdir): def loadGrooveDir(g): - """ Try to auto-load a groove from the library. + """ Try to auto-load a groove from the library. - The compliation of all the MMADIR files is stored in the dict - grooveDir{}. + The compliation of all the MMADIR files is stored in the dict + grooveDir{}. - Check the main libpath directory for the MMADIR file. The - names of the files and corresponding grooves are extracted. - This is stored in a dictionary with the filename as the key - and a list of grooves as the data. - """ + Check the main libpath directory for the MMADIR file. The + names of the files and corresponding grooves are extracted. + This is stored in a dictionary with the filename as the key + and a list of grooves as the data. + """ - global grooveDir + global grooveDir - """ If the global dict grooveDir is empty we first load the MMADIR info. - We're assuming that not much goes wrong here...if we don't find - the database we set grooveDir{} to a BS value to avoid future - load attempts. The entire load is in a try, which means it either - all works, or not ... - """ + """ If the global dict grooveDir is empty we first load the MMADIR info. + We're assuming that not much goes wrong here...if we don't find + the database we set grooveDir{} to a BS value to avoid future + load attempts. The entire load is in a try, which means it either + all works, or not ... + """ - if not grooveDir: - try: - infile = os.path.join(gbl.libPath, gbl.autoLib, mmadir) - f=file(infile, "rb") - f.readline() # Read/discard comment line - grooveDir = pickle.load(f) - f.close() - except: - grooveDir[0]='' + if not grooveDir: + try: + infile = os.path.join(gbl.libPath, gbl.autoLib, mmadir) + f=file(infile, "rb") + f.readline() # Read/discard comment line + grooveDir = pickle.load(f) + f.close() + except: + grooveDir[0]='' - """ Search the dict for a match. grooveDir{} is a dictionary - for lists. Each dictionary key is filename (eg: "lib/rhumba.mma") - and the list associated with it is a list of grooves defined - in that file. Just a matter of stepping though the dict. and - returning the proper filename. + """ Search the dict for a match. grooveDir{} is a dictionary + for lists. Each dictionary key is filename (eg: "lib/rhumba.mma") + and the list associated with it is a list of grooves defined + in that file. Just a matter of stepping though the dict. and + returning the proper filename. - RETURN: Lib-Filename if found - None if not found - """ + RETURN: Lib-Filename if found + None if not found + """ - for filename, namelist in grooveDir.items(): - if g in namelist: - return filename + for filename, namelist in grooveDir.items(): + if g in namelist: + return filename + + return None - return None diff --git a/mma/MMA/chords.py b/mma/MMA/chords.py index 0cc9426..76a6dc4 100644 --- a/mma/MMA/chords.py +++ b/mma/MMA/chords.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -27,69 +27,69 @@ import copy from MMA.common import * -from MMA.chordtable import _chords +from MMA.chordtable import chords def defChord(ln): - """ Add a new chord type to the _chords{} dict. """ + """ Add a new chord type to the chords{} dict. """ - emsg="DefChord needs NAME (NOTES) (SCALE)" + emsg="DefChord needs NAME (NOTES) (SCALE)" - # At this point ln is a list. The first item should be - # the new chord type name. + # At this point ln is a list. The first item should be + # the new chord type name. - if not len(ln): - error(emsg) - name = ln.pop(0) - if name in _chords.keys(): - warning("Redefining chordtype '%s'." % name) + if not len(ln): + error(emsg) + name = ln.pop(0) + if name in chords.keys(): + warning("Redefining chordtype '%s'" % name) - if '/' in name: - error("A slash in not permitted in chord type name") + if '/' in name: + error("A slash in not permitted in chord type name") - if '>' in name: - error("A '>' in not permitted in chord type name") + if '>' in name: + error("A '>' in not permitted in chord type name") - ln=pextract(''.join(ln), '(', ')') + ln=pextract(''.join(ln), '(', ')') - if ln[0] or len(ln[1])!=2: - error(emsg) + if ln[0] or len(ln[1])!=2: + error(emsg) - notes=ln[1][0].split(',') - if len(notes) < 2 or len(notes)>8: - error("There must be 2..8 notes in a chord, not '%s'." % len(note)) - notes.sort() - for i,v in enumerate(notes): - v=stoi(v, "Note offsets in chord must be integers, not '%s'." % v) - if v<0 or v>24: - error("Note offsets in chord must be 0..24, not '%s'." % v) - notes[i]=v + notes=ln[1][0].split(',') + if len(notes) < 2 or len(notes)>8: + error("There must be 2..8 notes in a chord, not '%s'" % len(note)) + notes.sort() + for i,v in enumerate(notes): + v=stoi(v, "Note offsets in chord must be integers, not '%s'" % v) + if v<0 or v>24: + error("Note offsets in chord must be 0..24, not '%s'" % v) + notes[i]=v - scale=ln[1][1].split(',') - if len(scale) != 7: - error("There must be 7 offsets in chord scale, not '%s'" % len(scale)) - scale.sort() - for i,v in enumerate(scale): - v=stoi(v, "Scale offsets in chord must be integers, not '%s'." % v) - if v<0 or v>24: - error("Scale offsets in chord must be 0..24, not '%s'." % v) - scale[i]=v + scale=ln[1][1].split(',') + if len(scale) != 7: + error("There must be 7 offsets in chord scale, not '%s'" % len(scale)) + scale.sort() + for i,v in enumerate(scale): + v=stoi(v, "Scale offsets in chord must be integers, not '%s'" % v) + if v<0 or v>24: + error("Scale offsets in chord must be 0..24, not '%s'" % v) + scale[i]=v - _chords[name] = ( notes, scale, "User Defined") + chords[name] = ( notes, scale, "User Defined") - if gbl.debug: - print "ChordType '%s', %s" % (name, _chords[name]) + if gbl.debug: + print "ChordType '%s', %s" % (name, chords[name]) def printChord(ln): - """ Display the note/scale/def for chord(s). """ + """ Display the note/scale/def for chord(s). """ - for c in ln: - if not _chords.has_key(c): - error("Chord '%s' is unknown" % c) - print c, ':', _chords[c][0], _chords[c][1], _chords[c][2] + for c in ln: + if not chords.has_key(c): + error("Chord '%s' is unknown" % c) + print c, ':', chords[c][0], chords[c][1], chords[c][2] """ @@ -100,53 +100,53 @@ that with C as a midpoint we shift left for G/A/B and right for D/E/F. Should the shifts take in account the current key signature? """ -_chordAdjust = { - 'Gb':-6, - 'G' :-5, - 'G#':-4, 'Ab':-4, - 'A' :-3, - 'A#':-2, 'Bb':-2, - 'B' :-1, 'Cb':-1, - 'B#': 0, 'C' : 0, - 'C#': 1, 'Db': 1, - 'D' : 2, - 'D#': 3, 'Eb': 3, - 'E' : 4, 'Fb': 4, - 'E#': 5, 'F' : 5, - 'F#': 6 } +cdAdjust = { + 'Gb':-6, + 'G' :-5, + 'G#':-4, 'Ab':-4, + 'A' :-3, + 'A#':-2, 'Bb':-2, + 'B' :-1, 'Cb':-1, + 'B#': 0, 'C' : 0, + 'C#': 1, 'Db': 1, + 'D' : 2, + 'D#': 3, 'Eb': 3, + 'E' : 4, 'Fb': 4, + 'E#': 5, 'F' : 5, + 'F#': 6 } def chordAdjust(ln): - """ Adjust the chord point up/down one octave. """ + """ Adjust the chord point up/down one octave. """ - if not ln: - error("ChordAdjust: Needs at least one argument.") + if not ln: + error("ChordAdjust: Needs at least one argument") - for l in ln: - try: - pitch, octave = l.split('=') - except: - error("Each arg must contain an '=', not '%s'." % l) + for l in ln: + try: + pitch, octave = l.split('=') + except: + error("Each arg must contain an '=', not '%s'" % l) - if pitch not in _chordAdjust: - error("ChordAdjust: '%s' is not a valid pitch." % pitch) + if pitch not in cdAdjust: + error("ChordAdjust: '%s' is not a valid pitch" % pitch) - octave = stoi(octave, "ChordAdjust: expecting integer, not '%s'." % octave) + octave = stoi(octave, "ChordAdjust: expecting integer, not '%s'" % octave) - p=_chordAdjust[pitch] - if octave == 0: - if p < -6: - _chordAdjust[pitch] += 12 - elif p > 6: - _chordAdjust[pitch]-=12 + p=cdAdjust[pitch] + if octave == 0: + if p < -6: + cdAdjust[pitch] += 12 + elif p > 6: + cdAdjust[pitch]-=12 - elif octave == -1 and p <= 6 and p >= -6: - _chordAdjust[pitch] -= 12 + elif octave == -1 and p <= 6 and p >= -6: + cdAdjust[pitch] -= 12 - elif octave == 1 and p <= 6 and p >= -6: - _chordAdjust[pitch] += 12 + elif octave == 1 and p <= 6 and p >= -6: + cdAdjust[pitch] += 12 - else: - error("ChordAdjust: '%s' is not a valid octave. Use 1, 0 or -1." % octave) + else: + error("ChordAdjust: '%s' is not a valid octave. Use 1, 0 or -1" % octave) @@ -155,348 +155,330 @@ def chordAdjust(ln): ############################### class ChordNotes: - """ The Chord class creates and manipulates chords for MMA. The - class is initialized with a call with the chord name. Eg: + """ The Chord class creates and manipulates chords for MMA. The + class is initialized with a call with the chord name. Eg: - ch = ChordNotes("Am") + ch = ChordNotes("Am") - The following methods and variables are defined: + The following methods and variables are defined: - noteList - the notes in the chord as a list. The "Am" - would be [9, 12, 16]. + noteList - the notes in the chord as a list. The "Am" + would be [9, 12, 16]. - noteListLen - length of noteList. + noteListLen - length of noteList. - tonic - the tonic of the chord ("Am" would be "A"). + tonic - the tonic of the chord ("Am" would be "A"). - chordType - the type of chord ("Am" would be "m"). + chordType - the type of chord ("Am" would be "m"). - rootNote - the root note of the chord ("Am" would be a 9). + rootNote - the root note of the chord ("Am" would be a 9). - bnoteList - the original chord notes, bypassing any - invert(), etc. mangling. + bnoteList - the original chord notes, bypassing any + invert(), etc. mangling. - scaleList - a 7 note list representing a scale similar to - the chord. + scaleList - a 7 note list representing a scale similar to + the chord. - reset() - resets noteList to the original chord notes. - This is useful to restore the original after - chord note mangling by invert(), etc. without having to - create a new chord object. + reset() - resets noteList to the original chord notes. + This is useful to restore the original after + chord note mangling by invert(), etc. without having to + create a new chord object. - invert(n) - Inverts a chord by 'n'. This is done inplace and - returns None. 'n' can have any integer value, but -1 and 1 - are most common. The order of the notes is not changed. Eg: + invert(n) - Inverts a chord by 'n'. This is done inplace and + returns None. 'n' can have any integer value, but -1 and 1 + are most common. The order of the notes is not changed. Eg: - ch=Chord('Am') - ch.noteList == [9, 12, 16] - ch.invert(1) - ch.noteList = [21, 12, 16] + ch=Chord('Am') + ch.noteList == [9, 12, 16] + ch.invert(1) + ch.noteList = [21, 12, 16] - compress() - Compresses the range of a chord to a single octave. This is - done inplace and return None. Eg: + compress() - Compresses the range of a chord to a single octave. This is + done inplace and return None. Eg: - ch=Chord("A13") - ch.noteList == [1, 5, 8, 11, 21] - ch.compress() - ch.noteList == [1, 5, 8, 11, 10 ] + ch=Chord("A13") + ch.noteList == [1, 5, 8, 11, 21] + ch.compress() + ch.noteList == [1, 5, 8, 11, 10 ] - limit(n) - Limits the range of the chord 'n' notes. Done inplace - and returns None. Eg: + limit(n) - Limits the range of the chord 'n' notes. Done inplace + and returns None. Eg: - ch=Chord("CM711") - ch.noteList == [0, 4, 7, 11, 15, 18] - ch.limit(4) - ch.noteList == [0, 4, 7, 11] + ch=Chord("CM711") + ch.noteList == [0, 4, 7, 11, 15, 18] + ch.limit(4) + ch.noteList == [0, 4, 7, 11] - """ + """ - ################# - ### Functions ### - ################# + ################# + ### Functions ### + ################# - def __init__(self, name, line=''): - """ Create a chord object. Pass the chord name as the only arg. + def __init__(self, name, line=''): + """ Create a chord object. Pass the chord name as the only arg. - NOTE: Chord names ARE case-sensitive! + NOTE: Chord names ARE case-sensitive! - The chord NAME at this point is something like 'Cm' or 'A#7'. - Split off the tonic and the type. - If the 2nd char is '#' or 'b' we have a 2 char tonic, - otherwise, it's the first char only. + The chord NAME at this point is something like 'Cm' or 'A#7'. + Split off the tonic and the type. + If the 2nd char is '#' or 'b' we have a 2 char tonic, + otherwise, it's the first char only. - A chord can start with a single '+' or '-'. This moves - the entire chord and scale up/down an octave. + A chord can start with a single '+' or '-'. This moves + the entire chord and scale up/down an octave. - Note pythonic trick: By using ranges like [1:2] we - avoid runtime errors on too-short strings. If a 1 char - string, name[1] is an error; name[1:2] just returns None. + Note pythonic trick: By using ranges like [1:2] we + avoid runtime errors on too-short strings. If a 1 char + string, name[1] is an error; name[1:2] just returns None. - Further note: I have tried to enable caching of the generated - chords, but found no speed difference. So, to make life simpler - I've decided to generate a new object each time. + Further note: I have tried to enable caching of the generated + chords, but found no speed difference. So, to make life simpler + I've decided to generate a new object each time. - """ + """ - slash = None - octave = 0 - inversion = 0 + slash = None + octave = 0 + inversion = 0 - if name == 'z': - self.tonic = self.chordType = None - self.noteListLen = 0 - self.notesList = self.bnoteList = [] - return + if name == 'z': + self.tonic = self.chordType = None + self.noteListLen = 0 + self.notesList = self.bnoteList = [] + return - if '/' in name and '>' in name: - error("You cannot use both an inversion and a slash in the same chord.") + if '/' in name and '>' in name: + error("You cannot use both an inversion and a slash in the same chord") - if '>' in name: - name, inversion = name.split('>', 1) - inversion = stoi(inversion, "Expecting interger after '>'.") - if inversion < -5 or inversion > 5: - error("Chord inversions limited to -5 to 5 (more seems silly).") + if '>' in name: + name, inversion = name.split('>', 1) + inversion = stoi(inversion, "Expecting interger after '>'") + if inversion < -5 or inversion > 5: + error("Chord inversions limited to -5 to 5 (more seems silly)") - if name.startswith('-'): - name = name[1:] - octave = -12 + if name.startswith('-'): + name = name[1:] + octave = -12 - if name.startswith('+'): - name = name[1:] - octave = 12 + if name.startswith('+'): + name = name[1:] + octave = 12 - name = name.replace('&', 'b') + name = name.replace('&', 'b') - # Strip off the slash part of the chord. Use later - # to do proper inversion. + # Strip off the slash part of the chord. Use later + # to do proper inversion. - if name.find('/') > 0: - name, slash = name.split('/') + if name.find('/') > 0: + name, slash = name.split('/') - if name[1:2] in ( '#b' ): - tonic = name[0:2] - ctype = name[2:] - else: - tonic = name[0:1] - ctype = name[1:] + if name[1:2] in ( '#b' ): + tonic = name[0:2] + ctype = name[2:] + else: + tonic = name[0:1] + ctype = name[1:] - if not ctype: # If no type, make it a Major - ctype='M' + if not ctype: # If no type, make it a Major + ctype='M' - try: - notes = _chords[ctype][0] - adj = _chordAdjust[tonic] + octave - except: - error( "Illegal/Unknown chord name: '%s'." % name ) + try: + notes = chords[ctype][0] + adj = cdAdjust[tonic] + octave + except: + error( "Illegal/Unknown chord name: '%s'" % name ) - self.noteList = [ x + adj for x in notes ] - self.bnoteList = tuple(self.noteList) - self.scaleList = tuple([ x + adj for x in _chords[ctype][1] ]) - self.chordType = ctype - self.tonic = tonic - self.rootNote = self.noteList[0] + self.noteList = [ x + adj for x in notes ] + self.bnoteList = tuple(self.noteList) + self.scaleList = tuple([ x + adj for x in chords[ctype][1] ]) + self.chordType = ctype + self.tonic = tonic + self.rootNote = self.noteList[0] - self.noteListLen = len(self.noteList) + self.noteListLen = len(self.noteList) - # Inversion + # Inversion - if inversion: - self.invert(inversion) - self.bnoteList = tuple(self.noteList) + if inversion: + self.invert(inversion) + self.bnoteList = tuple(self.noteList) - # Do inversions if there is a valid slash notation. + # Do inversions if there is a valid slash notation. - if slash: - if not _chordAdjust.has_key(slash): - error("The note '%s' in the slash chord is unknown." % slash) + if slash: + if not cdAdjust.has_key(slash): + error("The note '%s' in the slash chord is unknown" % slash) - r=_chordAdjust[slash] # r = -6 to 6 + r=cdAdjust[slash] # r = -6 to 6 - # If the slash note is in the chord we invert - # the chord so the slash note is in root position. + # If the slash note is in the chord we invert + # the chord so the slash note is in root position. - c_roted = 0 - s=self.noteList - for octave in [0, 12, 24]: - if r+octave in s: - rot=s.index(r+octave) - for i in range(rot): - s.append(s.pop(0)+12) - if s[0] >= 12: - for i,v in enumerate(s): - s[i] = v-12 - self.noteList = s - self.bnoteList = tuple(s) - self.rootNote = self.noteList[0] - c_roted = 1 - break + c_roted = 0 + s=self.noteList + for octave in [0, 12, 24]: + if r+octave in s: + rot=s.index(r+octave) + for i in range(rot): + s.append(s.pop(0)+12) + if s[0] >= 12: + for i,v in enumerate(s): + s[i] = v-12 + self.noteList = s + self.bnoteList = tuple(s) + self.rootNote = self.noteList[0] + c_roted = 1 + break - s_roted = 0 - s=list(self.scaleList) - for octave in [0, 12, 24]: - if r+octave in s: - rot=s.index(r+octave) - for i in range(rot): - s.append(s.pop(0)+12) - if s[0] > 12: - for i,v in enumerate(s): - s[i] = v-12 - self.scaleList=tuple(s) - s_roted = 1 - break + s_roted = 0 + s=list(self.scaleList) + for octave in [0, 12, 24]: + if r+octave in s: + rot=s.index(r+octave) + for i in range(rot): + s.append(s.pop(0)+12) + if s[0] > 12: + for i,v in enumerate(s): + s[i] = v-12 + self.scaleList=tuple(s) + s_roted = 1 + break - if not c_roted and not s_roted: - warning("The slash chord note '%s' not in " - "chord or scale." % slash) + if not c_roted and not s_roted: + warning("The slash chord note '%s' not in chord or scale" % slash) - elif not c_roted: - warning("The slash chord note '%s' not in " - "chord '%s'" % (slash, name)) + elif not c_roted: + warning("The slash chord note '%s' not in chord '%s'" % (slash, name)) - elif not s_roted: # Probably will never happen :) - warning("The slash chord note '%s' not in " - "scale for the chord '%s'" % (slash, name)) + elif not s_roted: # Probably will never happen :) + warning("The slash chord note '%s' not in scale for the chord '%s'" % (slash, name)) - def reset(self): - """ Restores notes array to original, undoes mangling. """ + def reset(self): + """ Restores notes array to original, undoes mangling. """ - self.noteList = list(self.bnoteList[:]) - self.noteListLen = len(self.noteList) + self.noteList = list(self.bnoteList[:]) + self.noteListLen = len(self.noteList) - def invert(self, n): - """ Apply an inversion to a chord. + def invert(self, n): + """ Apply an inversion to a chord. - This does not reorder any notes, which means that the root note of - the chord reminds in postion 0. We just find that highest/lowest - notes in the chord and adjust their octave. + This does not reorder any notes, which means that the root note of + the chord reminds in postion 0. We just find that highest/lowest + notes in the chord and adjust their octave. - NOTE: Done on the existing list of notes. Returns None. - """ + NOTE: Done on the existing list of notes. Returns None. + """ - if n: - c=self.noteList[:] + if n: + c=self.noteList[:] - while n>0: # Rotate up by adding 12 to lowest note - n -= 1 - c[c.index(min(c))]+=12 + while n>0: # Rotate up by adding 12 to lowest note + n -= 1 + c[c.index(min(c))]+=12 - while n<0: # Rotate down, subtract 12 from highest note - n += 1 - c[c.index(max(c))]-=12 + while n<0: # Rotate down, subtract 12 from highest note + n += 1 + c[c.index(max(c))]-=12 - self.noteList = c + self.noteList = c - return None + return None - def compress(self): - """ Compress a chord to one ocatve. + def compress(self): + """ Compress a chord to one ocatve. - Get max permitted value. This is the lowest note - plus 12. Note: use the unmodifed value bnoteList! - """ + Get max permitted value. This is the lowest note + plus 12. Note: use the unmodifed value bnoteList! + """ - mx = self.bnoteList[0] + 12 - c=[] + mx = self.bnoteList[0] + 12 + c=[] - for i, n in enumerate(self.noteList): - if n > mx: - n -= 12 - c.append(n) + for i, n in enumerate(self.noteList): + if n > mx: + n -= 12 + c.append(n) - self.noteList = c + self.noteList = c - return None + return None - def limit(self, n): - """ Limit the number of notes in a chord. """ + def limit(self, n): + """ Limit the number of notes in a chord. """ - if n < self.noteListLen: - self.noteList = self.noteList[:n] - self.noteListLen = len(self.noteList) + if n < self.noteListLen: + self.noteList = self.noteList[:n] + self.noteListLen = len(self.noteList) - return None + return None - def center1(self, lastChord): - """ Descriptive comment needed here!!!! """ + def center1(self, lastChord): + """ Descriptive comment needed here!!!! """ - def minDistToLast(x, lastChord): - dist=99 - for j in range(len(lastChord)): - if abs(x-lastChord[j])0): - return 1 - elif (x<0): - return -1 - else: - return 0 + def sign(x): + if (x>0): + return 1 + elif (x<0): + return -1 + else: + return 0 - # Only change what needs to be changed compared to the last chord - # (leave notes where they are if they are in the new chord as well). + # Only change what needs to be changed compared to the last chord + # (leave notes where they are if they are in the new chord as well). - if lastChord: - ch=self.noteList + if lastChord: + ch=self.noteList - for i in range(len(ch)): + for i in range(len(ch)): - # minimize distance to last chord + # minimize distance to last chord - oldDist = minDistToLast(ch[i], lastChord) - while abs(minDistToLast(ch[i] - sign(oldDist)*12, - lastChord)) < abs(oldDist): - ch[i] -= 12* sign(oldDist) - oldDist = minDistToLast(ch[i], lastChord) + oldDist = minDistToLast(ch[i], lastChord) + while abs(minDistToLast(ch[i] - sign(oldDist)*12, + lastChord)) < abs(oldDist): + ch[i] -= 12* sign(oldDist) + oldDist = minDistToLast(ch[i], lastChord) - return None + return None - def center2(self, centerNote, noteRange): - """ Need COMMENT """ + def center2(self, centerNote, noteRange): + """ Need COMMENT """ - ch=self.noteList - for i,v in enumerate(ch): + ch=self.noteList + for i,v in enumerate(ch): - dist = v - centerNote - if dist < -noteRange: - ch[i] = v + 12 * ( abs(dist) / 12+1 ) - if dist > noteRange: - ch[i] = v - 12 * ( abs(dist) / 12+1 ) + dist = v - centerNote + if dist < -noteRange: + ch[i] = v + 12 * ( abs(dist) / 12+1 ) + if dist > noteRange: + ch[i] = v - 12 * ( abs(dist) / 12+1 ) - return None + return None ######## End of Chord class ##### -def docs(): - """ Print out a list of chord names and docs in LaTex. """ - - import copy - - # Just in case someone else wants to use _chords, work on a copy - - chords=copy.copy(_chords) - - for n in sorted(chords.keys()): - nm=n.replace("#", '$\\sharp$') - nm=nm.replace('b', '$\\flat$') - print "\\insline{%s}{%s}" % (nm, chords[n][2]) - - diff --git a/mma/MMA/chordtable.py b/mma/MMA/chordtable.py index 9bfe5c1..99b0fe7 100644 --- a/mma/MMA/chordtable.py +++ b/mma/MMA/chordtable.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel @@ -53,222 +53,348 @@ A = Bbb= 9 As = Bb = 10 B = Cb = 11 -_chords = { - 'M': ((C, E, G ), - (C, D, E, F, G, A, B), - "Major triad. This is the default and is used in " - "the absense of any other chord type specification."), +chords = { + 'M': ((C, E, G ), + (C, D, E, F, G, A, B), + "Major triad. This is the default and is used in " + "the absense of any other chord type specification."), - 'm': ((C, Eb, G ), - (C, D, Eb, F, G, Ab, Bb), - "Minor triad."), + '(b5)': ((C, E, Gb ), + (C, D, E, F, Gb, A, B), + "Major triad with flat 5th."), - 'mb5': ((C, Eb, Gb ), - (C, D, Eb, F, Gb, Ab, Bb), - "Minor triad with flat 5th."), + 'add9': ((C, E, G, D+12), + (C, D, E, F, G, A, D+12), + "Major chord plus 9th (no 7th.)"), - 'm#5': ((C, Eb, Gs ), - (C, D, Eb, F, Gs, Ab, Bb), - "Major triad with augmented 5th."), + 'm': ((C, Eb, G ), + (C, D, Eb, F, G, Ab, Bb), + "Minor triad."), - 'm6': ((C, Eb, G, A ), - (C, D, Eb, F, G, A, Bb), - "Minor 6th."), + 'mb5': ((C, Eb, Gb ), + (C, D, Eb, F, Gb, Ab, Bb), + "Minor triad with flat 5th (aka dim)."), - 'm6(add9)': ((C, Eb, G, D+12, A+12), - (C, D, Eb, F, G, A, B), - "Minor 6th with added 9th. This is sometimes notated as a slash chord " - "in the form ``m6/9''." ), + 'm#5': ((C, Eb, Gs ), + (C, D, Eb, F, Gs, Ab, Bb), + "Minor triad with augmented 5th."), - 'm7': ((C, Eb, G, Bb ), - (C, D, Eb, F, G, Ab, Bb), - "Minor 7th."), + 'm6': ((C, Eb, G, A ), + (C, D, Eb, F, G, A, Bb), + "Minor 6th (flat 3rd plus a 6th)."), - 'mM7': ((C, Eb, G, B ), - (C, D, Eb, F, G, Ab, B), - "Minor Triad plus Major 7th. You will also see this printed " - "as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' " - "(which \mma\ accepts); as well as the \mma\ \emph{invalid} " - "forms: ``-($\Delta$7)'', and ``min$\\natural$7''."), + 'm6(add9)': ((C, Eb, G, D+12, A+12), + (C, D, Eb, F, G, A, Bb), + "Minor 6th with added 9th. This is sometimes notated as a slash chord " + "in the form ``m6/9''." ), - 'm7b5': ((C, Eb, Gb, Bb ), - (C, D, Eb, F, Gb, Ab, Bb), - "Minor 7th, flat 5 (aka 1/2 diminished). "), + 'm7': ((C, Eb, G, Bb ), + (C, D, Eb, F, G, Ab, Bb), + "Minor 7th (flat 3rd plus dominant 7th)."), - 'm7b9': ((C, Eb, G, Bb, Db+12 ), - (C, Db, Eb, F, G, Ab, Bb), - "Minor 7th with added flat 9th."), + 'mM7': ((C, Eb, G, B ), + (C, D, Eb, F, G, Ab, B), + "Minor Triad plus Major 7th. You will also see this printed " + "as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' " + "(which \mma\ accepts); as well as the \mma\ \emph{invalid} " + "forms: ``-($\Delta$7)'', and ``min$\\natural$7''."), - '7': ((C, E, G, Bb ), - (C, D, E, F, G, A, Bb), - "Dominant 7th."), + 'm+7b9': ((C, Eb, Gs, Bb, Db+12), + (C, Db, Eb, F, Gs, Ab, Bb), + "Augmented minor 7 plus flat 9th."), - '7#5': ((C, E, Gs, Bb ), - (C, D, E, F, Gs, A, Bb), - "7th, sharp 5."), + 'm+7#9': ((C, Eb, Gs, Bb, Ds+12), + (C, Ds, Eb, F, Gs, Ab, Bb), + "Augmented minor 7 plus sharp 9th."), + + 'mM7(add9)': ((C, Eb, G, B, D+12), + (C, D, Eb, F, G, Ab, B), + "Minor Triad plus Major 7th and 9th."), - '7b5': ((C, E, Gb, Bb ), - (C, D, E, F, Gb, A, Bb), - "7th, flat 5."), + 'm7b5': ((C, Eb, Gb, Bb ), + (C, D, Eb, F, Gb, Ab, Bb), + "Minor 7th, flat 5 (aka 1/2 diminished). "), - 'dim7': ((C, Eb, Gb, Bbb ), - (C, D, Eb, F, Gb, Ab, Bbb ), # missing 8th note - "Diminished seventh."), + 'm7b9': ((C, Eb, G, Bb, Db+12 ), + (C, Db, Eb, F, G, Ab, Bb), + "Minor 7th with added flat 9th."), - 'aug': ((C, E, Gs ), - (C, D, E, F, Gs, A, B ), - "Augmented triad."), + 'm7#9': ((C, Eb, G, Bb, Ds+12 ), + (C, Ds, Eb, F, G, Ab, Bb), + "Minor 7th with added sharp 9th."), - '6': ((C, E, G, A ), - (C, D, E, F, G, A, B), - "Major tiad with added 6th."), + '7': ((C, E, G, Bb ), + (C, D, E, F, G, A, Bb), + "7th."), - '6(add9)': ((C, E, G, D+12, A+12), - (C, D, E, F, G, A, B), - "6th with added 9th. This is sometimes notated as a slash chord " - "in the form ``6/9''."), + '7b5': ((C, E, Gb, Bb ), + (C, D, E, F, Gb, A, Bb), + "7th, flat 5."), - 'M7': ((C, E, G, B), - (C, D, E, F, G, A, B), - "Major 7th."), + 'dim7': ((C, Eb, Gb, Bbb ), + (C, D, Eb, F, Gb, Ab, Bbb ), # missing 8th note + "Diminished seventh."), + + 'dim7(addM7)': ((C, Eb, Gb, A, B), + (C, D, Eb, F, Gb, A, B), + "Diminished tirad with added Major 7th."), - 'M7#5': ((C, E, Gs, B), - (C, D, E, F, Gs, A, B), - "Major 7th with sharp 5th."), + 'aug': ((C, E, Gs ), + (C, D, E, F, Gs, A, B ), + "Augmented triad."), - 'M7b5': ((C, E, Gb, B ), - (C, D, E, F, Gb, A, B ), - "Major 7th with a flat 5th."), + '6': ((C, E, G, A ), + (C, D, E, F, G, A, B), + "Major tiad with added 6th."), - '9': ((C, E, G, Bb, D+12 ), - (C, D, E, F, G, A, Bb), - "Dominant 7th plus 9th."), + '6(add9)': ((C, E, G, D+12, A+12), + (C, D, E, F, G, A, B), + "6th with added 9th. This is sometimes notated as a slash chord " + "in the form ``6/9''."), - 'sus9': ((C, E, G, D+12), - (C, D, E, F, G, A, D+12), - "Dominant 7th plus 9th, omit 7th."), + 'M7': ((C, E, G, B), + (C, D, E, F, G, A, B), + "Major 7th."), - '9b5': ((C, E, Gb, Bb, D+12 ), - (C, D, E, F, Gb, A, Bb), - "Dominant 7th plus 9th with flat 5th."), + 'M7#5': ((C, E, Gs, B), + (C, D, E, F, Gs, A, B), + "Major 7th with sharp 5th."), - 'm9': ((C, Eb, G, Bb, D+12 ), - (C, D, Eb, F, G, Ab, Bb), - "Minor triad plus 7th and 9th."), + 'M7b5': ((C, E, Gb, B ), + (C, D, E, F, Gb, A, B ), + "Major 7th with a flat 5th."), - 'm9b5': ((C, Eb, Gb, Bb, D+12 ), - (C, D, Eb, F, Gb, Ab, Bb), - "Minor triad, flat 5, plus 7th and 9th."), + '9': ((C, E, G, Bb, D+12 ), + (C, D, E, F, G, A, Bb), + "7th plus 9th."), - 'm(sus9)':((C, Eb, G, D+12 ), - (C, D, Eb, F, G, Ab, D+12), - "Minor triad plus 9th (no 7th)."), + - 'M9': ((C, E, G, B, D+12 ), - (C, D, E, F, G, A, B), - "Major 7th plus 9th."), + '9b5': ((C, E, Gb, Bb, D+12 ), + (C, D, E, F, Gb, A, Bb), + "7th plus 9th with flat 5th."), - '7b9': ((C, E, G, Bb, Db+12 ), - (C, Db, E, F, G, A, Bb), - "Dominant 7th with flat 9th."), + 'm9': ((C, Eb, G, Bb, D+12 ), + (C, D, Eb, F, G, Ab, Bb), + "Minor triad plus 7th and 9th."), - '7#9': ((C, E, G, Bb, Ds+12 ), - (C, Ds, E, F, G, A, Bb), - "Dominant 7th with sharp 9th."), + 'm7b5b9': ((C, Eb, Gb, Bb, Db+12), + (C, Db, Eb, F, Gb, Ab, Bb), + "Minor 7th with flat 5th and flat 9th."), - '7b5b9':((C, E, Gb, Bb, Db+12 ), - (C, Db, E, F, Gb, A, Bb), - "Dominant 7th with flat 5th and flat 9th."), + 'm9b5': ((C, Eb, Gb, Bb, D+12 ), + (C, D, Eb, F, Gb, Ab, Bb), + "Minor triad, flat 5, plus 7th and 9th."), - '7b5#9':((C, E, Gb, Bb, Ds+12 ), - (C, Ds, E, F, Gb, A, Bb), - "Dominant 7th with flat 5th and sharp 9th."), + 'm(sus9)':((C, Eb, G, D+12 ), + (C, D, Eb, F, G, Ab, D+12), + "Minor triad plus 9th (no 7th)."), - '7#5#9':((C, E, Gs, Bb, Ds+12 ), - (C, Ds, E, F, Gs, A, Bb), - "Dominant 7th with sharp 5th and sharp 9th."), + 'M9': ((C, E, G, B, D+12 ), + (C, D, E, F, G, A, B), + "Major 7th plus 9th."), - '7#5b9':((C, E, Gs, Bb, Db+12 ), - (C, Db, E, F, Gs, A, Bb), - "Dominant 7th with sharp 5th and flat 9th."), + 'M9#11': ((C, E, G, B, D+12, Fs+12), + (C, D, E, Fs, G, A, B), + "Major 9th plus sharp 11th."), - 'aug7': ((C, E, Gs, Bb ), - (C, D, E, F, Gs, A, Bb), - "An augmented chord (raised 5th) with a dominant 7th."), + '7b9': ((C, E, G, Bb, Db+12 ), + (C, Db, E, F, G, A, Bb), + "7th with flat 9th."), - 'aug7b9':((C, E, Gs, Bb, Db+12 ), - (C, Db, E, F, Gs, A, Bb), - "Augmented 7th with flat 5th and sharp 9th."), + '7#9': ((C, E, G, Bb, Ds+12 ), + (C, Ds, E, F, G, A, Bb), + "7th with sharp 9th."), - '11': ((C, E, G, Bb, D+12, F+12 ), - (C, D, E, F, G, A, Bb), - "9th chord plus 11th."), + '7#9b13': ((C, E, G, Bb, Ds+12, Ab+12 ), + (C, Ds, E, F, G, Ab, Bb), + "7th with sharp 9th and flat 13th."), - 'm11': ((C, Eb, G, Bb, D+12, F+12 ), - (C, D, Eb, F, G, Ab, Bb), - "9th with minor 3rd, plus 11th."), + '7b5b9':((C, E, Gb, Bb, Db+12 ), + (C, Db, E, F, Gb, A, Bb), + "7th with flat 5th and flat 9th."), - '11b9': ((C, E, G, Bb, Db+12, F+12 ), - (C, Db, E, F, G, A, Bb), - "9th chord plus flat 11th."), + '7b5#9':((C, E, Gb, Bb, Ds+12 ), + (C, Ds, E, F, Gb, A, Bb), + "7th with flat 5th and sharp 9th."), - '9#5': ((C, E, Gs, Bb, D+12 ), - (C, D, E, F, Gs, A, Bb), - "Dominant 7th plus 9th with sharp 5th."), + '7#5#9':((C, E, Gs, Bb, Ds+12 ), + (C, Ds, E, F, Gs, A, Bb), + "7th with sharp 5th and sharp 9th."), - '9#11': ((C, E, G, Bb, D+12, Fs+12 ), - (C, D, E, Fs, G, A, Bb), - "Dominant 7th plus 9th and sharp 11th."), + + 'aug7': ((C, E, Gs, Bb ), + (C, D, E, F, Gs, A, Bb), + "An augmented chord (raised 5th) with a dominant 7th."), - '7#9#11':((C, E, G, Bb, Ds+12, Fs+12 ), - (C, Ds, E, Fs, G, A, Bb), - "Dominant 7th plus sharp 9th and sharp 11th."), + 'aug7b9':((C, E, Gs, Bb, Db+12 ), + (C, Db, E, F, Gs, A, Bb), + "An augmented chord (raised 5th) with a dominant 7th and flat 9th."), + 'aug7#9':((C, E, Gs, Bb, Ds+12 ), + (C, Ds, E, F, Gs, A, Bb), + "An augmented chord (raised 5th) with a dominant 7th and sharp 9th."), - 'M7#11':((C, E, G, B, D+12, Fs+12 ), - (C, D, E, Fs, G, A, B), - "Major 7th plus 9th and sharp 11th."), + 'aug9M7':((C, E, Gs, B, D+12 ), + (C, D, E, F, Gs, A, B), + "An augmented chord (raised 5th) with a major 7th and 9th."), - # Sus chords. Not sure what to do with the associated scales. For - # now just duplicating the 2nd or 3rd in the scale seems to make sense. + '+7b9#11': ((C, E, Gs, Bb, Db+12, Fs+12), + (C, Db, E, Fs, G, A, Bb), + "Augmented 7th with flat 9th and sharp 11th."), - 'sus4': ((C, F, G ), - (C, D, F, F, G, A, B), - "Suspended 4th, major triad with 3rd raised half tone."), + 'm+7b9#11': ((C, Eb, Gs, Bb, Db+12, Fs+12), + (C, Db, Eb, Fs, Gs, A, Bb), + "Augmented minor 7th with flat 9th and sharp 11th."), - '7sus': ((C, F, G, Bb ), - (C, D, F, F, G, A, Bb), - "7th with suspended 4th, dominant 7th with 3rd " - "raised half tone."), + '11': ((C, C, G, Bb, D+12, F+12 ), + (C, D, E, F, G, A, Bb), + "9th chord plus 11th (3rd not voiced)."), - 'sus2': ((C, D, G ), - (C, D, D, F, G, A, B), - "Suspended 2nd, major triad with major 2nd above " - "root substituted for 3rd."), + 'm11': ((C, Eb, G, Bb, D+12, F+12 ), + (C, D, Eb, F, G, Ab, Bb), + "9th with minor 3rd, plus 11th."), - '7sus2':((C, D, G, Bb ), - (C, D, D, F, G, A, Bb), - "A sus2 with dominant 7th added."), + 'm7(add11)': ((C, Eb, G, Bb, F+12 ), + (C, D, Eb, F, G, Ab, Bb), + "Minor 7th plus 11th."), - # these two chords should probably NOT have the 5th included, - # but since a number of voicings depend on the 5th being - # the third note of the chord, they're here. + 'm9#11': ((C, Eb, G, Bb, D+12, Fs+12), + (C, D, Eb, Fs, G, A, Bb), + "Minor 7th plus 9th and sharp 11th."), - '13': ((C, E, G, Bb, A+12), - (C, D, E, F, G, A, Bb), - "Dominant 7th (including 5th) plus 13th."), + 'm7b9#11': ((C, Eb, G, Bb, Db+12, Fs+12), + (C, Db, Eb, Fs, G, A, Bb), + "Minor 7th plus flat 9th and sharp 11th."), - 'M13': ((C, E, G, B, A+12), - (C, D, E, F, G, A, B), - "Major 7th (including 5th) plus 13th."), + 'm7(add13)': ((C, Eb, G, Bb, A+12 ), + (C, D, Eb, F, G, A, Bb), + "Minor 7th plus 13th."), - # Because some patterns assume that the 3rd note in a chord is a 5th, - # or a varient, we duplicate the root into the position of the 3rd ... and - # to make the sound even we duplicate the 5th into the 4th position as well. + '11b9': ((C, E, G, Bb, Db+12, F+12 ), + (C, Db, E, F, G, A, Bb), + "7th chord plus flat 9th and 11th."), - '5': ((C, C, G, G ), - (C, D, E, F, G, A, B), - "Altered Fifth or Power Chord; root and 5th only."), + '9#5': ((C, E, Gs, Bb, D+12 ), + (C, D, E, F, Gs, A, Bb), + "7th plus 9th with sharp 5th (same as aug9)."), + + '9#11': ((C, E, G, Bb, D+12, Fs+12 ), + (C, D, E, Fs, G, A, Bb), + "7th plus 9th and sharp 11th."), + + '7#9#11':((C, E, G, Bb, Ds+12, Fs+12 ), + (C, Ds, E, Fs, G, A, Bb), + "7th plus sharp 9th and sharp 11th."), + + '7b9#11': ((C, E, G, Bb, Db+12, Fs+12 ), + (C, Db, E, Fs, G, A, Bb), + "7th plus flat 9th and sharp 11th."), + + '7#11':((C, E, G, Bb, Fs+12 ), + (C, D, E, Fs, G, A, Bb), + "7th plus sharp 11th (9th omitted)."), + + 'M7#11':((C, E, G, B, Fs+12 ), + (C, D, E, Fs, G, A, B), + "Major 7th plus sharp 11th (9th omitted)."), + + 'm11b5': ((C, Eb, Gb, Bb, D+12, F+12), + (C, D, Eb, F, Gb, A, Bb), + "Minor 7th with flat 5th plus 11th."), + + # Sus chords. Not sure what to do with the associated scales. For + # now just duplicating the 2nd or 3rd in the scale seems to make sense. + + 'sus4': ((C, F, G ), + (C, D, F, F, G, A, B), + "Suspended 4th, major triad with the 3rd raised half tone."), + + '7sus': ((C, F, G, Bb ), + (C, D, F, F, G, A, Bb), + "7th with suspended 4th, dominant 7th with 3rd " + "raised half tone."), + + '7susb9': ((C, F, G, Bb, Db+12), + (C, Db, F, F, G, A, Bb), + "7th with suspended 4th and flat 9th."), + + 'sus2': ((C, D, G ), + (C, D, D, F, G, A, B), + "Suspended 2nd, major triad with the major 2nd above the " + "root substituted for 3rd."), + + '7sus2':((C, D, G, Bb ), + (C, D, D, F, G, A, Bb), + "A sus2 with dominant 7th added."), + + 'sus9': ((C, F, G, Bb, D+12), + (C, D, F, F, G, A, Bb), + "7sus plus 9th."), + + '13sus': ((C, F, G, Bb, D+12, A+12), + (C, D, F, F, G, A, Bb), + "7sus, plus 9th and 13th"), + + '13susb9': ((C, F, G, Bb, Db+12, A+12), + (C, Db, F, F, G, A, Bb), + "7sus, plus flat 9th and 13th"), + + # these chords should probably NOT have the 5th included, + # but since a number of voicings depend on the 5th being + # the third note of the chord, they're here. + + '13': ((C, E, G, Bb, A+12), + (C, D, E, F, G, A, Bb), + "7th (including 5th) plus 13th (the 9th and 11th are not voiced)."), + + '13b5': ((C, E, Gb, Bb, A+12), + (C, D, E, F, Gb, A, Bb), + "7th with flat 5th, plus 13th (the 9th and 11th are not voiced)."), + + '13#9': ((C, E, G, Bb, Ds+12, A+12), + (C, Ds, E, F, G, A, Bb), + "7th (including 5th) plus 13th and sharp 9th (11th not voiced)."), + + '13b9': ((C, E, G, Bb, Db+12, A+12), + (C, Db, E, F, G, A, Bb), + "7th (including 5th) plus 13th and flat 9th (11th not voiced)."), + + 'M13': ((C, E, G, B, A+12), + (C, D, E, F, G, A, B), + "Major 7th (including 5th) plus 13th (9th and 11th not voiced)."), + + 'm13': ((C, Eb, G, Bb, A+12), + (C, D, Eb, F, G, A, Bb), + "Minor 7th (including 5th) plus 13th (9th and 11th not voiced)."), + + '13#11': ((C, E, G, Bb, Fs+12, A+12), + (C, D, E, Fs, G, A, Bb), + "7th plus sharp 11th and 13th (9th not voiced)."), + + 'M13#11': ((C, E, G, B, Fs+12, A+12), + (C, D, E, Fs, G, A, B), + "Major 7th plus sharp 11th and 13th (9th not voiced)."), + + # Because some patterns assume that the 3rd note in a chord is a 5th, + # or a varient, we duplicate the root into the position of the 3rd ... and + # to make the sound even we duplicate the 5th into the 4th position as well. + + '5': ((C, C, G, G ), + (C, D, E, F, G, A, B), + "Altered Fifth or Power Chord; root and 5th only."), + + 'omit3add9': ((C, C, G, D+12), + (C, D, E, F, G, A, Bb), + "Triad: root, 5th and 9th."), + + '7omit3': ((C, C, G, Bb), + (C, D, E, F, G, A, Bb), + "7th with unvoiced 3rd."), + + 'm7omit5': ((C, Eb, Bb), + (C, D, Eb, F, G, A, Bb), + "Minor 7th with unvoiced 5th."), } @@ -278,44 +404,58 @@ the original. """ aliases = ( - ('aug9', '9#5' , ''), - ('69', '6(add9)', ''), - ('m69', 'm6(add9)', ''), - ('9+5', '9#5' , ''), - ('m+5', 'm#5' , ''), - ('M6', '6' , ''), - ('m7-5', 'm7b5' , ''), - ('+', 'aug' , ''), - ('+7', 'aug7' , ''), - ('#5', 'aug' , ''), - ('7-9', '7b9' , ''), - ('7+9', '7#9' , ''), - ('maj7', 'M7' , ''), - ('M7-5', 'M7b5' , ''), - ('M7+5', 'M7#5' , ''), - ('7alt', '7b5b9', ''), - ('7sus4', '7sus' , ''), - ('7#11', '9#11' , ''), - ('7+', 'aug7' , ''), - ('7+5', '7#5' , ''), - ('7-5', '7b5' , ''), - ('sus', 'sus4' , ''), - ('m(maj7)', 'mM7' , ''), - ('m+7', 'mM7' , ''), - ('min(maj7)','mM7' , ''), - ('min#7', 'mM7' , ''), - ('m#7', 'mM7' , ''), - ('dim', 'dim7' , 'A dim7, not a triad!'), - ('9sus', 'sus9' , ''), - ('9-5', '9b5' , ''), - ('dim3', 'mb5' , 'Diminished triad (non-standard notation).') - ) + ('aug9', '9#5', ''), + ('+9', '9#5', ''), + ('+9M7', 'aug9M7', ''), + ('+M7', 'M7#5', ''), + ('m(add9)', 'm(sus9)', ''), + ('69', '6(add9)', ''), + ('m69', 'm6(add9)', ''), + ('m(b5)', 'mb5', ''), + ('m7(b9)', 'm7b9', ''), + ('m7(#9)', 'm7#9', ''), + ('9+5', '9#5', ''), + ('m+5', 'm#5', ''), + ('M6', '6', ''), + ('m7-5', 'm7b5', ''), + ('m7(omit5)','m7omit5', ''), + ('+', 'aug', ''), + ('+7', 'aug7', ''), + ('7(omit3)', '7omit3', ''), + ('#5', 'aug', ''), + ('7#5b9', 'aug7b9', ''), + ('7-9', '7b9', ''), + ('7+9', '7#9', ''), + ('maj7', 'M7', ''), + ('M7-5', 'M7b5', ''), + ('M7+5', 'M7#5', ''), + ('M7(add13)','13b9', ''), + ('7alt', '7b5b9', ''), + ('7sus4', '7sus', ''), + ('7+', 'aug7', ''), + ('7#5', 'aug7', ''), + ('7+5', 'aug7', ''), + ('7-5', '7b5', ''), + ('sus', 'sus4', ''), + ('maj9', 'M9', ''), + ('maj13', 'M13', ''), + ('m(maj7)', 'mM7', ''), + ('m+7', 'mM7', ''), + ('min(maj7)','mM7', ''), + ('min#7', 'mM7', ''), + ('m#7', 'mM7', ''), + ('dim', 'dim7', 'A dim7, not a triad!'), + ('9sus', 'sus9', ''), + ('9-5', '9b5', ''), + ('dim3', 'mb5', 'Diminished triad (non-standard notation).'), + ('omit3(add9)','omit3add9', '') + ) for a,b,d in aliases: - n=_chords[b][0] - s=_chords[b][1] - if not d: - d=_chords[b][2] + n=chords[b][0] + s=chords[b][1] + if not d: + d=chords[b][2] - _chords[a] = (n, s, d) + chords[a] = (n, s, d) diff --git a/mma/MMA/common.py b/mma/MMA/common.py index 54e8c2f..b50865e 100644 --- a/mma/MMA/common.py +++ b/mma/MMA/common.py @@ -19,13 +19,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel These are a collection of miscellaneous routines used in various parts of MMA. It is safe to load the whole works with: - from MMA.common import * + from MMA.common import * without side effects (yeah, right). @@ -38,136 +38,136 @@ import gbl class struct: - pass + pass def error(msg): - """ Print an error message and exit. + """ Print an error message and exit. - If the global line number is >=0 then print the line number - as well. - """ + If the global line number is >=0 then print the line number + as well. + """ - ln = "" - if gbl.lineno >= 0: - ln += "" % gbl.lineno + ln = "" + if gbl.lineno >= 0: + ln += "" % gbl.lineno - if gbl.inpath: - ln += "" % gbl.inpath.fname + if gbl.inpath: + ln += "" % gbl.inpath.fname - if ln: - ln += '\n' + if ln: + ln += '\n' - print "ERROR:%s %s" % (ln, msg) + print "ERROR:%s %s" % (ln, msg) - sys.exit(1) + sys.exit(1) def warning(msg): - """ Print warning message and return. """ + """ Print warning message and return. """ - if gbl.noWarn: - return + if gbl.noWarn: + return - ln = "" + ln = "" - if gbl.lineno >= 0: - ln = "" % gbl.lineno + if gbl.lineno >= 0: + ln = "" % gbl.lineno - if gbl.inpath: - ln += "" % gbl.inpath.fname + if gbl.inpath: + ln += "" % gbl.inpath.fname - print "Warning:%s\n %s" % (ln, msg) + print "Warning:%s\n %s" % (ln, msg) def getOffset(ticks, ran=None): - """ Calculate a midi offset into a song. + """ Calculate a midi offset into a song. - ticks == offset into the current bar. - ran == random adjustment from RTIME + ticks == offset into the current bar. + ran == random adjustment from RTIME - When calculating the random factor the test ensures - that a note never starts before the start of the bar. - This is important ... voice changes, etc. will be - buggered if we put the voice change after the first - note-on event. - """ + When calculating the random factor the test ensures + that a note never starts before the start of the bar. + This is important ... voice changes, etc. will be + buggered if we put the voice change after the first + note-on event. + """ - p = gbl.tickOffset + int(ticks) # int() cast is important! + p = gbl.tickOffset + int(ticks) # int() cast is important! - if ran: - r = randrange( -ran, ran+1 ) - if ticks == 0 and r < 0: - r=0 - p+=r + if ran: + r = randrange( -ran, ran+1 ) + if ticks == 0 and r < 0: + r=0 + p+=r - return p + return p def stoi(s, errmsg=None): - """ string to integer. """ + """ string to integer. """ - try: - return int(s, 0) - except: - if errmsg: - error(errmsg) - else: - error("Expecting integer value, not %s" % s) + try: + return int(s, 0) + except: + if errmsg: + error(errmsg) + else: + error("Expecting integer value, not %s" % s) def stof(s, errmsg=None): - """ String to floating point. """ + """ String to floating point. """ - try: - return float(s) - except: - if errmsg: - error(errmsg) - else: - error("Expecting a value, not %s" % s) + try: + return float(s) + except: + if errmsg: + error(errmsg) + else: + error("Expecting a value, not %s" % s) def printList(l): - """ Print each item in a list. Works for numeric and string.""" + """ Print each item in a list. Works for numeric and string.""" - for a in l: - print a, - print + for a in l: + print a, + print def pextract(s, open, close, onlyone=None): - """ Extract a parenthesized set of substrings. + """ Extract a parenthesized set of substrings. - s - original string - open - substring start tag \ can be multiple character - close - substring end tag / strings (ie. "<<" or "-->") - onlyone - optional, if set only the first set is extracted + s - original string + open - substring start tag \ can be multiple character + close - substring end tag / strings (ie. "<<" or "-->") + onlyone - optional, if set only the first set is extracted - returns ( original sans subs, [subs, ...] ) + returns ( original sans subs, [subs, ...] ) - eg: pextract( "x{123}{666}y", '{', '}' ) - Returns: ( 'xy', [ '123', '666' ] ) + eg: pextract( "x{123}{666}y", '{', '}' ) + Returns: ( 'xy', [ '123', '666' ] ) - """ + """ - subs =[] - while 1: - lstart = s.find(open) - lend = s.find(close) + subs =[] + while 1: + lstart = s.find(open) + lend = s.find(close) - if lstart>-1 and lstart < lend: - subs.append( s[lstart+len(open):lend].strip() ) - s = s[:lstart] + s[lend+len(close):] - if onlyone: - break - else: - break + if lstart>-1 and lstart < lend: + subs.append( s[lstart+len(open):lend].strip() ) + s = s[:lstart] + s[lend+len(close):] + if onlyone: + break + else: + break - return s.strip(), subs + return s.strip(), subs diff --git a/mma/MMA/docs.py b/mma/MMA/docs.py index 42f73e5..d268e2c 100644 --- a/mma/MMA/docs.py +++ b/mma/MMA/docs.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -32,47 +32,47 @@ import MMA.midiC def docDrumNames(order): - """ Print LaTex table of drum names. """ + """ Print LaTex table of drum names. """ - notenames = ['E\\flat', 'E', 'F', 'G\\flat', 'G', 'A\\flat', - 'A', 'B\\flat', 'B', 'C', 'D\\flat', 'D'] * 5 + notenames = ['E\\flat', 'E', 'F', 'G\\flat', 'G', 'A\\flat', + 'A', 'B\\flat', 'B', 'C', 'D\\flat', 'D'] * 5 - n=zip( MMA.midiC.drumNames, range(27,len(MMA.midiC.drumNames)+27), notenames ) + n=zip( MMA.midiC.drumNames, range(27,len(MMA.midiC.drumNames)+27), notenames ) - if order == "a": - for a,v,m in sorted(n): - print "\\insline{%s} {%s$^{%s}$}" % (a, v, m ) + if order == "a": + for a,v,m in sorted(n): + print "\\insline{%s} {%s$^{%s}$}" % (a, v, m ) - else: - for a,v,m in n: - print "\\insline{%s} {%s$^{%s}$}" % (v, a, m) + else: + for a,v,m in n: + print "\\insline{%s} {%s$^{%s}$}" % (v, a, m) def docCtrlNames(order): - """ Print LaTex table of MIDI controller names. """ + """ Print LaTex table of MIDI controller names. """ - n=zip( MMA.midiC.ctrlNames, range(len(MMA.midiC.ctrlNames)) ) + n=zip( MMA.midiC.ctrlNames, range(len(MMA.midiC.ctrlNames)) ) - if order == "a": - for a,v in sorted(n): - print "\\insline{%s} {%02x}" % (a, v) + if order == "a": + for a,v in sorted(n): + print "\\insline{%s} {%02x}" % (a, v) - else: - for a,v in n: - print "\\insline{%02x} {%s}" % (v, a) + else: + for a,v in n: + print "\\insline{%02x} {%s}" % (v, a) def docInstNames(order): - """ Print LaTex table of instrument names. """ + """ Print LaTex table of instrument names. """ - n=zip( MMA.midiC.voiceNames, range(len(MMA.midiC.voiceNames)) ) - if order == "a": - for a,v in sorted(n): - a=a.replace('&', '\&') - print "\\insline{%s} {%s}" % (a, v) + n=zip( MMA.midiC.voiceNames, range(len(MMA.midiC.voiceNames)) ) + if order == "a": + for a,v in sorted(n): + a=a.replace('&', '\&') + print "\\insline{%s} {%s}" % (a, v) - else: - for a,v in n: - a=a.replace('&', '\&') - print "\\insline{%s} {%s}" % (v, a) + else: + for a,v in n: + a=a.replace('&', '\&') + print "\\insline{%s} {%s}" % (v, a) """ Whenever MMA encounters a DOC command, or if it defines @@ -91,129 +91,166 @@ fname = '' author="" notes="" defs=[] +variables=[] def docAuthor(ln): - global author + global author - author = ' '.join(ln) + author = ' '.join(ln) def docNote(ln): - """ Add a doc line. """ + """ Add a doc line. """ - global fname, notes + global fname, notes - if not gbl.docs or not ln: - return + if not gbl.docs or not ln: + return - # Grab the arg and data, save it + # Grab the arg and data, save it - fname = os.path.basename(gbl.inpath.fname) - if notes: - notes += ' ' - notes += ' '.join(ln) + fname = os.path.basename(gbl.inpath.fname) + if notes: + notes += ' ' + notes += ' '.join(ln) + +def docVars(ln): + """ Add a VARIABLE line (docs vars used in lib file).""" + + global fname, variables + + if not gbl.docs or not ln: + return + + fname = os.path.basename(gbl.inpath.fname) + variables.append([ln[0], ' '.join(ln[1:]) ] ) def docDefine(ln): - """ Save a DEFGROOVE comment string. + """ Save a DEFGROOVE comment string. - Entries are stored as a list. Each item in the list is - complete groove def looking like: - defs[ [ Name, Seqsize, Description, [ [TRACK,INST]...]] ...] + Entries are stored as a list. Each item in the list is + complete groove def looking like: + defs[ [ Name, Seqsize, Description, [ [TRACK,INST]...]] ...] - """ + """ - global defs + global defs - l = [ ln[0], gbl.seqSize, ' '.join(ln[1:]) ] - for a in sorted(gbl.tnames.keys()): - c=gbl.tnames[a] - if c.sequence and len(c.sequence) != c.sequence.count(None): - if c.vtype=='DRUM': - v=MMA.midiC.valueToDrum(c.toneList[0]) - else: - v=MMA.midiC.valueToInst(c.voice[0]) - l.append( [c.name, v ] ) + l = [ ln[0], gbl.seqSize, ' '.join(ln[1:]) ] + for a in sorted(gbl.tnames.keys()): + c=gbl.tnames[a] + if c.sequence and len(c.sequence) != c.sequence.count(None): + if c.vtype=='DRUM': + v=MMA.midiC.valueToDrum(c.toneList[0]) + else: + v=MMA.midiC.valueToInst(c.voice[0]) + l.append( [c.name, v ] ) - defs.append(l) + defs.append(l) def docDump(): - """ Print the LaTex docs. """ + """ Print the LaTex docs. """ - global fname, author, notes, defs + global fname, author, notes, defs, variables - if gbl.docs == 1: # latex docs - if notes: - if fname.endswith(gbl.ext): - fname='.'.join(fname.split('.')[:-1]) - print "\\filehead{%s}{%s}" % (totex(fname), totex(notes)) - print + if gbl.docs == 1: # latex docs + if notes: + if fname.endswith(gbl.ext): + fname='.'.join(fname.split('.')[:-1]) + print "\\filehead{%s}{%s}" % (totex(fname), totex(notes)) + print - if defs: - for l in defs: - print " \\instable{%s}{%s}{%s}{" % \ - (totex(l[0]), totex(l[2]), l[1] ) - for c,v in l[3:]: - print " \\insline{%s}{%s}" % (c.title(), totex(v)) - print " }" + if variables: + print " \\variables{" + for l in variables: + print " \\insvar{%s}{%s}" % ( totex(l[0]), totex(l[1]) ) + print " }" + print - if gbl.docs == 2: # html docs - if notes: - print '' % time.ctime() - print '' - print '' - if fname.endswith(gbl.ext): - fname='.'.join(fname.split('.')[:-1]) - print "

%s

" % fname.title() - print "

%s" % notes - if defs: - print "

    " - for l in defs: - print "
  • %s" % (l[0], l[0]) - print "
" - for l in defs: - print '' % l[0] - print '

' - print '' - print ' ' - print ' ' - print '
' - print '

%s

' % l[0] - print ' %s (%s) ' % ( l[2], l[1] ) - print '
' - print ' ' - for c,v in l[3:]: - print " " % (c.title(), v) - print '
%s %s
' - print '
' - print - print '' - defs = [] - notes = "" - author = "" + if defs: + for l in defs: + print " \\instable{%s}{%s}{%s}{" % \ + (totex(l[0]), totex(l[2]), l[1] ) + for c,v in l[3:]: + print " \\insline{%s}{%s}" % (c.title(), totex(v)) + print " }" + + if gbl.docs == 2: # html docs + if notes: + print '' % time.ctime() + print '' + print '' + if fname.endswith(gbl.ext): + fname='.'.join(fname.split('.')[:-1]) + print "

%s

" % fname.title() + print "

%s" % notes + + if variables: + print "

" + print '' + print ' ' + print ' ' + print '
' + print '

Variables

' + print '
' + print ' ' + for l in variables: + print " " + print " " % l[0] + print " " % l[1] + print " " + print '
%s %s
' + print '
' + + if defs: + print "

    " + for l in defs: + print "
  • %s" % (l[0], l[0]) + print "
" + for l in defs: + print '' % l[0] + print '' + print ' ' + print ' ' + print '
' + print '

%s

' % l[0] + print ' %s (%s) ' % ( l[2], l[1] ) + print '
' + print ' ' + for c,v in l[3:]: + print " " % (c.title(), v) + print '
%s %s
' + print '
' + print + print '' + defs = [] + variables=[] + notes = "" + author = "" def totex(s): - """ Parse a string and quote tex stuff. + """ Parse a string and quote tex stuff. - Also handles proper quotation style. - """ + Also handles proper quotation style. + """ - s = s.replace("$", "\\$") - s = s.replace("*", "$*$") - s = s.replace("\\", "\\\\") - s = s.replace("#", "\\#") - s = s.replace("&", "\\&") + s = s.replace("$", "\$") + s = s.replace("*", "$*$") + s = s.replace("_", "\\_") + #s = s.replace("\\", "\\\\") + s = s.replace("#", "\\#") + s = s.replace("&", "\\&") - q="``" - while s.count('"'): - i=s.find('"') - s=s[:i] + q + s[i+1:] - if q=="``": - q="''" - else: - a="``" + q="``" + while s.count('"'): + s=s.replace('"', q, 1) + if q=="``": + q="''" + else: + q="``" - return s + return s diff --git a/mma/MMA/file.py b/mma/MMA/file.py index bac7967..cd0cc0d 100644 --- a/mma/MMA/file.py +++ b/mma/MMA/file.py @@ -19,11 +19,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ - import sys import os @@ -31,38 +30,38 @@ import gbl from MMA.common import * def locFile(name, lib): - """ Locate a filename. + """ Locate a filename. - This checks, in order: - lib/name + .mma - lib/name - name + .mma - name - """ + This checks, in order: + lib/name + .mma + lib/name + name + .mma + name + """ - ext=gbl.ext - exists = os.path.exists + ext=gbl.ext + exists = os.path.exists - name=os.path.expanduser(name) # for ~ expansion only + name=os.path.expanduser(name) # for ~ expansion only - if lib: - if not name.endswith(ext): - t=os.path.join(lib, name + ext) - if exists(t): - return t - t=os.path.join(lib, name) - if exists(t): - return t + if lib: + if not name.endswith(ext): + t=os.path.join(lib, name + ext) + if exists(t): + return t + t=os.path.join(lib, name) + if exists(t): + return t - if not name.endswith(ext): - t = name + ext - if exists(t): - return t + if not name.endswith(ext): + t = name + ext + if exists(t): + return t - if exists(name): - return name + if exists(name): + return name - return None + return None ########################### @@ -72,241 +71,241 @@ def locFile(name, lib): class ReadFile: - class FileData: - """ After reading the file in bulk it is parsed and stored in this - data structure. Blanks lines and comments are removed. - """ + class FileData: + """ After reading the file in bulk it is parsed and stored in this + data structure. Blanks lines and comments are removed. + """ - def __init__(self, lnum, data, label): - self.lnum=lnum - self.data=data - self.label=label + def __init__(self, lnum, data, label): + self.lnum=lnum + self.data=data + self.label=label - def __init__(self, fname): + def __init__(self, fname): - self.fdata=fdata=[] - self.lastline = None - self.lineptr = None - self.fname = None + self.fdata=fdata=[] + self.lastline = None + self.lineptr = None + self.fname = None - self.que = [] # que for pushed lines (mainly for REPEAT) - self.qnums = [] + self.que = [] # que for pushed lines (mainly for REPEAT) + self.qnums = [] - dataStore = self.FileData # shortcut to avoid '.'s + dataStore = self.FileData # shortcut to avoid '.'s - try: - inpath = file(fname, 'r') + try: + inpath = file(fname, 'r') - except: - error("Unable to open '%s' for input" % fname) + except: + error("Unable to open '%s' for input" % fname) - if gbl.debug or gbl.showFilenames: - print "Opening file '%s'." % fname + if gbl.debug or gbl.showFilenames: + print "Opening file '%s'." % fname - self.fname = fname + self.fname = fname - """ Read entire file, line by line: + """ Read entire file, line by line: - - strip off blanks, comments - - join continuation lines - - parse out LABELS - - create line numbers - """ + - strip off blanks, comments + - join continuation lines + - parse out LABELS + - create line numbers + """ - lcount=0 - label='' - labs=[] # track label defs, error if duplicate in same file - nlabs=[] # track linenumber label defs + lcount=0 + label='' + labs=[] # track label defs, error if duplicate in same file + nlabs=[] # track linenumber label defs - while 1: - l = inpath.readline() + while 1: + l = inpath.readline() - if not l: # EOF - break + if not l: # EOF + break - l= l.strip() - lcount += 1 + l= l.strip() + lcount += 1 - if not l: - continue + if not l: + continue - while l[-1] == '\\': - l = l[0:-1] + ' ' + inpath.readline().strip() - lcount +=1 + while l[-1] == '\\': + l = l[0:-1] + ' ' + inpath.readline().strip() + lcount +=1 - """ This next line splits the line at the first found - comment '//', drops the comment, and splits the - remaining line into tokens using whitespace delimiters. - Note that split() will strip off trailing and leading - spaces, so a strip() is not needed here. - """ + """ This next line splits the line at the first found + comment '//', drops the comment, and splits the + remaining line into tokens using whitespace delimiters. + Note that split() will strip off trailing and leading + spaces, so a strip() is not needed here. + """ - l = l.split('//',1)[0].split() + l = l.split('//',1)[0].split() - if not l: - continue + if not l: + continue - """ Parse out label lines. There are 2 different kinds of labels: - - LABEL XXX - and - - NNN + """ Parse out label lines. There are 2 different kinds of labels: + - LABEL XXX + and + - NNN - The first kind is treated as an exclusive. If a NNN label or previous - XXX duplicates, and error is generated. + The first kind is treated as an exclusive. If a NNN label or previous + XXX duplicates, and error is generated. - The LINE NUMBER type is not exclusive. If a duplicate NNN is found, the - last one is used. + The LINE NUMBER type is not exclusive. If a duplicate NNN is found, the + last one is used. - XXX NNN types can not duplicate each other. + XXX NNN types can not duplicate each other. - Also note that XXX lines are stripped from input as well as NNN lines - with only a NNN. - """ + Also note that XXX lines are stripped from input as well as NNN lines + with only a NNN. + """ - if l[0].upper()=='LABEL': - if len(l) !=2: - gbl.lineno = lcount - error("Usage: LABEL ") - label=l[1].upper() - if label[0]=='$': - gbl.lineno = lcount - error("Variables are not permitted as labels") - if label in labs: - gbl.lineno = lcount - error("Duplicate label specified in line %s." % lcount) - elif label in nlabs: - gbl.lineno = lcount - error("Label '%s' duplicates line number label" % label) - labs.append(label) + if l[0].upper()=='LABEL': + if len(l) !=2: + gbl.lineno = lcount + error("Usage: LABEL ") + label=l[1].upper() + if label[0]=='$': + gbl.lineno = lcount + error("Variables are not permitted as labels") + if label in labs: + gbl.lineno = lcount + error("Duplicate label specified in line %s" % lcount) + elif label in nlabs: + gbl.lineno = lcount + error("Label '%s' duplicates line number label" % label) + labs.append(label) - elif l[0].isdigit(): - label=l[0] + elif l[0].isdigit(): + label=l[0] - if label in labs: - gbl.lineno = lcount - error("Line number '%s' duplicates LABEL." % label) + if label in labs: + gbl.lineno = lcount + error("Line number '%s' duplicates LABEL" % label) - if not label in nlabs: - nlabs.append(label) - else: - for i, a in enumerate(fdata): - if a.label == label: - fdata[i].label='' + if not label in nlabs: + nlabs.append(label) + else: + for i, a in enumerate(fdata): + if a.label == label: + fdata[i].label='' - else: - label = None + else: + label = None - # Save the line, linenumber and (maybe) the label. + # Save the line, linenumber and (maybe) the label. - fdata.append( dataStore(lcount, l, label)) + fdata.append( dataStore(lcount, l, label)) - inpath.close() + inpath.close() - self.lineptr = 0 - self.lastline = len(fdata) + self.lineptr = 0 + self.lastline = len(fdata) - def toEof(self): - """ Move pointer to End of File. """ + def toEof(self): + """ Move pointer to End of File. """ - self.lineptr=self.lastline+1 - self.que = [] - self.qnums = [] + self.lineptr=self.lastline+1 + self.que = [] + self.qnums = [] - def goto(self, l): - """ Do a goto jump. + def goto(self, l): + """ Do a goto jump. - This isn't perfect, but is probably the way most GOTOs work. If - inside a repeat/if then nothing more is processed. The jump is - immediate. Of course, you'll run into problems with missing - repeat/repeatend if you try it. Since all repeats are stacked - back into the que, we just delete the que. Then we look for a - matching label in the file line array. + This isn't perfect, but is probably the way most GOTOs work. If + inside a repeat/if then nothing more is processed. The jump is + immediate. Of course, you'll run into problems with missing + repeat/repeatend if you try it. Since all repeats are stacked + back into the que, we just delete the que. Then we look for a + matching label in the file line array. - Label search is linear. Not too efficient, but the lists - will probably never be that long either. + Label search is linear. Not too efficient, but the lists + will probably never be that long either. - """ + """ - if not l: - error("No label specified") + if not l: + error("No label specified") - if self.que: - self.que=[] + if self.que: + self.que=[] - for i,a in enumerate(self.fdata): - if a.label == l: - self.lineptr=i - return + for i,a in enumerate(self.fdata): + if a.label == l: + self.lineptr=i + return - error("Label '%s' has not be set." % l) + error("Label '%s' has not be set" % l) - def push(self, q, nums): - """ Push a list of lines back into the input stream. + def push(self, q, nums): + """ Push a list of lines back into the input stream. - Note: This is a list of semi-processed lines, no comments, etc. + Note: This is a list of semi-processed lines, no comments, etc. - It's quicker to extend a list than to insert, so add to the end. - Note: we reverse the original, extend() then reverse again, just - in case the caller cares. + It's quicker to extend a list than to insert, so add to the end. + Note: we reverse the original, extend() then reverse again, just + in case the caller cares. - nums is a list of linenumbers. Needed to report error lines. - """ + nums is a list of linenumbers. Needed to report error lines. + """ - if not self.que: - self.que = [''] - self.qnums=[gbl.lineno] + if not self.que: + self.que = [''] + self.qnums=[gbl.lineno] - q.reverse() - self.que.extend(q) - q.reverse() + q.reverse() + self.que.extend(q) + q.reverse() - nums.reverse() - self.qnums.extend(nums) - nums.reverse() + nums.reverse() + self.qnums.extend(nums) + nums.reverse() - def read(self): - """ Return a line. + def read(self): + """ Return a line. - This will return either a queued line or a line from the - file (which was stored/processed earlier). - """ + This will return either a queued line or a line from the + file (which was stored/processed earlier). + """ - while 1: + while 1: - # Return a queued line if possible. + # Return a queued line if possible. - if self.que: - ln = self.que.pop(-1) + if self.que: + ln = self.que.pop(-1) - gbl.lineno = self.qnums.pop() + gbl.lineno = self.qnums.pop() - if not ln: - continue + if not ln: + continue - return ln + return ln - # Return the next line in the file. + # Return the next line in the file. - if self.lineptr>=self.lastline: - return None #### EOF + if self.lineptr>=self.lastline: + return None #### EOF - ln=self.fdata[self.lineptr].data - gbl.lineno = self.fdata[self.lineptr].lnum - self.lineptr +=1 + ln=self.fdata[self.lineptr].data + gbl.lineno = self.fdata[self.lineptr].lnum + self.lineptr +=1 - return ln + return ln diff --git a/mma/MMA/gbl.py b/mma/MMA/gbl.py index 53faa4d..4a22d18 100644 --- a/mma/MMA/gbl.py +++ b/mma/MMA/gbl.py @@ -18,47 +18,47 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ import os -version = "1.0-rc2" # Version -- Oct 15/2006 +version = "1.1" # Version -- March 7/2007 """ mtrks is storage for the MIDI data as it is created. It is a dict of class Mtrk() instances. Keys are the - midi channel numbers. Ie, mtrks[2] is for channel 2, - etc. mtrks[0] is for the meta stuff. + midi channel numbers. Ie, mtrks[2] is for channel 2, + etc. mtrks[0] is for the meta stuff. """ mtrks = {} """ tnames is a dict of assigned track names. The keys are the track names; each entry is a pattern class instance. - We have tnames['BASS-FOO'], etc. + We have tnames['BASS-FOO'], etc. """ tnames = {} """ midiAssigns keeps track of channel/track assignments. The keys are midi channels (1..16), the data is a list of tracks assigned - to each channel. The tracks are only added, not deleted. Right - now this is only used in -c reporting. + to each channel. The tracks are only added, not deleted. Right + now this is only used in -c reporting. """ midiAssigns={} for c in range(0,17): - midiAssigns[c]=[] + midiAssigns[c]=[] """ midiAvail is a list with each entry representing a MIDI channel. As channels are allocated/deallocated the appropriated slot - is inc/decremented. + is inc/decremented. """ midiAvail=[ 0 ] * 17 # slots 0..16, slot 0 is not used. -deletedTracks = [] # list of deleted tracks for -c report +deletedTracks = [] # list of deleted tracks for -c report """ This is a user constructed list of names/channels. The keys are names, data is a channel. Eg. midiChPrefs['BASS-SUS']==9 @@ -71,74 +71,76 @@ midiChPrefs={} """ Groove storage. Each entry in settingsGroove{} has a keyname of a saved groove. - lastGroove and currentGroove are used by macros + lastGroove and currentGroove are used by macros """ -settingsGroove = {} +settingsGroove = {} lastGroove = '' currentGroove = '' """ SeqRnd variable is a list. The first entry is a flag:(0, 1 or x): 0 - not set - 1 - set - 2 - set for specific tracks, track list starts at position [1] + 1 - set + 2 - set for specific tracks, track list starts at position [1] """ -seqRnd = [0] # set if SEQRND has been set +seqRnd = [0] # set if SEQRND has been set ############# String constants #################### -ext = ".mma" # extension for song/lib files. +ext = ".mma" # extension for song/lib files. ############## Tempo, and other midi positioning. ############# -BperQ = 192 # midi ticks per quarter note -QperBar = 4 # Beats/bar, set with TIME -tickOffset = 0 # offset of current bar in ticks -tempo = 120 # current tempo -seqSize = 1 # variation sequence table size -seqCount = 0 # running count of variation +BperQ = 192 # midi ticks per quarter note +QperBar = 4 # Beats/bar, set with TIME +tickOffset = 0 # offset of current bar in ticks +tempo = 120 # current tempo +seqSize = 1 # variation sequence table size +seqCount = 0 # running count of variation -transpose = 0 # Transpose is global (ignored by drum tracks) +transpose = 0 # Transpose is global (ignored by drum tracks) -lineno = -1 # used for error reporting +lineno = -1 # used for error reporting swingMode = 0 # defaults to 0, set to 1 for swing mode swingSkew = None # this is just for $_SwingMode macro barNum = 0 # Current line number +synctick = 0 # flag, set if we want a tick on all tracks at offset 0 + ############# Path and search variables. ############# libPath = '' -for p in ( "c:\\mma\\lib", "/usr/local/share/mma/lib", "/usr/share/mma/lib", "./lib"): - if os.path.isdir(p): - libPath=p - break +for p in ( "c:\\mma\\lib", "/usr/local/share/mma/lib", "/usr/share/mma/lib", "./lib"): + if os.path.isdir(p): + libPath=p + break incPath = '' for p in ( "c:\\mma\\includes", "/usr/local/share/mma/includes", - "/usr/share/mma/includes", "./includes"): - if os.path.isdir(p): - incPath=p - break + "/usr/share/mma/includes", "./includes"): + if os.path.isdir(p): + incPath=p + break autoLib = 'stdlib' -outPath = '' # Directory for MIDI file -mmaStart = [] # list of START files -mmaEnd = [] # list of END files -mmaRC = None # user specified RC file, overrides defaults -inpath = None # input file +outPath = '' # Directory for MIDI file +mmaStart = [] # list of START files +mmaEnd = [] # list of END files +mmaRC = None # user specified RC file, overrides defaults +inpath = None # input file -midiFileType = 1 # type 1 file, SMF command can change to 0 -runningStatus = 1 # running status enabled +midiFileType = 1 # type 1 file, SMF command can change to 0 +runningStatus = 1 # running status enabled ############# Options. ############# @@ -146,24 +148,24 @@ runningStatus = 1 # running status enabled """ These variables are all set from the command line in MMA.opts.py. It's a bit of an easy-way-out to have them all here, but I don't think - it hurts too much. + it hurts too much. """ -debug = Ldebug = 0 -pshow = Lpshow = 0 -seqshow = Lseqshow = 0 -showrun = Lshowrun = 0 -noWarn = LnoWarn = 0 -noOutput = LnoOutput = 0 -showExpand = LshowExpand = 0 -showFilenames = LshowFilenames = 0 -chshow = Lchshow = 0 +debug = Ldebug = 0 +pshow = Lpshow = 0 +seqshow = Lseqshow = 0 +showrun = Lshowrun = 0 +noWarn = LnoWarn = 0 +noOutput = LnoOutput = 0 +showExpand = LshowExpand = 0 +showFilenames = LshowFilenames = 0 +chshow = Lchshow = 0 -outfile = None -infile = None -docs = 0 -maxBars = 500 -makeGrvDefs = 0 -cmdSMF = None +outfile = None +infile = None +docs = 0 +maxBars = 500 +makeGrvDefs = 0 +cmdSMF = None diff --git a/mma/MMA/harmony.py b/mma/MMA/harmony.py index 90aa450..2ef8188 100644 --- a/mma/MMA/harmony.py +++ b/mma/MMA/harmony.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -29,110 +29,110 @@ from MMA.common import * def harmonize(hmode, note, chord): - """ Get harmony note(s) for given chord. """ + """ Get harmony note(s) for given chord. """ - hnotes = [] + hnotes = [] - for tp in hmode.split('+'): + for tp in hmode.split('+'): - if tp in ('2', '2BELOW'): - hnotes.append( gethnote(note, chord) ) + if tp in ('2', '2BELOW'): + hnotes.append( gethnote(note, chord) ) - elif tp == '2ABOVE': - hnotes.append( gethnote(note, chord)+12 ) + elif tp == '2ABOVE': + hnotes.append( gethnote(note, chord)+12 ) - elif tp in ( '3', '3BELOW'): - a = gethnote(note, chord) - b = gethnote(a, chord) - hnotes.extend( [a, b] ) + elif tp in ( '3', '3BELOW'): + a = gethnote(note, chord) + b = gethnote(a, chord) + hnotes.extend( [a, b] ) - elif tp == '3ABOVE': - a = gethnote(note, chord) - b = gethnote(a, chord) - hnotes.extend( [a+12, b+12] ) + elif tp == '3ABOVE': + a = gethnote(note, chord) + b = gethnote(a, chord) + hnotes.extend( [a+12, b+12] ) - elif tp in ('OPEN', "OPENBELOW"): - a=gethnote(note, chord) - hnotes.append( gethnote(a, chord)) + elif tp in ('OPEN', "OPENBELOW"): + a=gethnote(note, chord) + hnotes.append( gethnote(a, chord)) - elif tp == 'OPENABOVE': - a=gethnote(note, chord) - hnotes.append( gethnote(a, chord) + 12 ) + elif tp == 'OPENABOVE': + a=gethnote(note, chord) + hnotes.append( gethnote(a, chord) + 12 ) - elif tp in ('8', '8BELOW'): - hnotes.append( note - 12 ) + elif tp in ('8', '8BELOW'): + hnotes.append( note - 12 ) - elif tp == '8ABOVE': - hnotes.append( note + 12 ) + elif tp == '8ABOVE': + hnotes.append( note + 12 ) - elif tp in ('16', '16BELOW'): - hnotes.append( note - (2 * 12) ) + elif tp in ('16', '16BELOW'): + hnotes.append( note - (2 * 12) ) - elif tp == '16ABOVE': - hnotes.append( note + (2 * 12) ) + elif tp == '16ABOVE': + hnotes.append( note + (2 * 12) ) - elif tp in ('24', '24BELOW'): - hnotes.append( note - (3 * 12) ) + elif tp in ('24', '24BELOW'): + hnotes.append( note - (3 * 12) ) - elif tp == '24ABOVE': - hnotes.append( note + (3 * 12) ) - else: - error("Unknown harmony type '%s'." % tp) + elif tp == '24ABOVE': + hnotes.append( note + (3 * 12) ) + else: + error("Unknown harmony type '%s'" % tp) - """ Strip out duplicate notes from harmony list. Cute trick here, - we use the note values as keys for a new dictionary, assign - a null value, and return the list of keys. - """ + """ Strip out duplicate notes from harmony list. Cute trick here, + we use the note values as keys for a new dictionary, assign + a null value, and return the list of keys. + """ - return dict([(i, None) for i in hnotes]).keys() + return dict([(i, None) for i in hnotes]).keys() def gethnote(note, chord): - """ Determine harmony notes for a note based on the chord. + """ Determine harmony notes for a note based on the chord. - note - midi value of the note + note - midi value of the note - chord - list of midi values for the chord + chord - list of midi values for the chord - This routine works by creating a chord list with all - its notes having a value less than the note (remember, this - is all MIDI values). We then grab notes from the end of - the chord until one is found which is less than the original - note. - """ + This routine works by creating a chord list with all + its notes having a value less than the note (remember, this + is all MIDI values). We then grab notes from the end of + the chord until one is found which is less than the original + note. + """ - wm="No harmony note found since no chord, using note " + \ - "0 which will sound bad." + wm="No harmony note found since no chord, using note " + \ + "0 which will sound bad" - if not chord: # should never happen! - warning(wm) - return 0 + if not chord: # should never happen! + warning(wm) + return 0 - ch = list(chord) # copy chord and sort - ch.sort() + ch = list(chord) # copy chord and sort + ch.sort() - # ensure that the note is in the chord + # ensure that the note is in the chord - while ch[-1] < note: - for i,n in enumerate(ch): - ch[i]+=12 + while ch[-1] < note: + for i,n in enumerate(ch): + ch[i]+=12 - while ch[0] >= note: - for i,v in enumerate(ch): - ch[i]-=12 + while ch[0] >= note: + for i,v in enumerate(ch): + ch[i]-=12 - # get one lower than the note + # get one lower than the note - while 1: - if not ch: # this probably can't happen - warning(wm) - return 0 + while 1: + if not ch: # this probably can't happen + warning(wm) + return 0 - h=ch.pop() - if h - +Bob van der Poel + """ import gbl @@ -29,320 +29,320 @@ from MMA.common import * class Lyric: - textev = None # set if TEXT EVENTS (not recommended) - barsplit = None # set if lyrics NOT split into sep. events for bar - versenum = 1 # current verse number of lyric - dupchords = 0 # set if we want chords as lyric events - transpose = 0 # tranpose chord names (for dupchords only) - - pushedLyrics = [] + textev = None # set if TEXT EVENTS (not recommended) + barsplit = None # set if lyrics NOT split into sep. events for bar + versenum = 1 # current verse number of lyric + dupchords = 0 # set if we want chords as lyric events + transpose = 0 # tranpose chord names (for dupchords only) - transNames = ( ('C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'), - ('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B')) - - transKey = 0 # 0==flat, 1=sharp - - chordnames={ - 'B#': 0, 'C' : 0, 'C#': 1, 'Db': 1, - 'D' : 2, 'D#': 3, 'Eb': 3, 'E' : 4, - 'Fb': 4, 'E#': 5, 'F' : 5, 'F#': 6, - 'Gb': 6, 'G' : 7, 'G#': 8, 'Ab': 8, - 'A' : 9, 'A#': 10,'Bb': 10,'B' : 11, - 'Cb':11 } + pushedLyrics = [] - - def __init__(self): - pass - + transNames = ( ('C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'), + ('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B')) - def setting(self): - """ Called from macro. """ + transKey = 0 # 0==flat, 1=sharp - a="Event=" - - if self.textev: a+="Text" - else: a+="Lyric" - - a+=" Split=" - if self.barsplit: a+="Bar" - else: a+="Normal" - - a += " Verse=%s" % self.versenum - - a += " Chords=" - if self.dupchords: a+="On" - else: a+="Off" - - a += " Transpose=%s" % self.transpose - - a += " CNames=" - if self.transKey: a+="Sharp" - else: a+="Flat" - - return a - - - def option(self, ln): - """ Set a lyric option. """ - - for i, l in enumerate(ln): - l=l.upper() - - # Single word options - - if l.upper()=="SET": - - if i>=len(ln): - s='' - else: - s=' '.join(ln[i+1:]).strip() - - if not s.startswith('['): - s = '[' + s + ']' - - self.pushedLyrics.append(s) - - break - - - # All the rest are OPT=VALUE pairs - - try: - a,v = l.split('=') - except: - error("Lyric options must be in CMD=VALUE pairs.") - - - if a == 'EVENT': - if v == 'TEXT': - self.textev = 1 - warning ("Lyric: Placing lyrics as TEXT EVENTS is not recommended.") - - elif v == 'LYRIC': - self.textev = None - if gbl.debug: - print "Lyric: lyrics set as LYRIC events." - - else: - error("Valid options for Lyric Event are TEXT or LYRIC.") - - - elif a == 'SPLIT': - if v == 'BAR': - self.barsplit = 1 - if gbl.debug: - print "Lyric: lyrics distributed thoughout bar." - - elif v == 'NORMAL': - self.barsplit = None - if gbl.debug: - print "Lyric: lyrics appear as one per bar." - - else: - error("Valid options for Lyric Split are BAR or NORMAL.") - - - elif a == 'VERSE': - if v.isdigit(): - self.versenum = int(v) - - elif v == 'INC': - self.versenum += 1 - - elif v == 'DEC': - self.versenum -= 1 - - else: - error("Valid options of Lyric Verse are or INC or DEC.") - - if self.versenum < 1: - error("Attempt to set Lyric Verse to %s. Values " - "must be > 0." % self.versenum) - - if gbl.debug: - print "Lyric: verse number set to %s" % self.versenum + chordnames={ + 'B#': 0, 'C' : 0, 'C#': 1, 'Db': 1, + 'D' : 2, 'D#': 3, 'Eb': 3, 'E' : 4, + 'Fb': 4, 'E#': 5, 'F' : 5, 'F#': 6, + 'Gb': 6, 'G' : 7, 'G#': 8, 'Ab': 8, + 'A' : 9, 'A#': 10,'Bb': 10,'B' : 11, + 'Cb':11 } - elif a == 'CHORDS': - if v in ('1', 'ON'): - self.dupchords = 1 - if gbl.debug: - print "Lyric: chords are duplicated as lyrics." - - elif v in ('0', 'OFF'): - self.dupchords = 0 - if gbl.debug: - print "Lyric: chords are NOT duplicated as lyrics." - - else: - error ("Expecting 'ON' or 'OFF' in Lyric directive, not 'CHORDS=%s'" % v) - - elif a == 'TRANSPOSE': - - v = stoi(v, "Lyric Tranpose expecting value, not %s" % v) - - if v < -12 or v > 12: - error("Lyric Tranpose %s out-of-range; must be -12..12." % v) - - self.transpose = v - - elif a == 'CNAMES': - - if v in ('#', 'SHARP'): - self.transKey = 1 - elif v in ('B', '&', 'FLAT'): - self.transKey = 0 - - else: - error("Lyric CNames expecting 'Sharp' or 'Flat', not '%s'" % v ) - - else: - error("Usage: Lyric expecting EVENT, SPLIT, VERSE, CHORDS, TRANSPOSE, CNAMES or SET, " - "not '%s'" % a ) + def __init__(self): + pass - - + def setting(self): + """ Called from macro. """ - def leftovers(self): - """ Just report leftovers on stack.""" - - if self.pushedLyrics: - warning("Lyrics remaining on stack.") + a="Event=" - - def extract(self, ln, rpt): - """ Extract lyric info from a chord line and place in META track. - - Returns line and lyric as 2 strings. + if self.textev: a+="Text" + else: a+="Lyric" - The lyric is returned for debugging purposes, but it has been - processed and inserted into the MIDI track. - """ - - a=ln.count('[') - b=ln.count(']') - - if a != b: - error("Mismatched []s for lyrics found in chord line.") - - if self.pushedLyrics: - if a or b: - error("Lyrics not permitted inline and as LYRIC SET") + a+=" Split=" + if self.barsplit: a+="Bar" + else: a+="Normal" - - ln = ln + self.pushedLyrics.pop(0) - a=b=1 # flag that we have lyrics, count really doesn't matter - - - if rpt > 1: - if self.dupchords: - error("Chord to lyrics not supported with bar repeat.") - elif a or b: - error("Bars with both repeat count and lyrics are not permitted.") + a += " Verse=%s" % self.versenum + + a += " Chords=" + if self.dupchords: a+="On" + else: a+="Off" + + a += " Transpose=%s" % self.transpose + + a += " CNames=" + if self.transKey: a+="Sharp" + else: a+="Flat" + + return a - ln, lyrics = pextract(ln, '[', ']') - + def option(self, ln): + """ Set a lyric option. """ - """ If the CHORDS=ON option is set, make a copy of the chords and - insert as lyric. This permits illegal chord lines, but they will - be caught by the parser. - """ - - if self.dupchords: - ly = [] - - for v in ln.split(): - v = v.replace('&', 'b') - if v == 'z': - v = 'N.C.' - if 'z' in v: - v = v.split('z')[0] - while v.startswith('-'): - v=v[1:] - while v.startswith('+'): - v=v[1:] + for i, l in enumerate(ln): + l=l.upper() - if self.transpose: - tr=0 # Needed in case line is invalid! - cn=v[0:2] - if self.chordnames.has_key(cn): - tr=self.chordnames[cn] + self.transpose - - else: - cn=v[0:1] - if self.chordnames.has_key(cn): - tr=self.chordnames[cn] + self.transpose + # Single word options - while tr>=12: tr-=12 - while tr<=-12: tr+=12 + if l.upper()=="SET": - if tr: - v = self.transNames[self.transKey][tr] + v[len(cn):] + if i>=len(ln): + s='' + else: + s=' '.join(ln[i+1:]).strip() - - ly.append(v) + if not s.startswith('['): + s = '[' + s + ']' - i=gbl.QperBar - len(ly) - if i>0: - ly.extend( ['/'] * i ) - lyrics.insert(0, ' '.join(ly) + '\\r') + self.pushedLyrics.append(s) + + break - v=self.versenum - - if len(lyrics) == 1: - v=1 + # All the rest are OPT=VALUE pairs - if v > len(lyrics): - lyrics = '' - else: - lyrics=lyrics[v-1] - - if not len(lyrics): - return (ln, []) + try: + a,v = l.split('=') + except: + error("Lyric options must be in CMD=VALUE pairs") - lyrics=lyrics.replace('\\r', ' \\r ') - lyrics=lyrics.replace('\\n', ' \\n ') - lyrics=lyrics.replace(' ', ' ') - if self.barsplit: - lyrics = [lyrics] - else: - lyrics = lyrics.split() + if a == 'EVENT': + if v == 'TEXT': + self.textev = 1 + warning ("Lyric: Placing lyrics as TEXT EVENTS is not recommended") - beat = 0 - bstep = gbl.QperBar / float(len(lyrics)) + elif v == 'LYRIC': + self.textev = None + if gbl.debug: + print "Lyric: lyrics set as LYRIC events." - - for t, a in enumerate(lyrics): - a,b = pextract(a, '<', '>', 1) + else: + error("Valid options for Lyric Event are TEXT or LYRIC") - if b and b[0]: - beat = stof(b[0], "Expecting value in <%s> in lyric." % b) - if beat < 1 or beat > gbl.QperBar+1: - error("Offset in lyric <> must be 1 to %s." % gbl.QperBar) - beat -= 1 - bstep = (gbl.QperBar-beat)/float((len(lyrics)-t)) - a = a.replace('\\r', '\r') - a = a.replace('\\n', '\n') + elif a == 'SPLIT': + if v == 'BAR': + self.barsplit = 1 + if gbl.debug: + print "Lyric: lyrics distributed thoughout bar." - if a and a != ' ': - if not a.endswith('-'): - a += ' ' - - p=getOffset(beat * gbl.BperQ) - if self.textev: - gbl.mtrks[0].addText(p, a) - else: - gbl.mtrks[0].addLyric(p, a) + elif v == 'NORMAL': + self.barsplit = None + if gbl.debug: + print "Lyric: lyrics appear as one per bar." + + else: + error("Valid options for Lyric Split are BAR or NORMAL") + + + elif a == 'VERSE': + if v.isdigit(): + self.versenum = int(v) + + elif v == 'INC': + self.versenum += 1 + + elif v == 'DEC': + self.versenum -= 1 + + else: + error("Valid options of Lyric Verse are or INC or DEC") + + if self.versenum < 1: + error("Attempt to set Lyric Verse to %s. Values " + "must be > 0" % self.versenum) + + if gbl.debug: + print "Lyric: verse number set to %s" % self.versenum + + + elif a == 'CHORDS': + if v in ('1', 'ON'): + self.dupchords = 1 + if gbl.debug: + print "Lyric: chords are duplicated as lyrics." + + elif v in ('0', 'OFF'): + self.dupchords = 0 + if gbl.debug: + print "Lyric: chords are NOT duplicated as lyrics." + + else: + error ("Expecting 'ON' or 'OFF' in Lyric directive, not 'CHORDS=%s'" % v) + + elif a == 'TRANSPOSE': + + v = stoi(v, "Lyric Tranpose expecting value, not %s" % v) + + if v < -12 or v > 12: + error("Lyric Tranpose %s out-of-range; must be -12..12" % v) + + self.transpose = v + + elif a == 'CNAMES': + + if v in ('#', 'SHARP'): + self.transKey = 1 + elif v in ('B', '&', 'FLAT'): + self.transKey = 0 + + else: + error("Lyric CNames expecting 'Sharp' or 'Flat', not '%s'" % v ) + + else: + error("Usage: Lyric expecting EVENT, SPLIT, VERSE, CHORDS, TRANSPOSE, CNAMES or SET, " + "not '%s'" % a ) + + + + + + def leftovers(self): + """ Just report leftovers on stack.""" + + if self.pushedLyrics: + warning("Lyrics remaining on stack") + + + def extract(self, ln, rpt): + """ Extract lyric info from a chord line and place in META track. + + Returns line and lyric as 2 strings. + + The lyric is returned for debugging purposes, but it has been + processed and inserted into the MIDI track. + """ + + a=ln.count('[') + b=ln.count(']') + + if a != b: + error("Mismatched []s for lyrics found in chord line") + + if self.pushedLyrics: + if a or b: + error("Lyrics not permitted inline and as LYRIC SET") + + + ln = ln + self.pushedLyrics.pop(0) + a=b=1 # flag that we have lyrics, count really doesn't matter + + + if rpt > 1: + if self.dupchords: + error("Chord to lyrics not supported with bar repeat") + elif a or b: + error("Bars with both repeat count and lyrics are not permitted") + + + ln, lyrics = pextract(ln, '[', ']') + + + """ If the CHORDS=ON option is set, make a copy of the chords and + insert as lyric. This permits illegal chord lines, but they will + be caught by the parser. + """ + + if self.dupchords: + ly = [] + + for v in ln.split(): + v = v.replace('&', 'b') + if v == 'z': + v = 'N.C.' + if 'z' in v: + v = v.split('z')[0] + while v.startswith('-'): + v=v[1:] + while v.startswith('+'): + v=v[1:] + + if self.transpose: + tr=0 # Needed in case line is invalid! + cn=v[0:2] + if self.chordnames.has_key(cn): + tr=self.chordnames[cn] + self.transpose + + else: + cn=v[0:1] + if self.chordnames.has_key(cn): + tr=self.chordnames[cn] + self.transpose + + while tr>=12: tr-=12 + while tr<=-12: tr+=12 + + if tr: + v = self.transNames[self.transKey][tr] + v[len(cn):] + + + ly.append(v) + + i=gbl.QperBar - len(ly) + if i>0: + ly.extend( ['/'] * i ) + lyrics.insert(0, ' '.join(ly) + '\\r') + + + v=self.versenum + + if len(lyrics) == 1: + v=1 + + if v > len(lyrics): + lyrics = '' + else: + lyrics=lyrics[v-1] + + if not len(lyrics): + return (ln, []) + + lyrics=lyrics.replace('\\r', ' \\r ') + lyrics=lyrics.replace('\\n', ' \\n ') + lyrics=lyrics.replace(' ', ' ') + + if self.barsplit: + lyrics = [lyrics] + else: + lyrics = lyrics.split() + + beat = 0 + bstep = gbl.QperBar / float(len(lyrics)) + + + for t, a in enumerate(lyrics): + a,b = pextract(a, '<', '>', 1) + + if b and b[0]: + beat = stof(b[0], "Expecting value in <%s> in lyric" % b) + if beat < 1 or beat > gbl.QperBar+1: + error("Offset in lyric <> must be 1 to %s" % gbl.QperBar) + beat -= 1 + bstep = (gbl.QperBar-beat)/float((len(lyrics)-t)) + + a = a.replace('\\r', '\r') + a = a.replace('\\n', '\n') + + if a and a != ' ': + if not a.endswith('-'): + a += ' ' + + p=getOffset(beat * gbl.BperQ) + if self.textev: + gbl.mtrks[0].addText(p, a) + else: + gbl.mtrks[0].addLyric(p, a) + + beat += bstep + + return (ln, lyrics) - beat += bstep - - return (ln, lyrics) - # Create a single instance of the Lyric Class. diff --git a/mma/MMA/macro.py b/mma/MMA/macro.py index 9978c26..91eab54 100644 --- a/mma/MMA/macro.py +++ b/mma/MMA/macro.py @@ -19,11 +19,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel The macros are stored, set and parsed in this single-instance class. At the top of MMAparse an instance in created with -something like: macros=MMMmacros.Macros(). +something like: macros=MMMmacros.Macros(). """ import gbl @@ -33,6 +33,7 @@ import MMA.midiC import MMA.lyric import MMA.translate import MMA.patSolo +import MMA.patAria import MMA.volume import MMA.notelen @@ -41,634 +42,655 @@ import random class Macros: - vars={} # storage - expandMode = 1 # flag for variable expansion - pushstack = [] + vars={} # storage + expandMode = 1 # flag for variable expansion + pushstack = [] - def __init__(self): + def __init__(self): - self.vars={} + self.vars={} - def stackValue(self, s): - self.pushstack.append(' '.join(s)) + def clear(self, ln): + if ln: + error("VarClear does not take an argument.") + self.vars={} + if gbl.debug: + print "All variable definitions cleared." + def stackValue(self, s): + self.pushstack.append(' '.join(s)) - def sysvar(self, s): - """ Create an internal macro. """ - # Simple/global system values + def sysvar(self, s): + """ Create an internal macro. """ - if s == 'KEYSIG': - a=MMA.patSolo.keySig.kSig - if a >= 0: - f='#' - else: - f='b' - return "%s%s" % (abs(a), f) + # Simple/global system values - elif s == 'TIME': - return str(gbl.QperBar) + if s == 'KEYSIG': + a=MMA.patSolo.keySig.kSig + if a >= 0: + f='#' + else: + f='b' + return "%s%s" % (abs(a), f) - elif s == 'TEMPO': - return str(gbl.tempo) + elif s == 'TIME': + return str(gbl.QperBar) - elif s == 'VOLUME': - return str(int(MMA.volume.volume * 100)) # INT() is important + elif s == 'TEMPO': + return str(gbl.tempo) - elif s == 'VOLUMERATIO': - return str((MMA.volume.vTRatio * 100)) + elif s == 'VOLUME': + return str(int(MMA.volume.volume * 100)) # INT() is important - elif s == 'LASTVOLUME': - return str(int(MMA.volume.lastVolume * 100)) + elif s == 'VOLUMERATIO': + return str((MMA.volume.vTRatio * 100)) - elif s == 'GROOVE': - return gbl.currentGroove + elif s == 'LASTVOLUME': + return str(int(MMA.volume.lastVolume * 100)) - elif s == 'LASTGROOVE': - return gbl.lastGroove + elif s == 'GROOVE': + return gbl.currentGroove - elif s == 'SEQRND': - if gbl.seqRnd[0] == 0: return "Off" - if gbl.seqRnd[0] == 1: return "On" - return ' '.join(gbl.seqRnd[1:]) + elif s == 'LASTGROOVE': + return gbl.lastGroove - elif s == 'SEQSIZE': - return str(gbl.seqSize) + elif s == 'SEQRND': + if gbl.seqRnd[0] == 0: return "Off" + if gbl.seqRnd[0] == 1: return "On" + return ' '.join(gbl.seqRnd[1:]) - elif s == 'SWINGMODE': - if gbl.swingMode: - a = "On" - else: - a = "Off" - return "%s Skew=%s" % (a, gbl.swingSkew) + elif s == 'SEQSIZE': + return str(gbl.seqSize) - elif s == 'TRANSPOSE': - return str(gbl.transpose) + elif s == 'SWINGMODE': + if gbl.swingMode: + a = "On" + else: + a = "Off" + return "%s Skew=%s" % (a, gbl.swingSkew) - elif s == 'STACKVALUE': - if not self.pushstack: - error( "Empty push/pull variable stack.") - return self.pushstack.pop() + elif s == 'TRANSPOSE': + return str(gbl.transpose) - elif s == 'DEBUG': - return "Debug=%s Filenames=%s Patterns=%s " \ - "Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \ - (gbl.debug, gbl.showFilenames, gbl.pshow, gbl.seqshow, \ - gbl.showrun, int(not gbl.noWarn), gbl.showExpand) + elif s == 'STACKVALUE': + if not self.pushstack: + error( "Empty push/pull variable stack") + return self.pushstack.pop() + elif s == 'DEBUG': + return "Debug=%s Filenames=%s Patterns=%s " \ + "Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \ + (gbl.debug, gbl.showFilenames, gbl.pshow, gbl.seqshow, \ + gbl.showrun, int(not gbl.noWarn), gbl.showExpand) - elif s == 'LASTDEBUG': - return "Debug=%s Filenames=%s Patterns=%s " \ - "Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \ - (gbl.Ldebug, gbl.LshowFilenames, gbl.Lpshow, gbl.Lseqshow, \ - gbl.Lshowrun, int(not gbl.LnoWarn), gbl.LshowExpand) - elif s == 'VEXPAND': - if self.expandMode: - return "On" - else: - return "Off" + elif s == 'LASTDEBUG': + return "Debug=%s Filenames=%s Patterns=%s " \ + "Sequence=%s Runtime=%s Warnings=%s Expand=%s" % \ + (gbl.Ldebug, gbl.LshowFilenames, gbl.Lpshow, gbl.Lseqshow, \ + gbl.Lshowrun, int(not gbl.LnoWarn), gbl.LshowExpand) - elif s == "MIDISPLIT": - return ' '.join([str(x) for x in MMA.midi.splitChannels]) + elif s == 'VEXPAND': + if self.expandMode: + return "On" + else: + return "Off" - elif s == 'SEQRNDWEIGHT': - return ' '.join([str(x) for x in MMA.parse.seqRndWeight]) + elif s == "MIDISPLIT": + return ' '.join([str(x) for x in MMA.midi.splitChannels]) - elif s == 'AUTOLIBPATH': - return gbl.autoLib + elif s == 'SEQRNDWEIGHT': + return ' '.join([str(x) for x in MMA.parse.seqRndWeight]) - elif s == 'LIBPATH': - return gbl.libPath + elif s == 'AUTOLIBPATH': + return gbl.autoLib - elif s == 'INCPATH': - return gbl.incPath + elif s == 'LIBPATH': + return gbl.libPath - elif s == 'VOICETR': - return MMA.translate.vtable.retlist() + elif s == 'INCPATH': + return gbl.incPath - elif s == 'TONETR': - return MMA.translate.dtable.retlist() + elif s == 'VOICETR': + return MMA.translate.vtable.retlist() - elif s == 'OUTPATH': - return gbl.outPath + elif s == 'TONETR': + return MMA.translate.dtable.retlist() - elif s == 'BARNUM': - return str(gbl.barNum + 1) + elif s == 'OUTPATH': + return gbl.outPath - elif s == 'LINENUM': - return str(gbl.lineno) + elif s == 'BARNUM': + return str(gbl.barNum + 1) - elif s == 'LYRIC': - return MMA.lyric.lyric.setting() + elif s == 'LINENUM': + return str(gbl.lineno) - # Track vars ... these are in format TRACKNAME_VAR + elif s == 'LYRIC': + return MMA.lyric.lyric.setting() - a=s.rfind('_') - if a==-1: - error("Unknown system variable $_%s" % s) + # Track vars ... these are in format TRACKNAME_VAR - tname = s[:a] - func = s[a+1:] + a=s.rfind('_') + if a==-1: + error("Unknown system variable $_%s" % s) - if gbl.tnames.has_key(tname): - t=gbl.tnames[tname] - else: - error("System variable $_%s refers to nonexistent track." % s) + tname = s[:a] + func = s[a+1:] + if gbl.tnames.has_key(tname): + t=gbl.tnames[tname] + else: + error("System variable $_%s refers to nonexistent track" % s) - if func == 'ACCENT': - r=[] - for s in t.accent: - r.append("{") - for b,v in s: - r.append(str((b/gbl.BperQ)+1)) - r.append(str(int(v * 100))) - r.append("}") - return ' '.join(r) - elif func == 'ARTICULATE': - return ' '.join([str(x) for x in t.artic]) + if func == 'ACCENT': + r=[] + for s in t.accent: + r.append("{") + for b,v in s: + r.append(str((b/gbl.BperQ)+1)) + r.append(str(int(v * 100))) + r.append("}") + return ' '.join(r) - elif func == 'CHANNEL': - return str(t.channel) + elif func == 'ARTICULATE': + return ' '.join([str(x) for x in t.artic]) - elif func == 'COMPRESS': - return ' '.join([str(x) for x in t.compress]) + elif func == 'CHANNEL': + return str(t.channel) - elif func == 'DIRECTION': - return ' '.join([str(x) for x in t.direction]) + elif func == 'COMPRESS': + return ' '.join([str(x) for x in t.compress]) - elif func == 'DUPROOT': - if t.vtype != "CHORD": - error("Only CHORD tracks have DUPROOT") - return ' '.join([str(x) for x in t.dupRoot]) + elif func == 'DIRECTION': + if t.vtype == 'ARIA': + return ' '.join([str(x) for x in t.selectDir]) + else: + return ' '.join([str(x) for x in t.direction]) - elif func == 'HARMONY': - return ' '.join([str(x) for x in t.harmony]) + elif func == 'DUPROOT': + if t.vtype != "CHORD": + error("Only CHORD tracks have DUPROOT") + return ' '.join([str(x) for x in t.dupRoot]) - elif func == 'HARMONYVOLUME': - return ' '.join([str(int(a * 100)) for a in t.harmonyVolume]) + elif func == 'HARMONY': + return ' '.join([str(x) for x in t.harmony]) - elif func == 'INVERT': - return ' '.join([str(x) for x in t.invert]) + elif func == 'HARMONYVOLUME': + return ' '.join([str(int(a * 100)) for a in t.harmonyVolume]) - elif func == 'LIMIT': - return str( t.chordLimit ) + elif func == 'INVERT': + return ' '.join([str(x) for x in t.invert]) - elif func == 'MALLET': - if t.vtype not in ("SOLO", "MELODY"): - error("Mallet only valid in SOLO and MELODY tracks.") - return "Mallet Rate=%i Decay=%i" % (t.mallet, t.malletDecay*100) + elif func == 'LIMIT': + return str( t.chordLimit ) - elif func == 'OCTAVE': - return ' '.join([str(a/12) for a in t.octave]) + elif func == 'MALLET': + if t.vtype not in ("SOLO", "MELODY"): + error("Mallet only valid in SOLO and MELODY tracks") + return "Mallet Rate=%i Decay=%i" % (t.mallet, t.malletDecay*100) - elif func == 'RANGE': - return ' '.join([str(x) for x in t.chordRange]) + elif func == 'OCTAVE': + return ' '.join([str(a/12) for a in t.octave]) - elif func == 'RSKIP': - return ' '.join([str(int(a * 100)) for a in t.rSkip]) + elif func == 'RANGE': + return ' '.join([str(x) for x in t.chordRange]) - elif func == 'RTIME': - return ' '.join([str(x) for x in t.rTime]) + elif func == 'RSKIP': + return ' '.join([str(int(a * 100)) for a in t.rSkip]) - elif func == 'RVOLUME': - return ' '.join([str(int(a * 100)) for a in t.rVolume]) + elif func == 'RTIME': + return ' '.join([str(x) for x in t.rTime]) - elif func == 'SEQRND': - if t.seqRnd: return 'On' - else: return 'Off' + elif func == 'RVOLUME': + return ' '.join([str(int(a * 100)) for a in t.rVolume]) - elif func == 'SEQRNDWEIGHT': - return ' '.join([str(x) for x in t.seqRndWeight]) + elif func == 'SEQRND': + if t.seqRnd: return 'On' + else: return 'Off' - elif func == 'SPAN': - return "%s %s" % (t.spanStart, t.spanEnd) + elif func == 'SEQRNDWEIGHT': + return ' '.join([str(x) for x in t.seqRndWeight]) - elif func == 'STRUM': - if t.vtype != "CHORD": - error("Only CHORD tracks have STRUM") - return ' '.join([str(x) for x in t.strum]) + elif func == 'SPAN': + return "%s %s" % (t.spanStart, t.spanEnd) - elif func == 'TONE': - if t.vtype != "DRUM": - error("Only DRUM tracks have TONE") - return ' '.join([MMA.midiC.valueToDrum(a) for a in t.toneList]) + elif func == 'STRUM': + if t.vtype != "CHORD": + error("Only CHORD tracks have STRUM") + return ' '.join([str(x) for x in t.strum]) - elif func == 'UNIFY': - return ' '.join([str(x) for x in t.unify]) + elif func == 'TONE': + if t.vtype != "DRUM": + error("Only DRUM tracks have TONE") + return ' '.join([MMA.midiC.valueToDrum(a) for a in t.toneList]) - elif func == 'VOICE': - return ' '.join([MMA.midiC.voiceNames[a] for a in t.voice]) + elif func == 'UNIFY': + return ' '.join([str(x) for x in t.unify]) - elif func == 'VOICING': - if t.vtype != 'CHORD': - error("Only CHORD tracks have VOICING") - t=t.voicing - return "Mode=%s Range=%s Center=%s RMove=%s Move=%s Dir=%s" % \ - (t.mode, t.range, t.center, t.random, t.bcount, t.dir) + elif func == 'VOICE': + return ' '.join([MMA.midiC.voiceNames[a] for a in t.voice]) - elif func == 'VOLUME': - return ' '.join([str(int(a * 100)) for a in t.volume]) + elif func == 'VOICING': + if t.vtype != 'CHORD': + error("Only CHORD tracks have VOICING") + t=t.voicing + return "Mode=%s Range=%s Center=%s RMove=%s Move=%s Dir=%s" % \ + (t.mode, t.range, t.center, t.random, t.bcount, t.dir) - else: - error("Unknown system track variable %s." % s) + elif func == 'VOLUME': + return ' '.join([str(int(a * 100)) for a in t.volume]) + else: + error("Unknown system track variable %s" % s) - def expand(self, l): - """ Loop though input line and make variable subsitutions. - MMA variables are pretty simple ... any word starting - with a "$xxx" is a variable. - l - list + def expand(self, l): + """ Loop though input line and make variable subsitutions. + MMA variables are pretty simple ... any word starting + with a "$xxx" is a variable. - RETURNS: new list with all subs done. - """ + l - list - if not self.expandMode: - return l + RETURNS: new list with all subs done. + """ - while 1: # Loop until no more subsitutions have been done - sub=0 - for i,s in enumerate(l): - if s[:2] == '$$': - continue + if not self.expandMode: + return l - if s[0]=='$': - s=s[1:].upper() + while 1: # Loop until no more subsitutions have been done + sub=0 + for i,s in enumerate(l): + if s[:2] == '$$': + continue - if s.startswith('_'): - ex=self.sysvar(s[1:]) + if s[0]=='$': + s=s[1:].upper() - elif not s in self.vars: - error("User variable '%s' has not been defined." % s ) + if s.startswith('_'): + ex=self.sysvar(s[1:]) - else: - ex=self.vars[s] + elif not s in self.vars: + error("User variable '%s' has not been defined" % s ) - if type(ex) == type([]): # MSET variable - if len(ex): - gbl.inpath.push( ex[1:], [gbl.lineno] * len(ex[1:])) - if len(ex): - ex=ex[0] - else: - ex=[] - else: # regular SET variable - ex=ex.split() + else: + ex=self.vars[s] - l=l[:i] + ex + l[i+1:] # ex might be a list, so this is needed - sub=1 - break + if type(ex) == type([]): # MSET variable + if len(ex): + gbl.inpath.push( ex[1:], [gbl.lineno] * len(ex[1:])) + if len(ex): + ex=ex[0] + else: + ex=[] + else: # regular SET variable + ex=ex.split() - if not sub: - break + l=l[:i] + ex + l[i+1:] # ex might be a list, so this is needed + sub=1 + break - return l + if not sub: + break + return l - def showvars(self, ln): - """ Display all currently defined variables. """ - if len(ln): - for a in ln: - a=a.upper() - if a in self.vars: - print "$%s: %s" % (a, self.vars[a]) - else: - print "$%s - not defined" % a + def showvars(self, ln): + """ Display all currently defined variables. """ - else: + if len(ln): + for a in ln: + a=a.upper() + if a in self.vars: + print "$%s: %s" % (a, self.vars[a]) + else: + print "$%s - not defined" % a - print "User variables defined:" - kys = self.vars.keys() - kys.sort() + else: - mx = 0 + print "User variables defined:" + kys = self.vars.keys() + kys.sort() - for a in kys: # get longest name - if len(a) > mx: - mx = len(a) + mx = 0 - mx = mx + 2 + for a in kys: # get longest name + if len(a) > mx: + mx = len(a) - for a in kys: - print " %-*s %s" % (mx, '$'+a, self.vars[a]) + mx = mx + 2 - def getvname(self, v): - """ Helper routine to validate variable name. """ + for a in kys: + print " %-*s %s" % (mx, '$'+a, self.vars[a]) - if v[0] in ('$', '_'): - error("Variable names cannot start with a '$' or '_'.") - return v.upper() + def getvname(self, v): + """ Helper routine to validate variable name. """ - def rndvar(self, ln): - """ Set a variable randomly from a list. """ + if v[0] in ('$', '_'): + error("Variable names cannot start with a '$' or '_'") + return v.upper() - if len(ln) < 2: - error("Use: RndSet Variable_Name ") + def rndvar(self, ln): + """ Set a variable randomly from a list. """ - v = self.getvname(ln[0]) + if len(ln) < 2: + error("Use: RndSet Variable_Name ") - self.vars[v] = random.choice(ln[1:]) + v = self.getvname(ln[0]) - if gbl.debug: - print "Variable $%s randomly set to '%s'" % (v, self.vars[v]) + self.vars[v] = random.choice(ln[1:]) - def setvar(self, ln): - """ Set a variable. Not the difference between the next 2 lines: - Set Bar BAR - Set Foo AAA BBB $bar - $Foo == "AAA BBB BAR" - Set Foo AAA + BBB + $bar - $Foo == "AAABBBBAR" + if gbl.debug: + print "Variable $%s randomly set to '%s'" % (v, self.vars[v]) - The "+"s just strip out interveing spaces. - """ + def newsetvar(self, ln): + """ Set a new variable. Ignore if already set. """ - if len(ln) < 1: - error("Use: SET VARIABLE_NAME [Value] [[+] [Value]]") + if not len(ln): + error("Use: NSET VARIABLE_NAME [Value] [[+] [Value]]") - v=self.getvname(ln.pop(0)) + if self.getvname(ln[0]) in self.vars: + return - t='' - addSpace = 0 - for i,a in enumerate(ln): - if a == '+': - addSpace = 0 - continue - else: - if addSpace: - t += ' ' - t += a - addSpace = 1 + self.setvar(ln) + def setvar(self, ln): + """ Set a variable. Not the difference between the next 2 lines: + Set Bar BAR + Set Foo AAA BBB $bar + $Foo == "AAA BBB BAR" + Set Foo AAA + BBB + $bar + $Foo == "AAABBBBAR" - self.vars[v]=t + The "+"s just strip out interveing spaces. + """ - if gbl.debug: - print "Variable $%s == '%s'" % (v, self.vars[v]) + if len(ln) < 1: + error("Use: SET VARIABLE_NAME [Value] [[+] [Value]]") + v=self.getvname(ln.pop(0)) - def msetvar(self, ln): - """ Set a variable to a number of lines. """ + t='' + addSpace = 0 + for i,a in enumerate(ln): + if a == '+': + addSpace = 0 + continue + else: + if addSpace: + t += ' ' + t += a + addSpace = 1 - if len(ln) !=1: - error("Use: MSET VARIABLE_NAME MsetEnd") - v=self.getvname(ln[0]) + self.vars[v]=t - lm=[] + if gbl.debug: + print "Variable $%s == '%s'" % (v, self.vars[v]) - while 1: - l=gbl.inpath.read() - if not l: - error("Reached EOF while looking for MSetEnd") - cmd=l[0].upper() - if cmd in ("MSETEND", 'ENDMSET'): - if len(l) > 1: - error("No arguments permitted for MSetEnd/EndMSet") - else: - break - lm.append(l) - self.vars[v]=lm + def msetvar(self, ln): + """ Set a variable to a number of lines. """ + if len(ln) !=1: + error("Use: MSET VARIABLE_NAME MsetEnd") - def unsetvar(self, ln): - """ Delete a variable reference. """ + v=self.getvname(ln[0]) + lm=[] - if len(ln) != 1: - error("Use: UNSET Variable") - v=ln[0].upper() - if v[0] == '_': - error("Internal variables cannot be deleted or modified.") + while 1: + l=gbl.inpath.read() + if not l: + error("Reached EOF while looking for MSetEnd") + cmd=l[0].upper() + if cmd in ("MSETEND", 'ENDMSET'): + if len(l) > 1: + error("No arguments permitted for MSetEnd/EndMSet") + else: + break + lm.append(l) - if v in self.vars: - del(macros.vars[v]) + self.vars[v]=lm - if gbl.debug: - print "Variable '%s' UNSET" % v - else: - warning("Attempt to UNSET nonexistent variable '%s'." % v) + def unsetvar(self, ln): + """ Delete a variable reference. """ - def vexpand(self, ln): - if len(ln) == 1: - cmd = ln[0].upper() - else: - cmd='' + if len(ln) != 1: + error("Use: UNSET Variable") + v=ln[0].upper() + if v[0] == '_': + error("Internal variables cannot be deleted or modified") - if cmd == 'ON': - self.expandMode=1 - if gbl.debug: - print "Variable expansion ON" + if v in self.vars: + del(macros.vars[v]) - elif cmd == 'OFF': - self.expandMode=0 - if gbl.debug: - print "Variable expansion OFF" + if gbl.debug: + print "Variable '%s' UNSET" % v + else: + warning("Attempt to UNSET nonexistent variable '%s'" % v) - else: - error("Use: Vexpand ON/Off.") + def vexpand(self, ln): - def varinc(self, ln): - """ Increment a variable. """ + if len(ln) == 1: + cmd = ln[0].upper() + else: + cmd='' - if len(ln) == 1: - inc=1 + if cmd == 'ON': + self.expandMode=1 + if gbl.debug: + print "Variable expansion ON" - elif len(ln) == 2: - inc = stof(ln[1], "Expecting a value (not %s) for Inc." % ln[1]) + elif cmd == 'OFF': + self.expandMode=0 + if gbl.debug: + print "Variable expansion OFF" - else: - error("Usage: INC Variable [value]") + else: + error("Use: Vexpand ON/Off") - v=ln[0].upper() - if v[0] == '_': - error("Internal variables cannot be modified.") + def varinc(self, ln): + """ Increment a variable. """ - if not v in self.vars: - error("Variable '%s' not defined" % v) + if len(ln) == 1: + inc=1 - vl=stoi(self.vars[v], "Variable must be a value to increment.") + inc + elif len(ln) == 2: + inc = stof(ln[1], "Expecting a value (not %s) for Inc" % ln[1]) - if vl == int(vl): - vl = int(vl) - self.vars[v]=str(vl) + else: + error("Usage: INC Variable [value]") - if gbl.debug: - print "Variable '%s' INC to %s" % (v, self.vars[v]) + v=ln[0].upper() + if v[0] == '_': + error("Internal variables cannot be modified") - def vardec(self, ln): - """ Decrement a varaiable. """ + if not v in self.vars: + error("Variable '%s' not defined" % v) - if len(ln) == 1: - dec = 1 + vl=stoi(self.vars[v], "Variable must be a value to increment") + inc - elif len(ln) == 2: - dec = stof(ln[1], "Expecting a value (not %s) for Inc." % ln[1]) + if vl == int(vl): + vl = int(vl) + self.vars[v]=str(vl) - else: - error("Usage: DEC Variable [value]") + if gbl.debug: + print "Variable '%s' INC to %s" % (v, self.vars[v]) - v=ln[0].upper() - if v[0] == '_': - error("Internal variables cannot be modified.") - if not v in self.vars: - error("Variable '%s' not defined" % v) + def vardec(self, ln): + """ Decrement a varaiable. """ - vl=stoi(self.vars[v], "Variable must be a value to decrement.") - dec + if len(ln) == 1: + dec = 1 - if vl == int(vl): - vl = int(vl) + elif len(ln) == 2: + dec = stof(ln[1], "Expecting a value (not %s) for Inc" % ln[1]) - self.vars[v]=str(vl) + else: + error("Usage: DEC Variable [value]") - if gbl.debug: - print "Variable '%s' DEC to %s" % (v, self.vars[v]) + v=ln[0].upper() + if v[0] == '_': + error("Internal variables cannot be modified") + if not v in self.vars: + error("Variable '%s' not defined" % v) - def varIF(self, ln): - """ Conditional variable if/then. """ + vl=stoi(self.vars[v], "Variable must be a value to decrement") - dec - def expandV(l): - """ Private func. """ + if vl == int(vl): + vl = int(vl) - l=l.upper() + self.vars[v]=str(vl) - if l[:2] == '$$': - l=l[2:] - if not l in self.vars: - error("String Variable '%s' does not exist." % l) - l=self.vars[l] + if gbl.debug: + print "Variable '%s' DEC to %s" % (v, self.vars[v]) - try: - v=float(l) - except: - v=None - return ( l, v ) + def varIF(self, ln): + """ Conditional variable if/then. """ + def expandV(l): + """ Private func. """ - def readblk(): - """ Private, reads a block until ENDIF, IFEND or ELSE. - Return (Terminator, lines[], linenumbers[] ) - """ + l=l.upper() - q=[] - qnum=[] - nesting=0 + if l[:2] == '$$': + l=l[2:] + if not l in self.vars: + error("String Variable '%s' does not exist" % l) + l=self.vars[l] - while 1: - l=gbl.inpath.read() - if not l: - error("EOF reached while looking for EndIf") + try: + v=float(l) + except: + v=None - cmd=l[0].upper() - if cmd == 'IF': - nesting+=1 - if cmd in ("IFEND", 'ENDIF', 'ELSE'): - if len(l) > 1: - error("No arguments permitted for IfEnd/EndIf/Else") - if not nesting: - break - if cmd != 'ELSE': - nesting -= 1 + return ( l, v ) - q.append(l) - qnum.append(gbl.lineno) - return (cmd, q, qnum) + def readblk(): + """ Private, reads a block until ENDIF, IFEND or ELSE. + Return (Terminator, lines[], linenumbers[] ) + """ + q=[] + qnum=[] + nesting=0 - if len(ln)<2: - error("Usage: IF ") + while 1: + l=gbl.inpath.read() + if not l: + error("EOF reached while looking for EndIf") - action = ln[0].upper() + cmd=l[0].upper() + if cmd == 'IF': + nesting+=1 + if cmd in ("IFEND", 'ENDIF', 'ELSE'): + if len(l) > 1: + error("No arguments permitted for IfEnd/EndIf/Else") + if not nesting: + break + if cmd != 'ELSE': + nesting -= 1 - # 1. do the unary options: DEF, NDEF + q.append(l) + qnum.append(gbl.lineno) - if action in ('DEF', 'NDEF'): - if len(ln) != 2: - error("Usage: IF %s VariableName" % action) + return (cmd, q, qnum) - v=ln[1].upper() - retpoint = 2 - if action == 'DEF': - compare = self.vars.has_key(v) - elif action == 'NDEF': - compare = ( not self.vars.has_key(v)) - else: - error("Unreachable unary conditional") + if len(ln)<2: + error("Usage: IF ") + action = ln[0].upper() - # 2. Binary ops: EQ, NE, etc. + # 1. do the unary options: DEF, NDEF - elif action in ('LT', 'LE', 'EQ', 'GE', 'GT', 'NE'): - if len(ln) != 3: - error("Usage: VARS %s Value1 Value2" % action) + if action in ('DEF', 'NDEF'): + if len(ln) != 2: + error("Usage: IF %s VariableName" % action) + v=ln[1].upper() + retpoint = 2 - s1,v1 = expandV(ln[1]) - s2,v2 = expandV(ln[2]) + if action == 'DEF': + compare = self.vars.has_key(v) + elif action == 'NDEF': + compare = ( not self.vars.has_key(v)) + else: + error("Unreachable unary conditional") - if type(v1) == type(1.0) and type(v2) == type(1.0): - s1=v1 - s2=v2 + # 2. Binary ops: EQ, NE, etc. - retpoint = 3 + elif action in ('LT', 'LE', 'EQ', 'GE', 'GT', 'NE'): + if len(ln) != 3: + error("Usage: VARS %s Value1 Value2" % action) - if action == 'LT': - compare = (v1 < v2) - elif action == 'LE': - compare = (v1 <= v2) - elif action == 'EQ': - compare = (v1 == v2) - elif action == 'GE': - compare = (v1 >= v2) - elif action == 'GT': - compare = (v1 > v2) - elif action == 'NE': - compare = (v1 != v2) - else: - error("Unreachable binary conditional") - else: - error("Usage: IF ...") + s1,v1 = expandV(ln[1]) + s2,v2 = expandV(ln[2]) + if type(v1) == type(1.0) and type(v2) == type(1.0): + s1=v1 + s2=v2 - """ Go read until end of if block. - We shove the block back if the compare was true. - Unless, the block is terminated by an ELSE ... then we need - to read another block and push back one of the two. - """ - cmd, q, qnum = readblk() + retpoint = 3 + if action == 'LT': + compare = (v1 < v2) + elif action == 'LE': + compare = (v1 <= v2) + elif action == 'EQ': + compare = (v1 == v2) + elif action == 'GE': + compare = (v1 >= v2) + elif action == 'GT': + compare = (v1 > v2) + elif action == 'NE': + compare = (v1 != v2) + else: + error("Unreachable binary conditional") - if cmd == 'ELSE': - cmd, q1, qnum1 = readblk() + else: + error("Usage: IF ...") - if cmd == 'ELSE': - error("Only one ELSE is permitted in IF construct.") - if not compare: - compare = 1 - q = q1 - qnum = qnum1 + """ Go read until end of if block. + We shove the block back if the compare was true. + Unless, the block is terminated by an ELSE ... then we need + to read another block and push back one of the two. + """ - if compare: - gbl.inpath.push( q, qnum ) + cmd, q, qnum = readblk() + + + if cmd == 'ELSE': + cmd, q1, qnum1 = readblk() + + if cmd == 'ELSE': + error("Only one ELSE is permitted in IF construct") + + if not compare: + compare = 1 + q = q1 + qnum = qnum1 + + if compare: + gbl.inpath.push( q, qnum ) macros = Macros() diff --git a/mma/MMA/main.py b/mma/MMA/main.py index e18cdb6..cb11f3d 100644 --- a/mma/MMA/main.py +++ b/mma/MMA/main.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -47,13 +47,13 @@ import MMA.options MMA.options.opts() """ - LibPath and IncPath are set in MMA.globals. Debug setting isn't set - when the default is done. + LibPath and IncPath are set in MMA.globals. Debug setting isn't set + when the default is done. """ if gbl.debug: - print "Initialization has set LibPath set to", gbl.libPath - print "Initialization has set IncPath set to", gbl.incPath + print "Initialization has set LibPath set to", gbl.libPath + print "Initialization has set IncPath set to", gbl.incPath ####################################### @@ -75,25 +75,25 @@ gbl.docs = 0 rcread=0 -rcfiles = ('mmarc', 'c:\\mma\\mmarc', '~/.mmarc', '/usr/local/etc/mmarc', '/etc/mmarc' ) +rcfiles = ('mmarc', 'c:\\mma\\mmarc', '~/.mmarc', '/usr/local/etc/mmarc', '/etc/mmarc' ) if gbl.mmaRC: - rcfiles = [ gbl.mmaRC ] + rcfiles = [ gbl.mmaRC ] for i in rcfiles: - f = locFile(i, None) - if f: - if gbl.showrun: - print "Reading RC file '%s'" % f - MMA.parse.parseFile(f) - rcread+=1 - break - else: - if gbl.mmaRC: - error("Specified init file '%s' not found." % gbl.mmaRC) + f = locFile(i, None) + if f: + if gbl.showrun: + print "Reading RC file '%s'" % f + MMA.parse.parseFile(f) + rcread+=1 + break + else: + if gbl.mmaRC: + error("Specified init file '%s' not found" % gbl.mmaRC) if not rcread: - gbl.lineno = -1 - warning("No RC file was found or processed") + gbl.lineno = -1 + warning("No RC file was found or processed") gbl.docs = docOption # Restore doc options @@ -104,17 +104,17 @@ gbl.docs = docOption # Restore doc options # Note: This needs to be here, after reading of RC files if gbl.makeGrvDefs: - if gbl.infile: - error("No filename is permitted with the -g option") - from MMA.auto import libUpdate - libUpdate() # update and EXIT + if gbl.infile: + error("No filename is permitted with the -g option") + from MMA.auto import libUpdate + libUpdate() # update and EXIT ################################ # We need an input file for anything after this point. if not gbl.infile: - MMA.options.usage("No input filename specified.") + MMA.options.usage("No input filename specified.") # Add filename to meta track. @@ -124,35 +124,35 @@ gbl.mtrks[0].addText(0, "Input filename: %s" % gbl.infile) # Just extract docs (-Dx) to stdout. if docOption: - f=locFile(gbl.infile, None) - if not f: - error("File '%s' not found." % gbl.infile) - MMA.parse.parseFile(f) - sys.exit(0) + f=locFile(gbl.infile, None) + if not f: + error("File '%s' not found" % gbl.infile) + MMA.parse.parseFile(f) + sys.exit(0) ######################################################### # These cmdline options override settings in RC files if gbl.cmdSMF: - gbl.lineno = -1 - MMA.parse.setMidiFileType(['SMF=%s' % gbl.cmdSMF]) + gbl.lineno = -1 + MMA.parse.setMidiFileType(['SMF=%s' % gbl.cmdSMF]) ########################################## # Create the output filename. # If outfile was specified on cmd line then leave it alone. -# Otherwise ... -# 1. strip off the extension if it is .mma, -# 2. append .mid +# Otherwise ... +# 1. strip off the extension if it is .mma, +# 2. append .mid if gbl.outfile: - outfile = gbl.outfile + outfile = gbl.outfile else: - outfile, ext = os.path.splitext(gbl.infile) - if ext != gbl.ext: - outfile=gbl.infile - outfile += '.mid' + outfile, ext = os.path.splitext(gbl.infile) + if ext != gbl.ext: + outfile=gbl.infile + outfile += '.mid' outfile=os.path.expanduser(outfile) @@ -164,94 +164,94 @@ outfile=os.path.expanduser(outfile) # First the mmastart files for f in gbl.mmaStart: - fn = locFile(f, gbl.incPath) - if not fn: - warning("MmaStart file '%s' not found/processed." % fn) - MMA.parse.parseFile(fn) - gbl.lineno = -1 + fn = locFile(f, gbl.incPath) + if not fn: + warning("MmaStart file '%s' not found/processed" % fn) + MMA.parse.parseFile(fn) + gbl.lineno = -1 # The song file specified on the command line f = locFile(gbl.infile, None) if not f: - gbl.lineno = -1 - error("Input file '%s' not found." % gbl.infile) + gbl.lineno = -1 + error("Input file '%s' not found" % gbl.infile) MMA.parse.parseFile(f) # Finally, the mmaend files for f in gbl.mmaEnd: - fn = locFile(f, None) - if not fn: - warning("MmaEnd file '%s' not found/processed." % f) - MMA.parse.parseFile(fn) + fn = locFile(f, None) + if not fn: + warning("MmaEnd file '%s' not found/processed" % f) + MMA.parse.parseFile(fn) ################################################# # Just display the channel assignments (-c) and exit... if gbl.chshow: - print "\nFile '%s' parsed, but no MIDI file produced!" % gbl.infile - print - print "Tracks allocated:" - k=gbl.tnames.keys() - k.sort() - max=0 - for a in k + gbl.deletedTracks: - if len(a)>max: - max = len(a) - max+=1 - wrap=0 - for a in k: - wrap += max - if wrap>60: - wrap = max - print - print " %-*s" %( max, a), - print - print - if gbl.deletedTracks: - print "Deleted Tracks:" - wrap=0 - for a in gbl.deletedTracks: - wrap += max - if wrap>60: - wrap=max - print - print " %-*s" %( max,a), - print - print - print "Channel assignments:" - for c, n in sorted(gbl.midiAssigns.items()): - if n: - wrap = 3 - print " %2s" % c, - for nn in n: - wrap += max - if wrap>63: - print "\n ", - wrap=max+3 - print "%-*s" % (max,nn), + print "\nFile '%s' parsed, but no MIDI file produced!" % gbl.infile + print + print "Tracks allocated:" + k=gbl.tnames.keys() + k.sort() + max=0 + for a in k + gbl.deletedTracks: + if len(a)>max: + max = len(a) + max+=1 + wrap=0 + for a in k: + wrap += max + if wrap>60: + wrap = max + print + print " %-*s" %( max, a), + print + print + if gbl.deletedTracks: + print "Deleted Tracks:" + wrap=0 + for a in gbl.deletedTracks: + wrap += max + if wrap>60: + wrap=max + print + print " %-*s" %( max,a), + print + print + print "Channel assignments:" + for c, n in sorted(gbl.midiAssigns.items()): + if n: + wrap = 3 + print " %2s" % c, + for nn in n: + wrap += max + if wrap>63: + print "\n ", + wrap=max+3 + print "%-*s" % (max,nn), - print - print - sys.exit(0) + print + print + sys.exit(0) #################################### # Dry run, no output if gbl.noOutput: - warning( "Input file parsed successfully. No midi file generated.") - sys.exit(0) + warning( "Input file parsed successfully. No midi file generated") + sys.exit(0) ############################## # Create the output (MIDI) file -gbl.lineno=-1 # disable line nums for error/warning +gbl.lineno=-1 # disable line nums for error/warning """ We fix the outPath now. This lets you set outpath in the song file. @@ -271,11 +271,11 @@ gbl.lineno=-1 # disable line nums for error/warning """ if (not outfile.startswith('/')) and gbl.outPath and (not gbl.outfile): - if gbl.outPath[0] in '.\\/': - outfile = "%s/%s" % (gbl.outPath, outfile) - else: - head, tail = os.path.split(outfile) - outfile = "%s/%s/%s" % (head, gbl.outPath, tail) + if gbl.outPath[0] in '.\\/': + outfile = "%s/%s" % (gbl.outPath, outfile) + else: + head, tail = os.path.split(outfile) + outfile = "%s/%s/%s" % (head, gbl.outPath, tail) fileExist = os.path.exists(outfile) @@ -285,11 +285,11 @@ fileExist = os.path.exists(outfile) """ for n in gbl.tnames.values(): - if n.channel: - n.doMidiClear() - n.clearPending() - if n.riff: - warning("%s has pending Riff(s)" % n.name) + if n.channel: + n.doMidiClear() + n.clearPending() + if n.riff: + warning("%s has pending Riff(s)" % n.name) """ Check all the tracks and find total number used. When initializing each track (class) we made an initial entry @@ -297,36 +297,36 @@ for n in gbl.tnames.values(): track only has one entry we can safely skip the entire track. """ -trackCount=1 # account for meta track +trackCount=1 # account for meta track -for n in sorted(gbl.mtrks.keys())[1:]: # check all but 0 (meta) - if len(gbl.mtrks[n].miditrk) > 1: - trackCount += 1 +for n in sorted(gbl.mtrks.keys())[1:]: # check all but 0 (meta) + if len(gbl.mtrks[n].miditrk) > 1: + trackCount += 1 if trackCount == 1: # only meta track - if fileExist: - print - print "No data created. Did you remember to set a groove/sequence?" - if fileExist: - print "Existing file '%s' has not been modified." % outfile - sys.exit(1) + if fileExist: + print + print "No data created. Did you remember to set a groove/sequence?" + if fileExist: + print "Existing file '%s' has not been modified." % outfile + sys.exit(1) lyric.leftovers() if fileExist: - print "Overwriting existing", + print "Overwriting existing", else: - print "Creating new", + print "Creating new", print "midi file (%s bars): '%s'" % (gbl.barNum, outfile) try: - out = file(outfile, 'wb') + out = file(outfile, 'wb') except: - error("Can't open file '%s' for writing." % outfile) + error("Can't open file '%s' for writing" % outfile) MMA.midi.writeTracks(out) out.close() if gbl.debug: - print "Completed processing file '%s'." % outfile + print "Completed processing file '%s'." % outfile diff --git a/mma/MMA/mdefine.py b/mma/MMA/mdefine.py index 4772ac6..ebc6028 100644 --- a/mma/MMA/mdefine.py +++ b/mma/MMA/mdefine.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel This class is used to parse lines of MDEFINE and stores the sequences for later recall. @@ -31,58 +31,58 @@ from MMA.common import * import MMA.midiC class Mdefine: - def __init__(self): - self.defs = {} + def __init__(self): + self.defs = {} - def get(self, name): - """ Return a predefine MIDI pattern.""" + def get(self, name): + """ Return a predefine MIDI pattern.""" - try: - return self.defs[name] - except: - error("The MDEFINE pattern %s has not been defined." % name) + try: + return self.defs[name] + except: + error("The MDEFINE pattern %s has not been defined" % name) - def set(self, name, ln): - """ Parse a MDEFINE line. + def set(self, name, ln): + """ Parse a MDEFINE line. - The line must be in the form: + The line must be in the form: - NAME [; ...] + NAME [; ...] - """ + """ - name = name.upper() + name = name.upper() - ln=ln.rstrip('; ') # dump trailing ';' and whitespace - ln = ln.split(';') - evs = [] - for l in ln: - l=l.split() + ln=ln.rstrip('; ') # dump trailing ';' and whitespace + ln = ln.split(';') + evs = [] + for l in ln: + l=l.split() - if len(l) == 1: - evs.extend( self.get(l[0].upper() )) - continue + if len(l) == 1: + evs.extend( self.get(l[0].upper() )) + continue - if len(l) != 3: - error("MDEFINE sequence must have 3 values: Beat, Ctrl, Datum") + if len(l) != 3: + error("MDEFINE sequence must have 3 values: Beat, Ctrl, Datum") - off=stof(l[0], "Value for offset must be integer/float") + off=stof(l[0], "Value for offset must be integer/float") - c=MMA.midiC.ctrlToValue(l[1]) - if c < 0: - c=stoi(l[1]) - if c < 0 or c > 0x7f: - error("Controller values must be 0x00 to 0x7f.") + c=MMA.midiC.ctrlToValue(l[1]) + if c < 0: + c=stoi(l[1]) + if c < 0 or c > 0x7f: + error("Controller values must be 0x00 to 0x7f") - d=stoi(l[2]) - if d < 0 or d > 0x7f: - error("MIDI Control Datum value must be 0x00 to 0x7f.") + d=stoi(l[2]) + if d < 0 or d > 0x7f: + error("MIDI Control Datum value must be 0x00 to 0x7f") - evs.append( [off, chr(c) + chr(d)]) + evs.append( [off, chr(c) + chr(d)]) - self.defs[name]=evs + self.defs[name]=evs mdef = Mdefine() diff --git a/mma/MMA/midi.py b/mma/MMA/midi.py index 5027f83..e3c9fd9 100644 --- a/mma/MMA/midi.py +++ b/mma/MMA/midi.py @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -32,142 +32,142 @@ import MMA.midiC splitChannels = [] def setSplitChannels(ln): - """ Parser routine, sets up list of track to split. Overwrites existing. """ + """ Parser routine, sets up list of track to split. Overwrites existing. """ - global splitChannels + global splitChannels - splitChannels = [] + splitChannels = [] - for a in ln: - c = stoi(a) - if c < 1 or c >16: - error("SplitChannels: Expecting value 1 to 16, not %s." % c) - splitChannels.append(c) + for a in ln: + c = stoi(a) + if c < 1 or c >16: + error("SplitChannels: Expecting value 1 to 16, not %s" % c) + splitChannels.append(c) - if gbl.debug: - print "SplitChannels: ", - printList(splitChannels) + if gbl.debug: + print "SplitChannels: ", + printList(splitChannels) #################### def writeTracks(out): - """ Write the accumulated MIDI tracks to file. """ + """ Write the accumulated MIDI tracks to file. """ - keys=gbl.mtrks.keys() - keys.sort() + keys=gbl.mtrks.keys() + keys.sort() - """ For type 0 MIDI files all data is contained in 1 track. - We take all our tracks and copy them to track 0, then - set up keys[] so that only track 0 remains. - """ + """ For type 0 MIDI files all data is contained in 1 track. + We take all our tracks and copy them to track 0, then + set up keys[] so that only track 0 remains. + """ - if gbl.midiFileType == 0: - trk0=gbl.mtrks[0].miditrk - for n in keys[1:]: - trk=gbl.mtrks[n].miditrk - for k,v in trk.items(): - if k in trk0: - trk0[k].extend(v) - else: - trk0[k]=v - keys=[0] + if gbl.midiFileType == 0: + trk0=gbl.mtrks[0].miditrk + for n in keys[1:]: + trk=gbl.mtrks[n].miditrk + for k,v in trk.items(): + if k in trk0: + trk0[k].extend(v) + else: + trk0[k]=v + keys=[0] - # Write header + # Write header - tcount = len(keys) - out.write( mkHeader(tcount, gbl.BperQ, gbl.midiFileType) ) + tcount = len(keys) + out.write( mkHeader(tcount, gbl.BperQ, gbl.midiFileType) ) - # Write data chunks for each track + # Write data chunks for each track - for n in keys: + for n in keys: - if len(gbl.mtrks[n].miditrk): + if len(gbl.mtrks[n].miditrk): - if gbl.debug: - print "Writing <%s> ch=%s;" % \ - (gbl.mtrks[n].trackname, n), + if gbl.debug: + print "Writing <%s> ch=%s;" % \ + (gbl.mtrks[n].trackname, n), + + if n in splitChannels and gbl.midiFileType: + tcount += writeSplitTrack(n, out) + else: + gbl.mtrks[n].writeMidiTrack(out) - if n in splitChannels and gbl.midiFileType: - tcount += writeSplitTrack(n, out) - else: - gbl.mtrks[n].writeMidiTrack(out) + """ We have increased the track count! So, we need to + fix the file header. This is offset 10/11 which contains + the number of tracks. The counter tcount has been + tracking this, so just seek, replace and seek back. + """ - """ We have increased the track count! So, we need to - fix the file header. This is offset 10/11 which contains - the number of tracks. The counter tcount has been - tracking this, so just seek, replace and seek back. - """ - - if tcount != len(keys): - out.seek(0) - out.write( mkHeader(tcount, gbl.BperQ, gbl.midiFileType) ) - out.seek(0, 2) # return to eof + if tcount != len(keys): + out.seek(0) + out.write( mkHeader(tcount, gbl.BperQ, gbl.midiFileType) ) + out.seek(0, 2) # return to eof def writeSplitTrack(channel, out): - """ Split a drum track into a separate track for the non-note - stuff and then a track for each note. - """ + """ Split a drum track into a separate track for the non-note + stuff and then a track for each note. + """ - tr = gbl.mtrks[channel].miditrk # track to split + tr = gbl.mtrks[channel].miditrk # track to split - """ A dict to store the split midi tracks. We'll end out with - a track for each pitch which appears in the track and - a track (labeled -1) to store every other than note on data. - """ + """ A dict to store the split midi tracks. We'll end out with + a track for each pitch which appears in the track and + a track (labeled -1) to store every other than note on data. + """ - notes={} + notes={} - onEvent = 0x90 + (channel-1) - offEvent = 0x80 + (channel-1) + onEvent = 0x90 + (channel-1) + offEvent = 0x80 + (channel-1) - for offset in tr.keys(): - for x in range(len(tr[offset])-1, -1, -1): - ev = tr[offset][x] - if len(ev) == 3 and ( ord(ev[0]) in (onEvent, offEvent)): - n = ord(ev[1]) - else: - n = -1 # special value for non-note on events + for offset in tr.keys(): + for x in range(len(tr[offset])-1, -1, -1): + ev = tr[offset][x] + if len(ev) == 3 and ( ord(ev[0]) in (onEvent, offEvent)): + n = ord(ev[1]) + else: + n = -1 # special value for non-note on events - if not notes.has_key(n): # create a new mtrk if needed - notes[n]=Mtrk(10) + if not notes.has_key(n): # create a new mtrk if needed + notes[n]=Mtrk(10) - if offset in notes[n].miditrk: # copy event to new track - notes[n].miditrk[offset].append(ev) - else: - notes[n].miditrk[offset]=[ev] + if offset in notes[n].miditrk: # copy event to new track + notes[n].miditrk[offset].append(ev) + else: + notes[n].miditrk[offset]=[ev] - if gbl.debug: - print " Data has been split into %s tracks." % len(notes) + if gbl.debug: + print " Data has been split into %s tracks." % len(notes) - # Insert a channel name in all the new tracks. + # Insert a channel name in all the new tracks. - for a in notes.keys(): - if a == -1: - continue - if channel == 10: - m = "%s" % MMA.midiC.valueToDrum(a) - else: - m= "%s-%s" % (gbl.mtrks[channel].trackname, a) + for a in notes.keys(): + if a == -1: + continue + if channel == 10: + m = "%s" % MMA.midiC.valueToDrum(a) + else: + m= "%s-%s" % (gbl.mtrks[channel].trackname, a) - notes[a].addTrkName(0, m) + notes[a].addTrkName(0, m) - for a in sorted(notes.keys()): - notes[a].writeMidiTrack(out) + for a in sorted(notes.keys()): + notes[a].writeMidiTrack(out) - """ The split tracks have been written. Return the number of additional tracks - so that the caller can properly update the midi file header. Note that - len(notes)-1 IS CORRECT ... we've already figured on writing 1 track. - """ + """ The split tracks have been written. Return the number of additional tracks + so that the caller can properly update the midi file header. Note that + len(notes)-1 IS CORRECT ... we've already figured on writing 1 track. + """ - return len(notes)-1 + return len(notes)-1 def mkHeader(count, tempo, Mtype): - return "MThd" + intToLong(6) + intToWord(Mtype) + \ - intToWord(count) + intToWord(tempo) + return "MThd" + intToLong(6) + intToWord(Mtype) + \ + intToWord(count) + intToWord(tempo) """ Midi track class. All the midi creation is done here. @@ -176,384 +176,394 @@ def mkHeader(count, tempo, Mtype): class Mtrk: - def __init__(self, channel): - self.miditrk={} - self.channel = channel-1 - self.trackname = '' - self.lastEvent = [None] * 129 + def __init__(self, channel): + self.miditrk={} + self.channel = channel-1 + self.trackname = '' + self.lastEvent = [None] * 129 - def delDup(self, offset, cmd): - """Delete a duplicate event. Used by timesig, etc. """ + def delDup(self, offset, cmd): + """Delete a duplicate event. Used by timesig, etc. """ - tr=self.miditrk - lg=len(cmd) - if tr.has_key(offset): - for i,a in enumerate(tr[offset]): - if a[0:lg] == cmd: - del tr[offset][i] + tr=self.miditrk + lg=len(cmd) + if tr.has_key(offset): + for i,a in enumerate(tr[offset]): + if a[0:lg] == cmd: + del tr[offset][i] - def addTimeSig(self, offset, nn, dd, cc, bb): - """ Create a midi time signature. + def addTimeSig(self, offset, nn, dd, cc, bb): + """ Create a midi time signature. - delta - midi delta offset - nn = sig numerator, beats per measure - dd - sig denominator, 2=quarter note, 3=eighth, - cc - midi clocks/tick - bb - # of 32nd notes in quarter (normally 8) + delta - midi delta offset + nn = sig numerator, beats per measure + dd - sig denominator, 2=quarter note, 3=eighth, + cc - midi clocks/tick + bb - # of 32nd notes in quarter (normally 8) - This is only called by timeSig.set(). Don't - call this directly since the timeSig.set() checks for - duplicate settings. - """ + This is only called by timeSig.set(). Don't + call this directly since the timeSig.set() checks for + duplicate settings. + """ - cmd = chr(0xff) + chr(0x58) - self.delDup(offset, cmd) # NEEDED??? - self.addToTrack(offset, cmd + chr(0x04) + \ - chr(nn) + chr(dd) + chr(cc) + chr(bb) ) + cmd = chr(0xff) + chr(0x58) + self.delDup(offset, cmd) # NEEDED??? + self.addToTrack(offset, cmd + chr(0x04) + \ + chr(nn) + chr(dd) + chr(cc) + chr(bb) ) - def addKeySig(self, offset, n, mi): - """ Set the midi key signature. """ + def addKeySig(self, offset, n, mi): + """ Set the midi key signature. """ - cmd = chr(0xff) + chr(0x59) - self.delDup(offset, cmd) - self.addToTrack(offset, cmd + chr(0x02) + chr(n) + chr(mi) ) + cmd = chr(0xff) + chr(0x59) + self.delDup(offset, cmd) + self.addToTrack(offset, cmd + chr(0x02) + chr(n) + chr(mi) ) - def addMarker(self, offset, msg): - """ Create a midi MARKER event.""" + def addMarker(self, offset, msg): + """ Create a midi MARKER event.""" - self.addToTrack(offset, chr(0xff) + chr(0x06) + intToVarNumber(len(msg)) + msg ) + self.addToTrack(offset, chr(0xff) + chr(0x06) + intToVarNumber(len(msg)) + msg ) - def addText(self, offset, msg): - """ Create a midi TextEvent.""" + def addText(self, offset, msg): + """ Create a midi TextEvent.""" - self.addToTrack( offset, chr(0xff) + chr(0x01) + intToVarNumber(len(msg)) + msg ) + self.addToTrack( offset, chr(0xff) + chr(0x01) + intToVarNumber(len(msg)) + msg ) - def addLyric(self, offset, msg): - """ Create a midi lyric event. """ + def addLyric(self, offset, msg): + """ Create a midi lyric event. """ - self.addToTrack( offset, - chr(0xff) + chr(0x05) + intToVarNumber(len(msg)) + msg ) + self.addToTrack( offset, + chr(0xff) + chr(0x05) + intToVarNumber(len(msg)) + msg ) - def addTrkName(self, offset, msg): - """ Creates a midi track name event. """ + def addTrkName(self, offset, msg): + """ Creates a midi track name event. """ - offset = 0 # ignore user offset, always put this at 0 + offset = 0 # ignore user offset, always put this at 0 - self.trackname = msg + self.trackname = msg - cmd = chr(0xff) + chr(0x03) - self.delDup(offset, cmd) - self.addToTrack(offset, cmd + intToVarNumber(len(msg)) + msg ) + cmd = chr(0xff) + chr(0x03) + self.delDup(offset, cmd) + self.addToTrack(offset, cmd + intToVarNumber(len(msg)) + msg ) - def addProgChange( self, offset, program): - """ Create a midi program change. + def addProgChange( self, offset, program): + """ Create a midi program change. - program - midi program + program - midi program - Returns - packed string - """ + Returns - packed string + """ - self.addToTrack(offset, - chr(0xc0 | self.channel) + chr(program) ) + self.addToTrack(offset, + chr(0xc0 | self.channel) + chr(program) ) - def addGlis(self, offset, v): - """ Set the portamento. LowLevel MIDI. + def addGlis(self, offset, v): + """ Set the portamento. LowLevel MIDI. - This does 2 things: - 1. turns portamento on/off, - 2. sets the LSN rate. - """ + This does 2 things: + 1. turns portamento on/off, + 2. sets the LSN rate. + """ - if v == 0: - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x41) + chr(0x00) ) + if v == 0: + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x41) + chr(0x00) ) - else: - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x41) + chr(0x7f) ) - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x05) + chr(v) ) + else: + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x41) + chr(0x7f) ) + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x05) + chr(v) ) - def addPan(self, offset, v): - """ Set the lsb of the pan setting.""" + def addPan(self, offset, v): + """ Set the lsb of the pan setting.""" - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x0a) + chr(v) ) + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x0a) + chr(v) ) - def addCtl(self, offset, l): - """ Add arbitary control sequence to track.""" + def addCtl(self, offset, l): + """ Add arbitary control sequence to track.""" - self.addToTrack(offset, chr(0xb0 | self.channel) + l) + self.addToTrack(offset, chr(0xb0 | self.channel) + l) - def addNoteOff(self, offset): - """ Insert a "All Note Off" into the midi stream. + def addNoteOff(self, offset): + """ Insert a "All Note Off" into the midi stream. - Called from the cutTrack() function. - """ + Called from the cutTrack() function. + """ - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x7b) + chr(0) ) + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x7b) + chr(0) ) - def addChannelVol(self, offset, v): - """ Set the midi channel volume.""" + def addChannelVol(self, offset, v): + """ Set the midi channel volume.""" - self.addToTrack(offset, - chr(0xb0 | self.channel) + chr(0x07) + chr(v) ) + self.addToTrack(offset, + chr(0xb0 | self.channel) + chr(0x07) + chr(v) ) - def addTempo(self, offset, beats): - """ Create a midi tempo meta event. + def addTempo(self, offset, beats): + """ Create a midi tempo meta event. - beats - beats per second + beats - beats per second - Return - packed midi string - """ + Return - packed midi string + """ - cmd = chr(0xff) + chr(0x51) - self.delDup(offset, cmd) - self.addToTrack( offset, cmd + chr(0x03) + intTo3Byte(60000000/beats) ) + cmd = chr(0xff) + chr(0x51) + self.delDup(offset, cmd) + self.addToTrack( offset, cmd + chr(0x03) + intTo3Byte(60000000/beats) ) - def writeMidiTrack(self, out): - """ Create/write the MIDI track. + def writeMidiTrack(self, out): + """ Create/write the MIDI track. - We convert timing offsets to midi-deltas. - """ + We convert timing offsets to midi-deltas. + """ - tr=self.miditrk + tr=self.miditrk - if gbl.debug: - ttl = 0 - lg=1 - for t in tr: - a=len(tr[t]) - if a > lg: - lg = a - ttl += a - print "Unique ts: %s; Ttl events %s; Average ev/ts %.2f" % \ - (len(tr), ttl, float(ttl)/len(tr) ) + """ To every MIDI track we generate we add (if the -0 flag + was set) an on/off beep at offset 0. This makes for + easier sync in multi-tracks. + """ - last = 0 + if gbl.synctick and self.channel >= 0: + self.addToTrack(0, chr(0x90 | self.channel) + chr(80) + chr(90) ) + self.addToTrack(1, chr(0x90 | self.channel) + chr(80) + chr(0) ) + + + if gbl.debug: + ttl = 0 + lg=1 + for t in tr: + a=len(tr[t]) + if a > lg: + lg = a + ttl += a + print "Unique ts: %s; Ttl events %s; Average ev/ts %.2f" % \ + (len(tr), ttl, float(ttl)/len(tr) ) - # Convert all events to MIDI deltas and store in - # the track array/list + last = 0 - tdata=[] # empty track container - lastSts=None # Running status tracker + # Convert all events to MIDI deltas and store in + # the track array/list - for a in sorted(tr.keys()): - delta = a-last - for d in tr[a]: + tdata=[] # empty track container + lastSts=None # Running status tracker - """ Running status check. For each packet compare - the first byte with the first byte of the previous - packet. If it is can be converted to running status - we strip out byte 0. Note that valid running status - byte are 0x80..0xef. 0xfx are system messages - and are note suitable for running status. - """ + for a in sorted(tr.keys()): + delta = a-last + for d in tr[a]: - if len(d) > 1: - if d[0] == lastSts: - d=d[1:] - else: - lastSts = d[0] - s=ord(lastSts) - if s < 0x80 or s > 0xef or not gbl.runningStatus: - lastSts = None + """ Running status check. For each packet compare + the first byte with the first byte of the previous + packet. If it is can be converted to running status + we strip out byte 0. Note that valid running status + byte are 0x80..0xef. 0xfx are system messages + and are note suitable for running status. + """ - tdata.extend( [ intToVarNumber(delta) , d ] ) - delta = 0 - last = a + if len(d) > 1: + if d[0] == lastSts: + d=d[1:] + else: + lastSts = d[0] + s=ord(lastSts) + if s < 0x80 or s > 0xef or not gbl.runningStatus: + lastSts = None - # Add an EOF to the track (included in total track size) + tdata.extend( [ intToVarNumber(delta) , d ] ) + delta = 0 + last = a - tdata.append( intToVarNumber(0)) - tdata.append( chr(0xff) + chr(0x2f) + chr(0x00) ) + # Add an EOF to the track (included in total track size) - tdata = ''.join(tdata) - totsize = len(tdata) + tdata.append( intToVarNumber(0)) + tdata.append( chr(0xff) + chr(0x2f) + chr(0x00) ) - out.write("MTrk") - out.write(intToLong(totsize)) - out.write( tdata ) + tdata = ''.join(tdata) + totsize = len(tdata) + out.write("MTrk") + out.write(intToLong(totsize)) + out.write( tdata ) - def addPairToTrack(self, boffset, startRnd, duration, note, v, unify): - """ Add a note on/off pair to a track. - boffset - offset into current bar - startRnd - rand val start adjustment - duration - note len - note - midi value of note - v - midi velocity - unify - if set attempt to unify/compress on/offs + def addPairToTrack(self, boffset, startRnd, duration, note, v, unify): + """ Add a note on/off pair to a track. - This function tries its best to handle overlapping events. - Easy to show effect with a table of note ON/OFF pairs. Both - events are for the same note pitch. + boffset - offset into current bar + startRnd - rand val start adjustment + duration - note len + note - midi value of note + v - midi velocity + unify - if set attempt to unify/compress on/offs - Offsets | 200 | 300 | 320 | 420 - ---------|--------|--------|-------|-------- - Pair1 | on | | off | - Pair2 | | on | | off + This function tries its best to handle overlapping events. + Easy to show effect with a table of note ON/OFF pairs. Both + events are for the same note pitch. - The logic here will delete the OFF event at 320 and - insert a new OFF at 300. Result is that when playing - Pair1 will turn off at 300 followed by the same note - in Pair2 beginning sounded right after. Why the on/off? - Remember: Velocities may be different! + Offsets | 200 | 300 | 320 | 420 + ---------|--------|--------|-------|-------- + Pair1 | on | | off | + Pair2 | | on | | off - However, if the unify flag is set we should end up with: + The logic here will delete the OFF event at 320 and + insert a new OFF at 300. Result is that when playing + Pair1 will turn off at 300 followed by the same note + in Pair2 beginning sounded right after. Why the on/off? + Remember: Velocities may be different! - Offsets | 200 | 300 | 320 | 420 - ---------|--------|--------|-------|-------- - Pair1 | on | | | - Pair2 | | | | off + However, if the unify flag is set we should end up with: + Offsets | 200 | 300 | 320 | 420 + ---------|--------|--------|-------|-------- + Pair1 | on | | | + Pair2 | | | | off - """ - # Start/end offsets + """ - onOffset = getOffset( boffset, startRnd) - offOffset = onOffset + duration + # Start/end offsets - # ON/OFF events + onOffset = getOffset( boffset, startRnd) + offOffset = onOffset + duration - onEvent = chr(0x90 | self.channel) + chr(note) + chr(v) - offEvent = onEvent[:-1] + chr(0) + # ON/OFF events - """ Check for overlap on last event set for this track and - do some ugly trickry. + onEvent = chr(0x90 | self.channel) + chr(note) + chr(v) + offEvent = onEvent[:-1] + chr(0) - - The noOnFlag is set if we don't want to have the main - routine add in the ON event. This is set when UNIFY is - set and we have an overlap. + """ Check for overlap on last event set for this track and + do some ugly trickry. - - We set F to the stored event time for this note and, - if it's in the same event range as the current event - we loop though the saved events for this track. We are - looking for a NOTE OFF event. + - The noOnFlag is set if we don't want to have the main + routine add in the ON event. This is set when UNIFY is + set and we have an overlap. - - If we get a matching event we then delete it from the - track. This requires 2 statements: one for an event - list with only 1 event, a 2nd for multiple events. + - We set F to the stored event time for this note and, + if it's in the same event range as the current event + we loop though the saved events for this track. We are + looking for a NOTE OFF event. - - If UNIFY is NOT set we insert a NOTE OFF at the current - on time. This replaces the OFF we just deleted. + - If we get a matching event we then delete it from the + track. This requires 2 statements: one for an event + list with only 1 event, a 2nd for multiple events. - - If UNIFY is SET we skip the above step, and we set the - noOnFlag so that the ON event isn't set. + - If UNIFY is NOT set we insert a NOTE OFF at the current + on time. This replaces the OFF we just deleted. - """ + - If UNIFY is SET we skip the above step, and we set the + noOnFlag so that the ON event isn't set. - noOnFlag = None + """ - f=self.lastEvent[note] - if f >= onOffset and f <= offOffset: - tr=self.miditrk - for i in range(len(tr[f])): - if tr[f][i] == offEvent: - if len(tr[f]) == 1: - del(tr[f]) - else: - del(tr[f][i]) - if not unify: - self.addToTrack(onOffset, offEvent) - else: - noOnFlag=1 - break + noOnFlag = None - if not noOnFlag: - self.addToTrack(onOffset, onEvent ) - self.addToTrack(offOffset, offEvent ) + f=self.lastEvent[note] + if f >= onOffset and f <= offOffset: + tr=self.miditrk + for i in range(len(tr[f])): + if tr[f][i] == offEvent: + if len(tr[f]) == 1: + del(tr[f]) + else: + del(tr[f][i]) + if not unify: + self.addToTrack(onOffset, offEvent) + else: + noOnFlag=1 + break - # Save the NOTE OFF time for the next loop. + if not noOnFlag: + self.addToTrack(onOffset, onEvent ) + self.addToTrack(offOffset, offEvent ) - self.lastEvent[note] = offOffset + # Save the NOTE OFF time for the next loop. + self.lastEvent[note] = offOffset - def zapRangeTrack(self, start, end): - """ Clear NoteOn events from track in range: start ... end. - This is called from the fermata function. + def zapRangeTrack(self, start, end): + """ Clear NoteOn events from track in range: start ... end. - We delete the entire event list (3 bytes) from the buffer. This - can result in empty directory enteries, but that isn't a problem. - """ + This is called from the fermata function. - trk=self.miditrk - for a in trk: - if a>=start and a<=end: - for i in range(len(trk[a])-1, -1, -1): - e = trk[a][i] - if len(e)==3 and ord(e[0]) & 0xF0 == 0x90 and ord(e[2]): - del trk[a][i] + We delete the entire event list (3 bytes) from the buffer. This + can result in empty directory enteries, but that isn't a problem. + """ + trk=self.miditrk + for a in trk: + if a>=start and a<=end: + for i in range(len(trk[a])-1, -1, -1): + e = trk[a][i] + if len(e)==3 and ord(e[0]) & 0xF0 == 0x90 and ord(e[2]): + del trk[a][i] - def addToTrack(self, offset, event): - """ Add an event to a track. - MIDI data is saved as created in track structures. - Each track has a miditrk dictionary entry which used - the time offsets and keys and has the various events - as data. Each event is packed string of bytes and - the events are stored as a list in the order they are - created. Our storage looks like: + def addToTrack(self, offset, event): + """ Add an event to a track. - miditrk[123] = [event1, event2, ...] - """ + MIDI data is saved as created in track structures. + Each track has a miditrk dictionary entry which used + the time offsets and keys and has the various events + as data. Each event is packed string of bytes and + the events are stored as a list in the order they are + created. Our storage looks like: - if offset<0: - offset=0 + miditrk[123] = [event1, event2, ...] + """ - tr=self.miditrk + if offset<0: + offset=0 - if offset in tr: - tr[offset].append(event) - else: - tr[offset]=[event] + tr=self.miditrk + + if offset in tr: + tr[offset].append(event) + else: + tr[offset]=[event] class TimeSig: - """ Track and set the current time signature. + """ Track and set the current time signature. - Timesigs are completely optional and are inserted into - the MIDI file by addTimeSig(). MMA routines ignore timesig - settings. - """ + Timesigs are completely optional and are inserted into + the MIDI file by addTimeSig(). MMA routines ignore timesig + settings. + """ - def __init__(self): - """ Initialze to null value, user will never set to this.""" + def __init__(self): + """ Initialze to null value, user will never set to this.""" - self.lastsig = (None,None) + self.lastsig = (None,None) - def set(self, nn, dd): - """ Set timesig. If no change from last value, ignore. """ + def set(self, nn, dd): + """ Set timesig. If no change from last value, ignore. """ - if self.lastsig != (nn, dd): - gbl.mtrks[0].addTimeSig(gbl.tickOffset, nn, dd, 48, 8) - self.lastsig = (nn, dd) + if self.lastsig != (nn, dd): + gbl.mtrks[0].addTimeSig(gbl.tickOffset, nn, dd, 48, 8) + self.lastsig = (nn, dd) - def get(self): - """ Return existing timesig. """ + def get(self): + """ Return existing timesig. """ - return self.lastsig + return self.lastsig timeSig = TimeSig() diff --git a/mma/MMA/midiC.py b/mma/MMA/midiC.py index 16b9aca..4fd4f3a 100644 --- a/mma/MMA/midiC.py +++ b/mma/MMA/midiC.py @@ -18,207 +18,72 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel -This module contains the constant names for the various -MIDI controllers, and conversion routines. +This module contains interface for MIDI constants and conversion routines. """ from MMA.common import * - -""" English names for midi instruments and drums. - - These tables are used by the pattern classes to - convert inst/drum names to midi values and by the - doc routines to print tables. -""" - -# The drum names are valid for tones 27 to 87 - -drumNames=[ - 'HighQ', 'Slap', 'ScratchPush', 'ScratchPull', - 'Sticks', 'SquareClick', 'MetronomeClick', - 'MetronomeBell', 'KickDrum2', 'KickDrum1', - 'SideKick', 'SnareDrum1', 'HandClap', - 'SnareDrum2', 'LowTom2', 'ClosedHiHat', - 'LowTom1', 'PedalHiHat', 'MidTom2', 'OpenHiHat', - 'MidTom1', 'HighTom2', 'CrashCymbal1', - 'HighTom1', 'RideCymbal1', 'ChineseCymbal', - 'RideBell', 'Tambourine', 'SplashCymbal', - 'CowBell', 'CrashCymbal2', 'VibraSlap', - 'RideCymbal2', 'HighBongo', 'LowBongo', - 'MuteHighConga', 'OpenHighConga', 'LowConga', - 'HighTimbale', 'LowTimbale', 'HighAgogo', - 'LowAgogo', 'Cabasa', 'Maracas', - 'ShortHiWhistle', 'LongLowWhistle', 'ShortGuiro', - 'LongGuiro', 'Claves', 'HighWoodBlock', - 'LowWoodBlock', 'MuteCuica', 'OpenCuica', - 'MuteTriangle', 'OpenTriangle', 'Shaker', - 'JingleBell', 'Castanets', 'MuteSudro', - 'OpenSudro' ] - -upperDrumNames = [name.upper() for name in drumNames] - - -voiceNames=[ - 'Piano1', 'Piano2','Piano3', - 'Honky-TonkPiano', 'RhodesPiano', 'EPiano', - 'HarpsiChord', 'Clavinet', 'Celesta', - 'Glockenspiel', 'MusicBox', 'Vibraphone', - 'Marimba', 'Xylophone', 'TubularBells', 'Santur', - 'Organ1', 'Organ2', 'Organ3', 'ChurchOrgan', - 'ReedOrgan', 'Accordion', 'Harmonica', - 'Bandoneon', 'NylonGuitar', 'SteelGuitar', - 'JazzGuitar', 'CleanGuitar', 'MutedGuitar', - 'OverDriveGuitar', 'DistortonGuitar', - 'GuitarHarmonics', 'AcousticBass', - 'FingeredBass', 'PickedBass', 'FretlessBass', - 'SlapBass1', 'SlapBass2', 'SynthBass1', - 'SynthBass2', 'Violin', 'Viola', 'Cello', - 'ContraBass', 'TremoloStrings', - 'PizzicatoString', 'OrchestralHarp', 'Timpani', - 'Strings', 'SlowStrings', 'SynthStrings1', - 'SynthStrings2', 'ChoirAahs', 'VoiceOohs', - 'SynthVox', 'OrchestraHit', 'Trumpet', - 'Trombone', 'Tuba', 'MutedTrumpet', 'FrenchHorn', - 'BrassSection', 'SynthBrass1', 'SynthBrass2', - 'SopranoSax', 'AltoSax', 'TenorSax', - 'BaritoneSax', 'Oboe', 'EnglishHorn', 'Bassoon', - 'Clarinet', 'Piccolo', 'Flute', 'Recorder', - 'PanFlute', 'BottleBlow', 'Shakuhachi', - 'Whistle', 'Ocarina', 'SquareWave', 'SawWave', - 'SynCalliope', 'ChifferLead', 'Charang', - 'SoloVoice', '5thSawWave', 'Bass&Lead', - 'Fantasia', 'WarmPad', 'PolySynth', 'SpaceVoice', - 'BowedGlass', 'MetalPad', 'HaloPad', 'SweepPad', - 'IceRain', 'SoundTrack', 'Crystal', 'Atmosphere', - 'Brightness', 'Goblins', 'EchoDrops', - 'StarTheme', 'Sitar', 'Banjo', 'Shamisen', - 'Koto', 'Kalimba', 'BagPipe', 'Fiddle', 'Shanai', - 'TinkleBell', 'AgogoBells', 'SteelDrums', - 'WoodBlock', 'TaikoDrum', 'MelodicTom1', - 'SynthDrum', 'ReverseCymbal', 'GuitarFretNoise', - 'BreathNoise', 'SeaShore', 'BirdTweet', - 'TelephoneRing', 'HelicopterBlade', - 'Applause/Noise', 'GunShot' ] - - -upperVoiceNames = [name.upper() for name in voiceNames] - -ctrlNames = [ - ### also see: http://www.midi.org/about-midi/table3.shtml - - ### 0-31 Double Precise Controllers - ### MSB (14-bits, 16,384 values) - - 'Bank', 'Modulation', 'Breath', 'Ctrl3', - 'Foot', 'Portamento', 'Data', 'Volume', - 'Balance', 'Ctrl9', 'Pan', 'Expression', - 'Effect1', 'Effect2', 'Ctrl14', 'Ctrl15', - 'General1','General2','General3','General4', - 'Ctrl20', 'Ctrl21', 'Ctrl22', 'Ctrl23', - 'Ctrl24', 'Ctrl25', 'Ctrl26', 'Ctrl27', - 'Ctrl28', 'Ctrl29', 'Ctrl30', 'Ctrl31', - ### 32-63 Double Precise Controllers - ### LSB (14-bits, 16,384 values) - 'BankLSB', 'ModulationLSB', 'BreathLSB', - 'Ctrl35', 'FootLSB', 'PortamentoLSB', - 'DataLSB','VolumeLSB','BalanceLSB', - 'Ctrl41','PanLSB','ExpressionLSB', - 'Effect1LSB', 'Effect2LSB','Ctrl46', 'Ctrl47', - 'General1LSB','General2LSB', 'General3LSB', - 'General4LSB', 'Ctrl52','Ctrl53', 'Ctrl54', - 'Ctrl55', 'Ctrl56', 'Ctrl57', 'Ctrl58', - 'Ctrl59', 'Ctrl60', 'Ctrl61', 'Ctrl62', - 'Ctrl63', - - ### 64-119 Single Precise Controllers - ### (7-bits, 128 values) - - 'Sustain', 'Portamento', 'Sostenuto', - 'SoftPedal', 'Legato', 'Hold2', 'Variation', - 'Resonance', 'ReleaseTime','AttackTime', 'Brightness', - 'DecayTime','VibratoRate','VibratoDepth', 'VibratoDelay', - 'Ctrl79','General5','General6','General7', - 'General8','PortamentoCtrl','Ctrl85','Ctrl86', - 'Ctrl87', 'Ctrl88', 'Ctrl89', 'Ctrl90', - 'Reverb', 'Tremolo', 'Chorus','Detune', - 'Phaser', 'DataInc','DataDec', - 'NonRegLSB', 'NonRegMSB', - 'RegParLSB', 'RegParMSB', - 'Ctrl102','Ctrl103','Ctrl104','Ctrl105', - 'Ctrl106','Ctrl107','Ctrl108','Ctrl109', - 'Ctrl110','Ctrl111','Ctrl112','Ctrl113', - 'Ctrl114','Ctrl115','Ctrl116','Ctrl117', - 'Ctrl118','Ctrl119', - - ### 120-127 Channel Mode Messages - - 'AllSoundsOff','ResetAll', - 'LocalCtrl','AllNotesOff', - 'OmniOff','OmniOn', 'PolyOff','PolyOn' ] - -upperCtrlNames = [name.upper() for name in ctrlNames] - +from MMA.miditables import * def drumToValue(name): - """ Get the value of the drum tone (-1==error). """ + """ Get the value of the drum tone (-1==error). """ - try: - v=int(name, 0) - except: - try: - v = upperDrumNames.index(name.upper()) + 27 - except ValueError: - error("Expecting a valid drum name or value for drum tone, not '%s'" % name) + try: + v=int(name, 0) + except: + try: + v = upperDrumNames.index(name.upper()) + 27 + except ValueError: + error("Expecting a valid drum name or value for drum tone, not '%s'" % name) - if v <0 or v > 127: - error("Note in Drum Tone list must be 0..127, not %s" % v) + if v <0 or v > 127: + error("Note in Drum Tone list must be 0..127, not %s" % v) - return v + return v def instToValue(name): - """ Get the value of the instrument name (-1==error). """ + """ Get the value of the instrument name (-1==error). """ - try: - return upperVoiceNames.index(name.upper()) - except ValueError: - return -1 + try: + return upperVoiceNames.index(name.upper()) + except ValueError: + return -1 def ctrlToValue(name): - """ Get the value of the controler name (-1==error). """ + """ Get the value of the controler name (-1==error). """ - try: - return upperCtrlNames.index(name.upper()) - except ValueError: - return -1 + try: + return upperCtrlNames.index(name.upper()) + except ValueError: + return -1 def valueToInst(val): - """ Get the name of the inst. (or 'ERR'). """ + """ Get the name of the inst. (or 'ERR'). """ - try: - return voiceNames[val] - except IndexError: - return "ERROR" + try: + return voiceNames[val] + except IndexError: + return "ERROR" def valueToDrum(val): - """ Get the name of the drum tone. + """ Get the name of the drum tone. - We return the NAME of the tone, or the original value if there is - no name associated with the value (only value 27 to 86 have names). - """ + We return the NAME of the tone, or the original value if there is + no name associated with the value (only value 27 to 86 have names). + """ - if val<27 or val>86: - return str(val) - else: - return drumNames[val-27] + if val<27 or val>86: + return str(val) + else: + return drumNames[val-27] def valueToCtrl(val): - """ Get the name of the controller (or 'ERR'). """ + """ Get the name of the controller (or 'ERR'). """ - try: - return ctrlNames[val] - except IndexError: - return "ERROR" + try: + return ctrlNames[val] + except IndexError: + return "ERROR" diff --git a/mma/MMA/midiIn.py b/mma/MMA/midiIn.py index 83a68dd..5a9d7ee 100644 --- a/mma/MMA/midiIn.py +++ b/mma/MMA/midiIn.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -38,482 +38,481 @@ offset = 0 # Current pointer into the MIDI file """ Helper functions It might be better to have these - functions setup in midiM.py ... but it's easier just - now to have it here. The main problem is that we are - reading from a buffer and don't know how many bytes to - pass back and forth. + functions setup in midiM.py ... but it's easier just + now to have it here. The main problem is that we are + reading from a buffer and don't know how many bytes to + pass back and forth. """ def mvarlen(): - """ Convert variable length midi value to int. """ + """ Convert variable length midi value to int. """ - global offset + global offset - x=0L - for i in range(4): + x=0L + for i in range(4): - try: - byte=ord(midifile[offset]) - offset += 1 - except: - error("Invalid MIDI file include (varlen->int).") + try: + byte=ord(midifile[offset]) + offset += 1 + except: + error("Invalid MIDI file include (varlen->int)") - if byte < 0x80: - x = ( x << 7 ) + byte - break - else: - x = ( x << 7 ) + ( byte & 0x7f ) + if byte < 0x80: + x = ( x << 7 ) + byte + break + else: + x = ( x << 7 ) + ( byte & 0x7f ) - return int(x) + return int(x) def chars(count): - """ Return 'count' chars from file (updates global pointer). """ + """ Return 'count' chars from file (updates global pointer). """ - global offset + global offset - bytes=midifile[offset:offset+count] - offset+=count - return bytes + bytes=midifile[offset:offset+count] + offset+=count + return bytes def m1i(): - """ Get 1 byte (updates global pointer). """ + """ Get 1 byte (updates global pointer). """ - global offset + global offset - try: - byte = midifile[offset] - offset += 1 - except: - error("Invalid MIDI file include (byte, offset=%s)." % offset) + try: + byte = midifile[offset] + offset += 1 + except: + error("Invalid MIDI file include (byte, offset=%s)" % offset) - return ord(byte) + return ord(byte) def m32i(): - """ Convert 4 bytes to integer. """ + """ Convert 4 bytes to integer. """ - global offset + global offset - x = 0L - for i in range(4): - try: - byte = midifile[offset] - offset += 1 - except: - error("Invalid MIDI file include (i32->int, offset=%s)." % offset) - x = (x << 8) + ord(byte) + x = 0L + for i in range(4): + try: + byte = midifile[offset] + offset += 1 + except: + error("Invalid MIDI file include (i32->int, offset=%s)" % offset) + x = (x << 8) + ord(byte) - return int(x) + return int(x) def m16i(): - """ Convert 2 bytes to integer. """ + """ Convert 2 bytes to integer. """ - global offset + global offset - x = 0L - for i in range(2): - try: - byte = midifile[offset] - offset += 1 - except: - error("Invalid MIDI file include (i16->int, offset=%s)." % offset) - x = (x << 8) + ord(byte) + x = 0L + for i in range(2): + try: + byte = midifile[offset] + offset += 1 + except: + error("Invalid MIDI file include (i16->int, offset=%s)" % offset) + x = (x << 8) + ord(byte) - return int(x) + return int(x) ###################################################### ## Main function, called from parser. def midiinc(ln): - """ Include a MIDI file into MMA generated files. """ + """ Include a MIDI file into MMA generated files. """ - global midifile, offset + global midifile, offset - filename = '' - doLyric = 0 - doText = 0 - volAdjust = 100 - octAdjust = 0 - transpose = None - channels = [] + filename = '' + doLyric = 0 + doText = 0 + volAdjust = 100 + octAdjust = 0 + transpose = None + channels = [] - # These are the start/end points for the included file. They are in - # beats, but are adjusted after the file is opened to ticks. + # These are the start/end points for the included file. They are in + # beats, but are adjusted after the file is opened to ticks. - istart=0 - iend = 0xffffff + istart=0 + iend = 0xffffff - for a in ln: - cmd, opt = a.split('=') + for a in ln: + cmd, opt = a.split('=') - cmd=cmd.upper() + cmd=cmd.upper() - if cmd == 'FILE': - filename = os.path.expanduser(opt) + if cmd == 'FILE': + filename = os.path.expanduser(opt) - elif cmd == 'VOLUME': - volAdjust = stoi(opt) + elif cmd == 'VOLUME': + volAdjust = stoi(opt) - elif cmd == 'OCTAVE': - octAdjust = stoi(opt) - if octAdjust < -4 or octAdjust > 4: - error("Octave adjustment must be -4 to 4, not %s." % opt) - octAdjust *= 12 + elif cmd == 'OCTAVE': + octAdjust = stoi(opt) + if octAdjust < -4 or octAdjust > 4: + error("Octave adjustment must be -4 to 4, not %s" % opt) + octAdjust *= 12 - elif cmd == 'TRANSPOSE': - transpose = stoi(opt) - if transpose < -24 or transpose > 24: - error("Tranpose must be -24 to 24, not %s." % opt) + elif cmd == 'TRANSPOSE': + transpose = stoi(opt) + if transpose < -24 or transpose > 24: + error("Tranpose must be -24 to 24, not %s" % opt) - elif cmd == 'START': - istart = stof(opt) + elif cmd == 'START': + istart = stof(opt) - elif cmd == 'END': - iend = stof(opt) + elif cmd == 'END': + iend = stof(opt) - elif cmd == 'TEXT': - opt=opt.upper() - if opt in ("ON", 1): - doText=1 - elif opt in ("OFF", 0): - doText=0 - else: - error("MidiInc Text= expecting 'ON' or 'OFF'") + elif cmd == 'TEXT': + opt=opt.upper() + if opt in ("ON", 1): + doText=1 + elif opt in ("OFF", 0): + doText=0 + else: + error("MidiInc Text= expecting 'ON' or 'OFF'") - elif cmd == 'LYRIC' and opt != '0': - opt=opt.upper() - if opt in ("ON", 1): - doLyric=1 - elif opt in ("OFF", 0): - doLyric=0 - else: - error("MidiInc Lyric= expecting 'ON' or 'OFF'") + elif cmd == 'LYRIC' and opt != '0': + opt=opt.upper() + if opt in ("ON", 1): + doLyric=1 + elif opt in ("OFF", 0): + doLyric=0 + else: + error("MidiInc Lyric= expecting 'ON' or 'OFF'") - # make sure this is last option ... it has to be a TRACKNAME=CHANNEL-NUMBER + # make sure this is last option ... it has to be a TRACKNAME=CHANNEL-NUMBER - else: - trackAlloc(cmd, 0) - if not cmd in gbl.tnames: - error("%s is not a valid MMA track." % cmd) + else: + trackAlloc(cmd, 0) + if not cmd in gbl.tnames: + error("%s is not a valid MMA track" % cmd) - ch = stoi(opt) - if ch < 1 or ch > 16: - error("MIDI channel for import must be 1..16, not %s." % ch) + ch = stoi(opt) + if ch < 1 or ch > 16: + error("MIDI channel for import must be 1..16, not %s" % ch) - channels.append( (cmd, ch-1)) + channels.append( (cmd, ch-1)) - if not channels: - if doLyric or doText: - warning("MidiInc: no import channels specified, only text or lyrics imported.") - else: - error("MidiInc: A channel to import and a destination track must be specified.") + if not channels: + if doLyric or doText: + warning("MidiInc: no import channels specified, only text or lyrics imported") + else: + error("MidiInc: A channel to import and a destination track must be specified") - if (istart >= iend) or (istart < 0) or (iend < 0): - error("MidiInc range invalid: start=%s, end=%s" % (istart, iend)) + if (istart >= iend) or (istart < 0) or (iend < 0): + error("MidiInc range invalid: start=%s, end=%s" % (istart, iend)) - if gbl.debug: - print "MidiInc: file=%s, Volume=%s, Octave=%s, Transpose=%s, Lyric=%s, Text=%s, Range=%s..%s"\ - % (filename, volAdjust, octAdjust, transpose, doLyric, doText, istart, iend) - for t, ch in channels: - print "MidiInc: Channel %s --> Track %s" % (ch+1, t) + if gbl.debug: + print "MidiInc: file=%s, Volume=%s, Octave=%s, Transpose=%s, Lyric=%s, Text=%s, Range=%s..%s"\ + % (filename, volAdjust, octAdjust, transpose, doLyric, doText, istart, iend) + for t, ch in channels: + print "MidiInc: Channel %s --> Track %s" % (ch+1, t) - # If transpose was NOT set, use the global transpose value + # If transpose was NOT set, use the global transpose value - if transpose == None: - transpose = gbl.transpose + if transpose == None: + transpose = gbl.transpose - octAdjust += transpose # this takes care of octave and transpose + octAdjust += transpose # this takes care of octave and transpose - try: - inpath = file(filename, "rb") - except: - error("Unable to open MIDI file %s for reading" % filename) + try: + inpath = file(filename, "rb") + except: + error("Unable to open MIDI file %s for reading" % filename) - midifile=inpath.read() - inpath.close() + midifile=inpath.read() + inpath.close() - # Create our storage: - # A dic with the channels 0-15 as keys for the midi note events - # 2 lists for lyrics and text events. These have tuples for (time, text) + # Create our storage: + # A dic with the channels 0-15 as keys for the midi note events + # 2 lists for lyrics and text events. These have tuples for (time, text) - events={} - for c in range(0,16): - events[c]=[] + events={} + for c in range(0,16): + events[c]=[] - textEvs=[] - lyricEvs=[] + textEvs=[] + lyricEvs=[] - # Ensure this is valid header + # Ensure this is valid header - hd=midifile[0:4] - if hd != 'MThd': - error("Expecting 'HThd', %s not a standard midi file." % filename) + hd=midifile[0:4] + if hd != 'MThd': + error("Expecting 'HThd', %s not a standard midi file" % filename) - offset = 4 - a = m32i() + offset = 4 + a = m32i() - if a != 6: - error("Expecting a 32 bit value of 6 in header") + if a != 6: + error("Expecting a 32 bit value of 6 in header") - format=m16i() + format=m16i() - if format not in (0,1): - error("MIDI file format %s not recognized" % format) + if format not in (0,1): + error("MIDI file format %s not recognized" % format) - ntracks=m16i() - beatDivision=m16i() + ntracks=m16i() + beatDivision=m16i() - if beatDivision != gbl.BperQ: - warning("MIDI file '%s' tick/beat of %s differs from MMA's " - "%s. Will try to compensate." % - (filename, beatDivision, gbl.BperQ)) + if beatDivision != gbl.BperQ: + warning("MIDI file '%s' tick/beat of %s differs from MMA's " + "%s. Will try to compensate" % + (filename, beatDivision, gbl.BperQ)) - # Adjust start/end to the file's tick + # Adjust start/end to the file's tick - istart *= beatDivision - iend *= beatDivision + istart *= beatDivision + iend *= beatDivision - midievents={} - firstNote = 0xffffff + midievents={} + firstNote = 0xffffff - for tr in range(ntracks): - tm=0 + for tr in range(ntracks): + tm=0 - hdr = midifile[offset:offset+4] - offset+=4 + hdr = midifile[offset:offset+4] + offset+=4 - if hdr != 'MTrk': - error("Malformed MIDI file in track header") - trlen = m32i() # track length, not used? + if hdr != 'MTrk': + error("Malformed MIDI file in track header") + trlen = m32i() # track length, not used? - lastevent = None + lastevent = None - """ Parse the midi file. We have to parse off each event, even - though many will just be thrown away. You can't just skip around - in a midi file :) In the future we might decide to include meta - stuff, etc. Or, we may not :) For now, we keep: - - note on - - note off - - key pressure - - control change - - program change - - channel pressure - - pitch blend - - text event - - lyric event - """ + """ Parse the midi file. We have to parse off each event, even + though many will just be thrown away. You can't just skip around + in a midi file :) In the future we might decide to include meta + stuff, etc. Or, we may not :) For now, we keep: + - note on + - note off + - key pressure + - control change + - program change + - channel pressure + - pitch blend + - text event + - lyric event + """ - while 1: - tm += mvarlen() # adjust total offset by delta + while 1: + tm += mvarlen() # adjust total offset by delta - ev=m1i() + ev=m1i() - if ev < 0x80: - if not lastevent: - error("Illegal running status in %s at %s" \ - % (midifile, offset)) - offset -= 1 - ev=lastevent + if ev < 0x80: + if not lastevent: + error("Illegal running status in %s at %s" % (midifile, offset)) + offset -= 1 + ev=lastevent - sValue = ev>>4 # Shift MSBs to get a 4 bit value - channel = ev & 0x0f + sValue = ev>>4 # Shift MSBs to get a 4 bit value + channel = ev & 0x0f - if sValue == 0x8: # note off event + if sValue == 0x8: # note off event - note=m1i() - vel=m1i() + note=m1i() + vel=m1i() - if octAdjust and channel != 10: - note += octAdjust - if note < 0 or note > 127: - continue + if octAdjust and channel != 10: + note += octAdjust + if note < 0 or note > 127: + continue - events[channel].append([tm, ev & 0xf0, chr(note)+chr(vel)]) + events[channel].append([tm, ev & 0xf0, chr(note)+chr(vel)]) - elif sValue == 0x9: # note on event - if tm < firstNote: - firstNote = tm + elif sValue == 0x9: # note on event + if tm < firstNote: + firstNote = tm - note=m1i() - vel=m1i() + note=m1i() + vel=m1i() - if octAdjust and channel != 10: - note += octAdjust - if note < 0 or note > 127: - continue + if octAdjust and channel != 10: + note += octAdjust + if note < 0 or note > 127: + continue - if volAdjust != 100: - vel = int( (vel*volAdjust)/100) - if vel<0: vel=1 - if vel>127: vel=127 + if volAdjust != 100: + vel = int( (vel*volAdjust)/100) + if vel<0: vel=1 + if vel>127: vel=127 - events[ev & 0xf].append([tm, ev & 0xf0, chr(note)+chr(vel)]) + events[ev & 0xf].append([tm, ev & 0xf0, chr(note)+chr(vel)]) - elif sValue == 0xa: # key pressure - events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) + elif sValue == 0xa: # key pressure + events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) - elif sValue == 0xb: # control change - events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) + elif sValue == 0xb: # control change + events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) - elif sValue == 0xc: # program change - events[ev & 0xf].append([tm, ev & 0xf0, chars(1)]) + elif sValue == 0xc: # program change + events[ev & 0xf].append([tm, ev & 0xf0, chars(1)]) - elif sValue == 0xd: # channel pressure - events[ev & 0xf].append([tm, ev & 0xf0, chars(1)]) + elif sValue == 0xd: # channel pressure + events[ev & 0xf].append([tm, ev & 0xf0, chars(1)]) - elif sValue == 0xe: # pitch blend - events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) + elif sValue == 0xe: # pitch blend + events[ev & 0xf].append([tm, ev & 0xf0, chars(2)]) - elif sValue == 0xf: # system, mostly ignored - if ev == 0xff: # meta events - a=m1i() + elif sValue == 0xf: # system, mostly ignored + if ev == 0xff: # meta events + a=m1i() - if a == 0x00: # sequence number - l=mvarlen() - offset += l + if a == 0x00: # sequence number + l=mvarlen() + offset += l - elif a == 0x01: # text (could be lyrics) - textEvs.append((tm, chars(mvarlen()))) + elif a == 0x01: # text (could be lyrics) + textEvs.append((tm, chars(mvarlen()))) - elif a == 0x02: # copyright - l=mvarlen() - offset += l + elif a == 0x02: # copyright + l=mvarlen() + offset += l - elif a == 0x03: # seq/track name - l=mvarlen() - offset += l + elif a == 0x03: # seq/track name + l=mvarlen() + offset += l - elif a == 0x04: # instrument name - l=mvarlen() - offset += l + elif a == 0x04: # instrument name + l=mvarlen() + offset += l - elif a == 0x05: # lyric - lyricEvs.append((tm, chars(mvarlen()))) + elif a == 0x05: # lyric + lyricEvs.append((tm, chars(mvarlen()))) - elif a == 0x06: # marker - l=mvarlen() - offset += l + elif a == 0x06: # marker + l=mvarlen() + offset += l - elif a == 0x07: # cue point - l=mvarlen() - offset += l + elif a == 0x07: # cue point + l=mvarlen() + offset += l - elif a == 0x21: # midi port - l=mvarlen() - offset += l + elif a == 0x21: # midi port + l=mvarlen() + offset += l - elif a == 0x2f: # end of track - l=mvarlen() - offset += l - break + elif a == 0x2f: # end of track + l=mvarlen() + offset += l + break - elif a == 0x51: #tempo - l=mvarlen() - offset += l + elif a == 0x51: #tempo + l=mvarlen() + offset += l - elif a == 0x54: # SMPTE offset - l=mvarlen() - offset += l + elif a == 0x54: # SMPTE offset + l=mvarlen() + offset += l - elif a == 0x58: # time sig - l=mvarlen() - offset += l + elif a == 0x58: # time sig + l=mvarlen() + offset += l - elif a == 0x59: # key sig - l=mvarlen() - offset += l + elif a == 0x59: # key sig + l=mvarlen() + offset += l - else: # probably 0x7f, proprietary event - l=mvarlen() - offset += l + else: # probably 0x7f, proprietary event + l=mvarlen() + offset += l - elif ev == 0xf0: # system exclusive - l=mvarlen() - offset += l + elif ev == 0xf0: # system exclusive + l=mvarlen() + offset += l - elif ev == 0xf2: # song position pointer, 2 bytes - offset += 2 + elif ev == 0xf2: # song position pointer, 2 bytes + offset += 2 - elif ev == 0xf3: # song select, 1 byte - offset += 1 - - else: # all others are single byte commands - pass + elif ev == 0xf3: # song select, 1 byte + offset += 1 + + else: # all others are single byte commands + pass - if ev >= 0x80 and ev <= 0xef: - lastevent = ev + if ev >= 0x80 and ev <= 0xef: + lastevent = ev - # Midi file parsed, add selected events to mma data + # Midi file parsed, add selected events to mma data - beatad = gbl.BperQ / float(beatDivision) + beatad = gbl.BperQ / float(beatDivision) - if doText: - inst=0 - disc=0 - for tm,tx in textEvs: - delta = tm-firstNote - if delta >= istart and delta <= iend: - gbl.mtrks[0].addText(gbl.tickOffset + int(delta * beatad), tx) - inst+=1 - else: - disc+=1 - if gbl.debug: - print"MidiInc text events: %s inserted, %s out of range." % (inst, disc) - - if doLyric: - inst=0 - disc=0 - for tm, tx in lyricEvs: - delta = tm-firstNote - if delta >= istart and delta <= iend: - gbl.mtrks[0].addLyric(gbl.tickOffset + int(delta * beatad), tx) - inst+=1 - else: - disc+=1 - if gbl.debug: - print"MidiInc lyric events: %s inserted, %s out of range." % (inst, disc) - - - for n,c in channels: - if not len(events[c]): - warning("No data to assign from imported channel %s to track %s." % (c+1, n)) - - inst=0 - disc=0 - for tr, ch in channels: - t=gbl.tnames[tr] - if not t.channel: - t.setChannel() - - t.clearPending() - if t.voice[0] != t.ssvoice: - gbl.mtrks[t.channel].addProgChange( gbl.tickOffset, t.voice[0]) - - channel = t.channel - track = gbl.mtrks[channel] - - for ev in events[ch]: - delta = ev[0]-firstNote - if delta >= istart and delta <= iend: - track.addToTrack( gbl.tickOffset + int(delta * beatad), - chr(ev[1] | channel-1) + ev[2] ) - inst+=1 - else: - disc+=1 - - if gbl.debug: - print"MidiInc events: %s inserted, %s out of range." % (inst, disc) + if doText: + inst=0 + disc=0 + for tm,tx in textEvs: + delta = tm-firstNote + if delta >= istart and delta <= iend: + gbl.mtrks[0].addText(gbl.tickOffset + int(delta * beatad), tx) + inst+=1 + else: + disc+=1 + if gbl.debug: + print"MidiInc text events: %s inserted, %s out of range." % (inst, disc) + + if doLyric: + inst=0 + disc=0 + for tm, tx in lyricEvs: + delta = tm-firstNote + if delta >= istart and delta <= iend: + gbl.mtrks[0].addLyric(gbl.tickOffset + int(delta * beatad), tx) + inst+=1 + else: + disc+=1 + if gbl.debug: + print"MidiInc lyric events: %s inserted, %s out of range." % (inst, disc) + + + for n,c in channels: + if not len(events[c]): + warning("No data to assign from imported channel %s to track %s" % (c+1, n)) + + inst=0 + disc=0 + for tr, ch in channels: + t=gbl.tnames[tr] + if not t.channel: + t.setChannel() + + t.clearPending() + if t.voice[0] != t.ssvoice: + gbl.mtrks[t.channel].addProgChange( gbl.tickOffset, t.voice[0]) + + channel = t.channel + track = gbl.mtrks[channel] + + for ev in events[ch]: + delta = ev[0]-firstNote + if delta >= istart and delta <= iend: + track.addToTrack( gbl.tickOffset + int(delta * beatad), + chr(ev[1] | channel-1) + ev[2] ) + inst+=1 + else: + disc+=1 + + if gbl.debug: + print"MidiInc events: %s inserted, %s out of range." % (inst, disc) diff --git a/mma/MMA/midiM.py b/mma/MMA/midiM.py index 25e0672..b2b39ae 100644 --- a/mma/MMA/midiM.py +++ b/mma/MMA/midiM.py @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel This module contains the MIDI number (un)packing routines. @@ -29,29 +29,29 @@ MIDI expects. def intToWord(x): - """ Convert INT to a 2 byte MSB LSB value. """ + """ Convert INT to a 2 byte MSB LSB value. """ - return chr(x>>8 & 0xff) + chr(x & 0xff) + return chr(x>>8 & 0xff) + chr(x & 0xff) def intTo3Byte(x): - """ Convert INT to a 3 byte MSB...LSB value. """ + """ Convert INT to a 3 byte MSB...LSB value. """ - return intToLong(x)[1:] + return intToLong(x)[1:] def intToLong(x): - """ Convert INT to a 4 byte MSB...LSB value. """ + """ Convert INT to a 4 byte MSB...LSB value. """ - return intToWord(x>>16) + intToWord(x) + return intToWord(x>>16) + intToWord(x) def intToVarNumber(x): - """ Convert INT to a variable length MIDI value. """ + """ Convert INT to a variable length MIDI value. """ - lst = chr(x & 0x7f) - while 1: - x = x >> 7 - if x: - lst = chr((x & 0x7f) | 0x80) + lst - else: - return lst + lst = chr(x & 0x7f) + while 1: + x = x >> 7 + if x: + lst = chr((x & 0x7f) | 0x80) + lst + else: + return lst diff --git a/mma/MMA/miditables.py b/mma/MMA/miditables.py new file mode 100644 index 0000000..238bd0f --- /dev/null +++ b/mma/MMA/miditables.py @@ -0,0 +1,166 @@ + +# miditables.py + +""" +This module is an integeral part of the program +MMA - Musical Midi Accompaniment. + +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, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Bob van der Poel + +This module contains the constant names for the various +MIDI controllers. + +Having only the constants in this separate file permits to +call this from other programs, mainly the mma doc creators. + +""" + + + +""" English names for midi instruments and drums. + + These tables are used by the pattern classes to + convert inst/drum names to midi values and by the + doc routines to print tables. +""" + +# The drum names are valid for tones 27 to 87 + +drumNames=[ + 'HighQ', 'Slap', 'ScratchPush', 'ScratchPull', + 'Sticks', 'SquareClick', 'MetronomeClick', + 'MetronomeBell', 'KickDrum2', 'KickDrum1', + 'SideKick', 'SnareDrum1', 'HandClap', + 'SnareDrum2', 'LowTom2', 'ClosedHiHat', + 'LowTom1', 'PedalHiHat', 'MidTom2', 'OpenHiHat', + 'MidTom1', 'HighTom2', 'CrashCymbal1', + 'HighTom1', 'RideCymbal1', 'ChineseCymbal', + 'RideBell', 'Tambourine', 'SplashCymbal', + 'CowBell', 'CrashCymbal2', 'VibraSlap', + 'RideCymbal2', 'HighBongo', 'LowBongo', + 'MuteHighConga', 'OpenHighConga', 'LowConga', + 'HighTimbale', 'LowTimbale', 'HighAgogo', + 'LowAgogo', 'Cabasa', 'Maracas', + 'ShortHiWhistle', 'LongLowWhistle', 'ShortGuiro', + 'LongGuiro', 'Claves', 'HighWoodBlock', + 'LowWoodBlock', 'MuteCuica', 'OpenCuica', + 'MuteTriangle', 'OpenTriangle', 'Shaker', + 'JingleBell', 'Castanets', 'MuteSudro', + 'OpenSudro' ] + +upperDrumNames = [name.upper() for name in drumNames] + + +voiceNames=[ + 'Piano1', 'Piano2','Piano3', + 'Honky-TonkPiano', 'RhodesPiano', 'EPiano', + 'HarpsiChord', 'Clavinet', 'Celesta', + 'Glockenspiel', 'MusicBox', 'Vibraphone', + 'Marimba', 'Xylophone', 'TubularBells', 'Santur', + 'Organ1', 'Organ2', 'Organ3', 'ChurchOrgan', + 'ReedOrgan', 'Accordion', 'Harmonica', + 'Bandoneon', 'NylonGuitar', 'SteelGuitar', + 'JazzGuitar', 'CleanGuitar', 'MutedGuitar', + 'OverDriveGuitar', 'DistortonGuitar', + 'GuitarHarmonics', 'AcousticBass', + 'FingeredBass', 'PickedBass', 'FretlessBass', + 'SlapBass1', 'SlapBass2', 'SynthBass1', + 'SynthBass2', 'Violin', 'Viola', 'Cello', + 'ContraBass', 'TremoloStrings', + 'PizzicatoString', 'OrchestralHarp', 'Timpani', + 'Strings', 'SlowStrings', 'SynthStrings1', + 'SynthStrings2', 'ChoirAahs', 'VoiceOohs', + 'SynthVox', 'OrchestraHit', 'Trumpet', + 'Trombone', 'Tuba', 'MutedTrumpet', 'FrenchHorn', + 'BrassSection', 'SynthBrass1', 'SynthBrass2', + 'SopranoSax', 'AltoSax', 'TenorSax', + 'BaritoneSax', 'Oboe', 'EnglishHorn', 'Bassoon', + 'Clarinet', 'Piccolo', 'Flute', 'Recorder', + 'PanFlute', 'BottleBlow', 'Shakuhachi', + 'Whistle', 'Ocarina', 'SquareWave', 'SawWave', + 'SynCalliope', 'ChifferLead', 'Charang', + 'SoloVoice', '5thSawWave', 'Bass&Lead', + 'Fantasia', 'WarmPad', 'PolySynth', 'SpaceVoice', + 'BowedGlass', 'MetalPad', 'HaloPad', 'SweepPad', + 'IceRain', 'SoundTrack', 'Crystal', 'Atmosphere', + 'Brightness', 'Goblins', 'EchoDrops', + 'StarTheme', 'Sitar', 'Banjo', 'Shamisen', + 'Koto', 'Kalimba', 'BagPipe', 'Fiddle', 'Shanai', + 'TinkleBell', 'AgogoBells', 'SteelDrums', + 'WoodBlock', 'TaikoDrum', 'MelodicTom1', + 'SynthDrum', 'ReverseCymbal', 'GuitarFretNoise', + 'BreathNoise', 'SeaShore', 'BirdTweet', + 'TelephoneRing', 'HelicopterBlade', + 'Applause/Noise', 'GunShot' ] + + +upperVoiceNames = [name.upper() for name in voiceNames] + +ctrlNames = [ + ### also see: http://www.midi.org/about-midi/table3.shtml + + ### 0-31 Double Precise Controllers + ### MSB (14-bits, 16,384 values) + + 'Bank', 'Modulation', 'Breath', 'Ctrl3', + 'Foot', 'Portamento', 'Data', 'Volume', + 'Balance', 'Ctrl9', 'Pan', 'Expression', + 'Effect1', 'Effect2', 'Ctrl14', 'Ctrl15', + 'General1','General2','General3','General4', + 'Ctrl20', 'Ctrl21', 'Ctrl22', 'Ctrl23', + 'Ctrl24', 'Ctrl25', 'Ctrl26', 'Ctrl27', + 'Ctrl28', 'Ctrl29', 'Ctrl30', 'Ctrl31', + ### 32-63 Double Precise Controllers + ### LSB (14-bits, 16,384 values) + 'BankLSB', 'ModulationLSB', 'BreathLSB', + 'Ctrl35', 'FootLSB', 'PortamentoLSB', + 'DataLSB','VolumeLSB','BalanceLSB', + 'Ctrl41','PanLSB','ExpressionLSB', + 'Effect1LSB', 'Effect2LSB','Ctrl46', 'Ctrl47', + 'General1LSB','General2LSB', 'General3LSB', + 'General4LSB', 'Ctrl52','Ctrl53', 'Ctrl54', + 'Ctrl55', 'Ctrl56', 'Ctrl57', 'Ctrl58', + 'Ctrl59', 'Ctrl60', 'Ctrl61', 'Ctrl62', + 'Ctrl63', + + ### 64-119 Single Precise Controllers + ### (7-bits, 128 values) + + 'Sustain', 'Portamento', 'Sostenuto', + 'SoftPedal', 'Legato', 'Hold2', 'Variation', + 'Resonance', 'ReleaseTime','AttackTime', 'Brightness', + 'DecayTime','VibratoRate','VibratoDepth', 'VibratoDelay', + 'Ctrl79','General5','General6','General7', + 'General8','PortamentoCtrl','Ctrl85','Ctrl86', + 'Ctrl87', 'Ctrl88', 'Ctrl89', 'Ctrl90', + 'Reverb', 'Tremolo', 'Chorus','Detune', + 'Phaser', 'DataInc','DataDec', + 'NonRegLSB', 'NonRegMSB', + 'RegParLSB', 'RegParMSB', + 'Ctrl102','Ctrl103','Ctrl104','Ctrl105', + 'Ctrl106','Ctrl107','Ctrl108','Ctrl109', + 'Ctrl110','Ctrl111','Ctrl112','Ctrl113', + 'Ctrl114','Ctrl115','Ctrl116','Ctrl117', + 'Ctrl118','Ctrl119', + + ### 120-127 Channel Mode Messages + + 'AllSoundsOff','ResetAll', + 'LocalCtrl','AllNotesOff', + 'OmniOff','OmniOn', 'PolyOff','PolyOn' ] + +upperCtrlNames = [name.upper() for name in ctrlNames] diff --git a/mma/MMA/notelen.py b/mma/MMA/notelen.py index 6ce394e..5649bfa 100644 --- a/mma/MMA/notelen.py +++ b/mma/MMA/notelen.py @@ -2,7 +2,7 @@ # notelen.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ import gbl @@ -28,103 +28,103 @@ from MMA.common import * noteLenTable = { - '0' : 1, # special 0==1 midi tick - '1' : gbl.BperQ * 4, # whole note - '2' : gbl.BperQ * 2, # 1/2 - '23' : gbl.BperQ * 4 / 3, # 1/2 triplet - '4' : gbl.BperQ, # 1/4 - '43' : gbl.BperQ * 2 / 3, # 1/4 triplet - '8' : gbl.BperQ / 2, # 1/8 - '81' : None, # short 1/8 swing note - '82' : None, # long 1/8 swing note - '16' : gbl.BperQ / 4, # 1/16 - '32' : gbl.BperQ / 8, # 1/32 - '64' : gbl.BperQ / 16, # 1/64 - '6' : gbl.BperQ / 6, # 1/16 note triplet - '3' : gbl.BperQ / 3, # 1/8 note triplet - '5' : gbl.BperQ / 5 } # 1/8 note quintuplet + '0' : 1, # special 0==1 midi tick + '1' : gbl.BperQ * 4, # whole note + '2' : gbl.BperQ * 2, # 1/2 + '23' : gbl.BperQ * 4 / 3, # 1/2 triplet + '4' : gbl.BperQ, # 1/4 + '43' : gbl.BperQ * 2 / 3, # 1/4 triplet + '8' : gbl.BperQ / 2, # 1/8 + '81' : None, # short 1/8 swing note + '82' : None, # long 1/8 swing note + '16' : gbl.BperQ / 4, # 1/16 + '32' : gbl.BperQ / 8, # 1/32 + '64' : gbl.BperQ / 16, # 1/64 + '6' : gbl.BperQ / 6, # 1/16 note triplet + '3' : gbl.BperQ / 3, # 1/8 note triplet + '5' : gbl.BperQ / 5 } # 1/8 note quintuplet def swingMode(ln): - """ Enable/Disable Swing timing mode. """ + """ Enable/Disable Swing timing mode. """ - - emsg = "Use: SwingMode [ On, Off, 0, 1 Skew=xx ]." - - if not ln: - error(emsg) - - for v in ln: + emsg = "Use: SwingMode [ On, Off, 0, 1 Skew=xx ]." - a = v.upper() + if not ln: + error(emsg) - if a in ("ON", "1"): - gbl.swingMode = 1 - continue - - if a in ("OFF", "0"): - gbl.swingMode = 0 - continue - if a.find('=')>1: - a,b = a.split('=') + for v in ln: - if a == 'SKEW': - gbl.swingSkew = b - v = int( stoi(b) * gbl.BperQ / 100) - noteLenTable['81'] = v - noteLenTable['82'] = gbl.BperQ - v - continue + a = v.upper() - error(emsg) + if a in ("ON", "1"): + gbl.swingMode = 1 + continue + + if a in ("OFF", "0"): + gbl.swingMode = 0 + continue + + if a.find('=')>1: + a,b = a.split('=') + + if a == 'SKEW': + gbl.swingSkew = b + v = int( stoi(b) * gbl.BperQ / 100) + noteLenTable['81'] = v + noteLenTable['82'] = gbl.BperQ - v + continue + + error(emsg) + + if gbl.debug: + print "SwingMode: Status=%s, Skew Note lengths: %s and %s ticks." % \ + (gbl.swingMode, noteLenTable['81'], noteLenTable['82']) - if gbl.debug: - print "SwingMode: Status=%s, Skew Note lengths: %s and %s ticks." % \ - (gbl.swingMode, noteLenTable['81'], noteLenTable['82']) - swingMode(['Skew=66']) # Set the default swingskew values. -def getNoteLen(n): - """ Convert a Note to a midi tick length. - - Notes are 1==Whole, 4==Quarter, etc. - Notes can be dotted or double dotted. - Notes can be combined: 1+4 == 5 beats, 4. or 4+8 == dotted 1/4 +def getNoteLen(n): + """ Convert a Note to a midi tick length. + + Notes are 1==Whole, 4==Quarter, etc. + Notes can be dotted or double dotted. + Notes can be combined: 1+4 == 5 beats, 4. or 4+8 == dotted 1/4 1-4 == 3 beats, 1-0 == 4 beats less a midi tick - """ - - length = 0 - - n=n.replace('-', '+-') # change "2-4" to "2+-4" for easier parsing - n=n.replace('++-', '+-') # and in case we already used "+-", take out 2nd "+" - - for a in str(n).split('+'): - if a.endswith('..'): - dot = 2 - a=a[:-2] - elif a.endswith('.'): - dot = 1 - a=a[:-1] - else: - dot = 0 + """ - try: - if a.startswith('-'): - i = noteLenTable[a[1:]] * -1 - else: - i = noteLenTable[a] + length = 0 - except: - error("Unknown note duration %s" % n ) + n=n.replace('-', '+-') # change "2-4" to "2+-4" for easier parsing + n=n.replace('++-', '+-') # and in case we already used "+-", take out 2nd "+" - if dot == 2: - i += i/2 + i/4 - elif dot == 1: - i += i/2 - length += i - - return length + for a in str(n).split('+'): + if a.endswith('..'): + dot = 2 + a=a[:-2] + elif a.endswith('.'): + dot = 1 + a=a[:-1] + else: + dot = 0 + + try: + if a.startswith('-'): + i = noteLenTable[a[1:]] * -1 + else: + i = noteLenTable[a] + + except: + error("Unknown note duration %s" % n ) + + if dot == 2: + i += i/2 + i/4 + elif dot == 1: + i += i/2 + length += i + + return length diff --git a/mma/MMA/options.py b/mma/MMA/options.py index f6eba05..f56b0d5 100644 --- a/mma/MMA/options.py +++ b/mma/MMA/options.py @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -38,188 +38,156 @@ from MMA.macro import macros def opts(): - """ Option parser. """ + """ Option parser. """ - try: - opts, args = getopt.gnu_getopt(sys.argv[1:], - "dpsS:ri:wneom:f:M:cgGvD:", [] ) + try: + opts, args = getopt.gnu_getopt(sys.argv[1:], + "dpsS:ri:wneom:f:M:cgGvD:0", [] ) - except getopt.GetoptError: - usage() + except getopt.GetoptError: + usage() - for o,a in opts: - if o == '-d': - gbl.debug = gbl.Ldebug = 1 + for o,a in opts: + + if o == '-d': + gbl.debug = gbl.Ldebug = 1 - elif o == '-o': - gbl.showFilenames = gbl.LshowFilenames = 1 + elif o == '-o': + gbl.showFilenames = gbl.LshowFilenames = 1 - elif o == '-p': - gbl.pshow = gbl.Lpshow = 1 + elif o == '-p': + gbl.pshow = gbl.Lpshow = 1 - elif o == '-s': - gbl.seqshow = gbl.Lseqshow = 1 + elif o == '-s': + gbl.seqshow = gbl.Lseqshow = 1 - elif o == '-S': - ln = a.split('=', 1) - macros.setvar(ln) + elif o == '-S': + ln = a.split('=', 1) + macros.setvar(ln) - elif o == '-r': - gbl.showrun = gbl.Lshowrun = 1 + elif o == '-r': + gbl.showrun = gbl.Lshowrun = 1 - elif o == '-w': - gbl.noWarn = gbl.LnoWarn = 1 + elif o == '-w': + gbl.noWarn = gbl.LnoWarn = 1 - elif o == '-n': - gbl.noOutput = gbl.LnoOutput = 1 + elif o == '-n': + gbl.noOutput = gbl.LnoOutput = 1 - elif o == '-e': - gbl.showExpand = gbl.LshowExpand = 1 + elif o == '-e': + gbl.showExpand = gbl.LshowExpand = 1 - elif o == '-c': - gbl.chshow = gbl.Lchshow = 1 + elif o == '-c': + gbl.chshow = gbl.Lchshow = 1 - elif o == '-f': - gbl.outfile = a + elif o == '-f': + gbl.outfile = a - elif o == '-i': - gbl.mmaRC = a + elif o == '-i': + gbl.mmaRC = a - elif o == '-g': - gbl.makeGrvDefs = 1 + elif o == '-g': + gbl.makeGrvDefs = 1 - elif o == '-G': - gbl.makeGrvDefs = 2 + elif o == '-G': + gbl.makeGrvDefs = 2 - elif o == '-m': - try: - a=int(a) - except: - error("Expecting -m arg to be a integer") - gbl.maxBars = a + elif o == '-m': + try: + a=int(a) + except: + error("Expecting -m arg to be a integer") + gbl.maxBars = a - elif o == '-v': - print "%s" % gbl.version - sys.exit(0) + elif o == '-v': + print "%s" % gbl.version + sys.exit(0) - elif o == '-M': - if a in ['0', '1']: - gbl.cmdSMF = a - else: - error("Only a '0' or '1' is permitted for the -M arg.") + elif o == '-M': + if a in ['0', '1']: + gbl.cmdSMF = a + else: + error("Only a '0' or '1' is permitted for the -M arg") - elif o == '-D': - if a == 'xl': - gbl.docs = 1 + elif o == '-D': + if a == 'xl': + gbl.docs = 1 - elif a == 'xh': - gbl.docs = 2 + elif a == 'xh': + gbl.docs = 2 - elif a == 'k': + elif a == 'k': - def pl(msg, lst): - print msg, - for i in sorted(lst.keys()): - print i, - print "\n" + def pl(msg, lst): + print msg, + for i in sorted(lst.keys()): + print i, + print "\n" - pl("Base track names:", MMA.alloc.trkClasses ) - pl("Commands:", MMA.parse.simpleFuncs) - pl("TrackCommands:", MMA.parse.trackFuncs) - print "Not complete ... subcommands, comments, chords..." - sys.exit(0) + pl("Base track names:", MMA.alloc.trkClasses ) + pl("Commands:", MMA.parse.simpleFuncs) + pl("TrackCommands:", MMA.parse.trackFuncs) + print "Not complete ... subcommands, comments, chords..." + sys.exit(0) + else: + print "Unknown -D option." + usage() - elif a == 'n': - MMA.chords.docs() - sys.exit(0) + elif o == '-0': + gbl.synctick = 1 - elif a == 'da': - MMA.docs.docDrumNames("a") - sys.exit(0) + else: + usage() # unreachable?? - elif a == 'dm': - MMA.docs.docDrumNames("m") - sys.exit(0) - - elif a == 'ia': - MMA.docs.docInstNames("a") - sys.exit(0) - - elif a == 'im': - MMA.docs.docInstNames("m") - sys.exit(0) - - elif a == 'ca': - MMA.docs.docCtrlNames("a") - sys.exit(0) - - elif a == 'cm': - MMA.docs.docCtrlNames("m") - sys.exit(0) - - else: - print "Unknown -D option." - usage() - - - else: - usage() # unreachable?? - - if args: - if gbl.infile: - usage("Only one input filename is permitted.") - gbl.infile = args.pop(0) + if args: + if gbl.infile: + usage("Only one input filename is permitted.") + gbl.infile = args.pop(0) def usage(msg=''): - """ Usage message. """ + """ Usage message. """ - txt=[ - "MMA - Musical Midi Accompaniment", - " Copyright 2003-5, Bob van der Poel. Version %s" % gbl.version , - " Distributed under the terms of the GNU Public License.", - " Usage: mma [opts ...] INFILE [opts ...]", - "", - "Options:", - " -c display default Channel assignments", - " -d enable lots of Debugging messages", - " -Dk print list of MMA keywords", - " -Dxl eXtract Latex doc blocks from file", - " -Dxh eXtract HTML doc blocks from file", - " -Dn print Note/chord table", - " -Ddm print Midi drum names (by MIDI value)", - " -Dda print Midi drum names (alphabetical)", - " -Dim print Inst. names (by MIDI value)", - " -Dia print Inst. names (alphabetical)", - " -Dcm print Controller names (by value)", - " -Dca print Controller names (alphabetical)", - " -e show parsed/Expanded lines", - " -f set output Filename", - " -g update Groove dependency database", - " -G create Groove dependency database", - " -i specify init (mmarc) file", - " -m set Maxbars (default == 500)", - " -M set SMF to 0 or 1", - " -n No generation of midi output", - " -o show complete filenames when Opened", - " -p display Patterns as they are defined", - " -r display Running progress", - " -s display Sequence info during run", - " -S Set macro 'var' to 'data'", - " -v display Version number", - " -w disable Warning messages" ] + txt=[ + "MMA - Musical Midi Accompaniment", + " Copyright 2003-5, Bob van der Poel. Version %s" % gbl.version , + " Distributed under the terms of the GNU Public License.", + " Usage: mma [opts ...] INFILE [opts ...]", + "", + "Options:", + " -c display default Channel assignments", + " -d enable lots of Debugging messages", + " -Dk print list of MMA keywords", + " -Dxl eXtract Latex doc blocks from file", + " -Dxh eXtract HTML doc blocks from file", + " -e show parsed/Expanded lines", + " -f set output Filename", + " -g update Groove dependency database", + " -G create Groove dependency database", + " -i specify init (mmarc) file", + " -m set Maxbars (default == 500)", + " -M set SMF to 0 or 1", + " -n No generation of midi output", + " -o show complete filenames when Opened", + " -p display Patterns as they are defined", + " -r display Running progress", + " -s display Sequence info during run", + " -S Set macro 'var' to 'data'", + " -v display Version number", + " -w disable Warning messages", + " -0 create sync at start of all channel tracks" ] - for a in txt: - print a + for a in txt: + print a - if msg: - print - print msg + if msg: + print + print msg - print - sys.exit(1) + print + sys.exit(1) diff --git a/mma/MMA/parse.py b/mma/MMA/parse.py index a188ac3..e7756cb 100644 --- a/mma/MMA/parse.py +++ b/mma/MMA/parse.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel This module does all file parsing. Most commands @@ -54,28 +54,31 @@ from MMA.pat import seqBump lastChord = None # tracks last chord for "/ /" data lines. beginData = [] # Current data set by a BEGIN statement -beginPoints = [] # since BEGINs can be nested, we need ptrs for backing out of BEGINs +beginPoints = [] # since BEGINs can be nested, we need ptrs for backing out of BEGINs seqRndWeight = [1] groovesList = None groovesCount = 0 +gmagic = 9988 # magic name for groove saved with USE + """ This table is passed to the track classes. It has an instance for each chord in the current bar. """ class CTable: - chord = None # A pointer to the chordNotes structures - chordZ = None # set if chord is tacet - arpeggioZ = None # set if arpeggio is tacet - walkZ = None # set if walking bass is tacet - drumZ = None # set if drums are tacet - bassZ = None # set if bass is tacet - scaleZ = None # set if scale track is tacet + chord = None # A pointer to the chordNotes structures + chordZ = None # set if chord is tacet + arpeggioZ = None # set if arpeggio is tacet + walkZ = None # set if walking bass is tacet + drumZ = None # set if drums are tacet + bassZ = None # set if bass is tacet + scaleZ = None # set if scale track is tacet + ariaZ = None # set if aria track is tacet - def __init__(self, offset): - self.offset=offset + def __init__(self, offset): + self.offset=offset @@ -85,376 +88,378 @@ class CTable: def parseFile(n): - """ Open and process a file. Errors exit. """ + """ Open and process a file. Errors exit. """ - fp=gbl.inpath + fp=gbl.inpath - f=MMA.file.ReadFile(n) + f=MMA.file.ReadFile(n) - parse(f) - gbl.inpath=fp + parse(f) + gbl.inpath=fp - if gbl.debug: - print "File '%s' closed." % n + if gbl.debug: + print "File '%s' closed." % n def parse(inpath): - """ Process a mma input file. """ + """ Process a mma input file. """ - global beginData, lastChord - global groovesList, groovesCount + global beginData, lastChord + global groovesList, groovesCount - gbl.inpath = inpath + gbl.inpath = inpath - curline = None + curline = None - while 1: - curline = inpath.read() + while 1: + curline = inpath.read() - if curline == None: - MMA.docs.docDump() - break + if curline == None: + MMA.docs.docDump() + break - l = macros.expand(curline) + l = macros.expand(curline) - """ Handle BEGIN and END here. This is outside of the Repeat/End - and variable expand loops so SHOULD be pretty bullet proof. - Note that the beginData stuff is global to this module ... the - Include/Use directives check to make sure we're not doing that - inside a Begin/End. + """ Handle BEGIN and END here. This is outside of the Repeat/End + and variable expand loops so SHOULD be pretty bullet proof. + Note that the beginData stuff is global to this module ... the + Include/Use directives check to make sure we're not doing that + inside a Begin/End. - beginData[] is a list which we append to as more Begins are - encountered. + beginData[] is a list which we append to as more Begins are + encountered. - The placement here is pretty deliberate. Variable expand comes - later so you can't macorize BEGIN ... I think this makes sense. - """ + The placement here is pretty deliberate. Variable expand comes + later so you can't macorize BEGIN ... I think this makes sense. + """ - key=l[0].upper() - if key == 'BEGIN': - if not l: - error("Use: BEGIN STUFF.") - beginPoints.append(len(beginData)) - beginData.extend(l[1:]) - continue + key=l[0].upper() + if key == 'BEGIN': + if not l: + error("Use: Begin STUFF") + beginPoints.append(len(beginData)) + beginData.extend(l[1:]) + continue - if key == 'END': - if len(l) > 1: - error("No arguments permitted for End") - if not beginData: - error("No 'Begin' for 'End'") - beginData=beginData[:beginPoints.pop(-1)] - continue + if key == 'END': + if len(l) > 1: + error("No arguments permitted for END") + if not beginData: + error("No 'BEGIN' for 'END'") + beginData=beginData[:beginPoints.pop(-1)] + continue - if beginData: - l = beginData + l + if beginData: + l = beginData + l - action = l[0].upper() + action = l[0].upper() - if gbl.showExpand and action !='REPEAT': - print l + if gbl.showExpand and action !='REPEAT': + print l - # If the command is in the simple function table, jump & loop. + # If the command is in the simple function table, jump & loop. - if action in simpleFuncs: - simpleFuncs[action](l[1:]) - continue + if action in simpleFuncs: + simpleFuncs[action](l[1:]) + continue - """ We have several possibilities ... - 1. The command is a valid assigned track name, - 2. The command is a valid track name, but needs to be - dynamically allocated, - 3. It's really a chord action - """ + """ We have several possibilities ... + 1. The command is a valid assigned track name, + 2. The command is a valid track name, but needs to be + dynamically allocated, + 3. It's really a chord action + """ - if not action in gbl.tnames: - trackAlloc(action, 0) # ensure that track is allocated + if not action in gbl.tnames: + trackAlloc(action, 0) # ensure that track is allocated - if action in gbl.tnames: # BASS/DRUM/APEGGIO/CHORD + if action in gbl.tnames: # BASS/DRUM/APEGGIO/CHORD - name = action - if len(l) < 2: - error("Expecting argument after '%s'" % name) - action = l[1].upper() + name = action + if len(l) < 2: + error("Expecting argument after '%s'" % name) + action = l[1].upper() - if action in trackFuncs: - trackFuncs[action](name, l[2:]) - else: - error ("Don't know '%s'" % curline) + if action in trackFuncs: + trackFuncs[action](name, l[2:]) + else: + error ("Don't know '%s'" % curline) - continue + continue - ### Gotta be a chord data line! + ### Gotta be a chord data line! - """ A data line can have an optional bar number at the start - of the line. Makes debugging input easier. The next - block strips leading integers off the line. Note that - a line number on a line by itself it okay. - """ + """ A data line can have an optional bar number at the start + of the line. Makes debugging input easier. The next + block strips leading integers off the line. Note that + a line number on a line by itself it okay. + """ - if l[0].isdigit(): - l = l[1:] - if not l: # ignore empty lines - continue + if l[0].isdigit(): + l = l[1:] + if not l: # ignore empty lines + continue - """ A bar can have an optional repeat count. This must - be at the end of bar in the form '* xx'. - """ + """ A bar can have an optional repeat count. This must + be at the end of bar in the form '* xx'. + """ - if len(l)>1 and l[-2]=='*': - rptcount = stoi(l[-1], "Expecting integer after '*'") - l=l[:-2] - else: - rptcount = 1 + if len(l)>1 and l[-2]=='*': + rptcount = stoi(l[-1], "Expecting integer after '*'") + l=l[:-2] + else: + rptcount = 1 - """ Extract solo(s) from line ... this is anything in {}s. - The solo data is pushed into RIFFs and discarded from - the current line. - """ + """ Extract solo(s) from line ... this is anything in {}s. + The solo data is pushed into RIFFs and discarded from + the current line. + """ - l = ' '.join(l) - l = MMA.patSolo.extractSolo(l, rptcount) + l = ' '.join(l) + l = MMA.patSolo.extractSolo(l, rptcount) - """ Set lyrics from [stuff] in the current line or - stuff previously stored with LYRICS SET. - """ + """ Set lyrics from [stuff] in the current line or + stuff previously stored with LYRICS SET. + """ - l, lyrics = lyric.extract(l, rptcount) + l, lyrics = lyric.extract(l, rptcount) - """ At this point we have only chord info. A number - of sanity checks are made: - 1. Make sure there is some chord data, - 2. Ensure the correct number of chords. - """ + """ At this point we have only chord info. A number + of sanity checks are made: + 1. Make sure there is some chord data, + 2. Ensure the correct number of chords. + """ - l = l.split() + l = l.split() - if not l: - error("Expecting music (chord) data. Even lines with\n" - " lyrics or solos still need a chord.") + if not l: + error("Expecting music (chord) data. Even lines with\n" + " lyrics or solos still need a chord") - i = gbl.QperBar - len(l) - if i<0: - error("Too many chords in line. Max is %s, not %s." % - (gbl.QperBar, len(l) ) ) - if i: - l.extend( ['/'] * i ) + i = gbl.QperBar - len(l) + if i<0: + error("Too many chords in line. Max is %s, not %s" % + (gbl.QperBar, len(l) ) ) + if i: + l.extend( ['/'] * i ) - """ We now have a valid line. It'll look something like: + """ We now have a valid line. It'll look something like: - ['Cm', '/', 'z', 'F#'] + ['Cm', '/', 'z', 'F#'] - For each bar we create a ctable structure. This is just - a list of CTables, one for each beat division. - Each entry has the offset (in midi ticks), chordname, etc. + For each bar we create a ctable structure. This is just + a list of CTables, one for each beat division. + Each entry has the offset (in midi ticks), chordname, etc. - Special processing in needed for 'z' options in chords. A 'z' can - be of the form 'CHORDzX', 'z!' or just 'z'. - """ + Special processing in needed for 'z' options in chords. A 'z' can + be of the form 'CHORDzX', 'z!' or just 'z'. + """ - beat = 0 - ctable = [] + beat = 0 + ctable = [] - for c in l: - if c == '/': - if not lastChord: - error("A chord has to be set before you can use a '/'.") - c = lastChord - else: - lastChord = c + for c in l: + if c == '/': + if not lastChord: + error("A chord has to be set before you can use a '/'") + c = lastChord + else: + lastChord = c - ctable.append(parseZs(c, beat)) - beat += 1 + ctable.append(parseZs(c, beat)) + beat += 1 - # Create MIDI data for the bar + # Create MIDI data for the bar - for rpt in range(rptcount): - if MMA.volume.futureVol: - MMA.volume.volume = MMA.volume.futureVol.pop(0) + for rpt in range(rptcount): + if MMA.volume.futureVol: + MMA.volume.volume = MMA.volume.futureVol.pop(0) - tmp = [] - for x, i in enumerate(seqRndWeight): - tmp.extend([x] * i) - if not len(tmp): - error("SeqRndWeight has generated an empty list.") - randomSeq = random.choice(tmp) + tmp = [] + for x, i in enumerate(seqRndWeight): + tmp.extend([x] * i) + if not len(tmp): + error("SeqRndWeight has generated an empty list") + randomSeq = random.choice(tmp) - if gbl.seqRnd[0] == 1: - gbl.seqCount = randomSeq + if gbl.seqRnd[0] == 1: + gbl.seqCount = randomSeq - """ Process each track. It is important that the track classes - are written so that the ctable passed to them IS NOT MODIFIED. - This applies especially to chords. If the track class changes - the chord, then restore it before returning!!! - """ + """ Process each track. It is important that the track classes + are written so that the ctable passed to them IS NOT MODIFIED. + This applies especially to chords. If the track class changes + the chord, then restore it before returning!!! + """ - for a in gbl.tnames.values(): - seqSave = gbl.seqCount - if a.name in gbl.seqRnd: - gbl.seqCount = randomSeq + for a in gbl.tnames.values(): + seqSave = gbl.seqCount + if a.name in gbl.seqRnd: + gbl.seqCount = randomSeq - a.bar(ctable) ## process entire bar! + a.bar(ctable) ## process entire bar! - gbl.seqCount = seqSave + gbl.seqCount = seqSave - # Adjust counters + # Adjust counters - gbl.barNum += 1 + gbl.barNum += 1 - if gbl.barNum > gbl.maxBars: - error("Capacity exceeded. Maxbar setting is %s. Use -m option." - % gbl.maxBars) + if gbl.barNum > gbl.maxBars: + error("Capacity exceeded. Maxbar setting is %s. Use -m option" + % gbl.maxBars) - gbl.tickOffset += (gbl.QperBar * gbl.BperQ) + gbl.tickOffset += (gbl.QperBar * gbl.BperQ) - gbl.seqCount = (gbl.seqCount+1) % gbl.seqSize + gbl.seqCount = (gbl.seqCount+1) % gbl.seqSize - """ Handle groove lists. If there is more than 1 entry - in the groove list, advance (circle). We don't have - to qualify grooves since they were verified when - this list was created. groovesList==None if there - is only one groove (or none). - """ + """ Handle groove lists. If there is more than 1 entry + in the groove list, advance (circle). We don't have + to qualify grooves since they were verified when + this list was created. groovesList==None if there + is only one groove (or none). + """ - if groovesList: - groovesCount += 1 - if groovesCount > len(groovesList)-1: - groovesCount = 0 - slot = groovesList[groovesCount] + if groovesList: + groovesCount += 1 + if groovesCount > len(groovesList)-1: + groovesCount = 0 + slot = groovesList[groovesCount] - if slot != gbl.currentGroove: - grooveDo(slot) + if slot != gbl.currentGroove: + grooveDo(slot) - gbl.lastGroove = gbl.currentGroove - gbl.currentGroove = slot + gbl.lastGroove = gbl.currentGroove + gbl.currentGroove = slot - if gbl.debug: - print "Groove (list) setting restored from '%s'." % slot + if gbl.debug: + print "Groove (list) setting restored from '%s'." % slot - # Enabled with the -r command line option + # Enabled with the -r command line option - if gbl.showrun: - print "%3d:" % gbl.barNum, - for c in l: - print c, - if lyrics: - print lyrics, - print + if gbl.showrun: + print "%3d:" % gbl.barNum, + for c in l: + print c, + if lyrics: + print lyrics, + print def parseZs(c, beat): - """ Parse a chord in a barline, create Ctable and strips 'z's. + """ Parse a chord in a barline, create Ctable and strips 'z's. - This is called only from the main parser, but it's - complicated (ugly) enough to have its own function. - """ + This is called only from the main parser, but it's + complicated (ugly) enough to have its own function. + """ - ctab = CTable(beat * gbl.BperQ) + ctab = CTable(beat * gbl.BperQ) - if 'z' in c: - c, r = c.split('z', 1) # chord name/track mute + if 'z' in c: + c, r = c.split('z', 1) # chord name/track mute - if not c: - if r=='!': # mute all for 'z!' - r='DCAWBS' - c='z' # dummy chord name - elif not r: # mute all tracks except Drum 'z' - r='CBAWS' - c='z' + if not c: + if r=='!': # mute all for 'z!' + r='DCAWBSR' + c='z' # dummy chord name + elif not r: # mute all tracks except Drum 'z' + r='CBAWSR' + c='z' - else: - error("To mute individual tracks you must " - "use a chord/z combination not '%s'." % l) + else: + error("To mute individual tracks you must " + "use a chord/z combination not '%s'" % r) - else: # illegal construct -- 'Cz!' - if r=='!': - error("'%sz!' is illegal. 'z!' mutes all tracks " - "so you can't include the chord." % c) + else: # illegal construct -- 'Cz!' + if r=='!': + error("'%sz!' is illegal. 'z!' mutes all tracks " + "so you can't include the chord" % c) - elif not r: - error("'%sz' is illegal. You must specify tracks " - "if you use a chord." % c ) + elif not r: + error("'%sz' is illegal. You must specify tracks " + "if you use a chord" % c ) - for v in r: - if v == 'C': - ctab.chordZ = 1 - elif v == 'B': - ctab.bassZ = 1 - elif v == 'A': - ctab.arpeggioZ = 1 - elif v == 'W': - ctab.walkZ = 1 - elif v == 'D': - ctab.drumZ = 1 - elif v == 'S': - ctab.scaleZ = 1 + for v in r: + if v == 'C': + ctab.chordZ = 1 + elif v == 'B': + ctab.bassZ = 1 + elif v == 'A': + ctab.arpeggioZ = 1 + elif v == 'W': + ctab.walkZ = 1 + elif v == 'D': + ctab.drumZ = 1 + elif v == 'S': + ctab.scaleZ = 1 + elif v == 'R': + ctab.ariaZ = 1 - else: - error("Unknown voice '%s' for rest in '%s'." % (v,r)) + else: + error("Unknown voice '%s' for rest in '%s'" % (v,r)) - ctab.chord = MMA.chords.ChordNotes(c) + ctab.chord = MMA.chords.ChordNotes(c) - return ctab + return ctab ################################################################## def allTracks(ln): - """ Apply track to all tracks. """ + """ Apply track to all tracks. """ - allTypes = ('BASS', 'CHORD', 'ARPEGGIO', 'SCALE', 'DRUM', 'WALK', 'MELODY', 'SOLO') - ttypes = [] + allTypes = ('BASS', 'CHORD', 'ARPEGGIO', 'SCALE', 'DRUM', 'WALK', 'MELODY', 'SOLO') + ttypes = [] - if len(ln) < 1: - error("AllTracks: argument required.") + if len(ln) < 1: + error("AllTracks: argument (track?) required") - i = 0 - while i < len(ln) and ln[i].upper() in allTypes: - ttypes.append(ln[i].upper()) - i += 1 + i = 0 + while i < len(ln) and ln[i].upper() in allTypes: + ttypes.append(ln[i].upper()) + i += 1 - if ttypes == []: - ttypes = allTypes + if ttypes == []: + ttypes = allTypes - if i>=len(ln): - error("AllTracks: Additional argument required.") + if i>=len(ln): + error("AllTracks: Additional argument (command?) required") - cmd = ln[i].upper() - args = i+1 + cmd = ln[i].upper() + args = i+1 - if not cmd in trackFuncs: - error("AllTracks: command '%s' doen't exist." % cmd) + if not cmd in trackFuncs: + error("AllTracks: command '%s' doen't exist" % cmd) - for n in gbl.tnames: - if not gbl.tnames[n].vtype in ttypes: - continue + for n in gbl.tnames: + if not gbl.tnames[n].vtype in ttypes: + continue - trackFuncs[cmd](n, ln[args:]) + trackFuncs[cmd](n, ln[args:]) ####################################### # Do-nothing functions def comment(ln): - pass + pass def repeatend(ln): - error("Repeatend/EndRepeat without Repeat.") + error("Repeatend/EndRepeat without Repeat") def repeatending(ln): - error("Repeatending without Repeat.") + error("Repeatending without Repeat") def endmset(ln): - error("EndMset/MSetEnd without If.") + error("EndMset/MSetEnd without If") def ifend(ln): - error("ENDIF without IF.") + error("ENDIF without IF") def ifelse(ln): - error("ELSE without IF.") + error("ELSE without IF") @@ -463,144 +468,144 @@ def ifelse(ln): def repeat(ln): - """ Repeat/RepeatEnd/RepeatEnding. + """ Repeat/RepeatEnd/RepeatEnding. Read input until a RepeatEnd is found. The entire chunk is pushed back into the input stream the correct number of times. This accounts for endings and nested repeats. - """ + """ - def repeatChunk(): - q=[] - qnum=[] - nesting = 0 + def repeatChunk(): + q=[] + qnum=[] + nesting = 0 - while 1: - l=gbl.inpath.read() + while 1: + l=gbl.inpath.read() - if not l: - error("EOF encountered processing Repeat.") + if not l: + error("EOF encountered processing Repeat") - act=l[0].upper() + act=l[0].upper() - if act=='REPEAT': - nesting += 1 + if act=='REPEAT': + nesting += 1 - elif act in ('REPEATEND', 'ENDREPEAT') and nesting: - nesting -= 1 + elif act in ('REPEATEND', 'ENDREPEAT') and nesting: + nesting -= 1 - elif act == 'REPEATENDING' and nesting: - pass + elif act == 'REPEATENDING' and nesting: + pass - elif act in ('REPEATEND', 'ENDREPEAT', 'REPEATENDING'): - return (q, qnum, act, l[1:]) + elif act in ('REPEATEND', 'ENDREPEAT', 'REPEATENDING'): + return (q, qnum, act, l[1:]) - q.append(l) - qnum.append(gbl.lineno) + q.append(l) + qnum.append(gbl.lineno) - stack=[] - stacknum=[] - main=[] - mainnum=[] - ending = 0 + stack=[] + stacknum=[] + main=[] + mainnum=[] + ending = 0 - if ln: - error("REPEAT takes no arguments.") + if ln: + error("REPEAT takes no arguments") - main, mainnum, act, l = repeatChunk() + main, mainnum, act, l = repeatChunk() - while 1: - if act in ('REPEATEND', 'ENDREPEAT'): - if l: - l=macros.expand(l) - if len(l) == 2 and l[0].upper() == 'NOWARN': - l=l[1:] - warn=0 - else: - warn=1 + while 1: + if act in ('REPEATEND', 'ENDREPEAT'): + if l: + l=macros.expand(l) + if len(l) == 2 and l[0].upper() == 'NOWARN': + l=l[1:] + warn=0 + else: + warn=1 - if len(l) != 1: - error("%s: Use [NoWarn] Count." % act) + if len(l) != 1: + error("%s: Use [NoWarn] Count" % act) - count=stoi(l[0], "%s takes an integer arg." % act) + count=stoi(l[0], "%s takes an integer arg" % act) - if count == 2 and warn: - warning("%s count of 2 duplicates default. Did you mean 3 or more?" % act) + if count == 2 and warn: + warning("%s count of 2 duplicates default. Did you mean 3 or more?" % act) - elif count == 1 and warn: - warning("%s count of 1 means NO REPEAT." % act) + elif count == 1 and warn: + warning("%s count of 1 means NO REPEAT" % act) - elif count == 0 and warn: - warning("%s count of 0, Skipping entire repeated section." % act) + elif count == 0 and warn: + warning("%s count of 0, Skipping entire repeated section" % act) - elif count < 0: - error("%s count must be 0 or greater." % act) + elif count < 0: + error("%s count must be 0 or greater" % act) - elif count > 10 and warn: - warning("%s is a large value for %s." % (count, act) ) + elif count > 10 and warn: + warning("%s is a large value for %s" % (count, act) ) - else: - count=2 + else: + count=2 - if not ending: - count += 1 - for c in range(count-1): - stack.extend(main) - stacknum.extend(mainnum) - gbl.inpath.push(stack, stacknum) - break + if not ending: + count += 1 + for c in range(count-1): + stack.extend(main) + stacknum.extend(mainnum) + gbl.inpath.push(stack, stacknum) + break - elif act == 'REPEATENDING': - ending = 1 + elif act == 'REPEATENDING': + ending = 1 - if l: - l=macros.expand(l) - if len(l) == 2 and l[0].upper() == 'NOWARN': - warn=0 - l=l[1:] - else: - warn=1 + if l: + l=macros.expand(l) + if len(l) == 2 and l[0].upper() == 'NOWARN': + warn=0 + l=l[1:] + else: + warn=1 - if len(l) != 1: - error("REPEATENDING: Use [NoWarn] Count.") + if len(l) != 1: + error("REPEATENDING: Use [NoWarn] Count") - count=stoi(l[0], "RepeatEnding takes an integer arg.") + count=stoi(l[0], "RepeatEnding takes an integer arg") - if count < 0: - error("RepeatEnding count must be postive, not %s" % count) + if count < 0: + error("RepeatEnding count must be postive, not '%s'" % count) - elif count == 0 and warn: - warning("RepeatEnding count of 0, skipping section.") + elif count == 0 and warn: + warning("RepeatEnding count of 0, skipping section") - elif count == 1 and warn: - warning("RepeatEnding count of 1 duplicates default.") + elif count == 1 and warn: + warning("RepeatEnding count of 1 duplicates default") - elif count > 10 and warn: - warning("%s is a large value for RepeatEnding." % count) - else: - count = 1 + elif count > 10 and warn: + warning("%s is a large value for RepeatEnding" % count) + else: + count = 1 - rpt, rptnum, act, l = repeatChunk() + rpt, rptnum, act, l = repeatChunk() - for c in range(count): - stack.extend(main) - stacknum.extend(mainnum) - stack.extend(rpt) - stacknum.extend(rptnum) + for c in range(count): + stack.extend(main) + stacknum.extend(mainnum) + stack.extend(rpt) + stacknum.extend(rptnum) - else: - error("Unexpected line in REPEAT") + else: + error("Unexpected line in REPEAT") def goto(ln): - if len(ln) != 1: - error("Usage: GOTO Label") - gbl.inpath.goto(ln[0].upper()) + if len(ln) != 1: + error("Usage: GOTO Label") + gbl.inpath.goto(ln[0].upper()) def eof(ln): - gbl.inpath.toEof() + gbl.inpath.toEof() ####################################### @@ -608,197 +613,194 @@ def eof(ln): def setTime(ln): - """ Set the 'time sig'. + """ Set the 'time sig'. We do restrict the time setting to the range of 1..12. No particular reason, but we do need some limit? Certainly it has to be greater than 0. - """ + """ - if len(ln) != 1: - error("Use: Time N.") + if len(ln) != 1: + error("Use: Time N") - n = stoi(ln[0], "Argument for time must be integer.") + n = stoi(ln[0], "Argument for time must be integer") - if n < 1 or n > 12: - error("Time (beats/bar) must be 1..12.") + if n < 1 or n > 12: + error("Time (beats/bar) must be 1..12") - # If no change, just ignore this. + # If no change, just ignore this. - if gbl.QperBar != n: - gbl.QperBar = int(n) + if gbl.QperBar != n: + gbl.QperBar = int(n) - # Time changes zap all predfined sequences + # Time changes zap all predfined sequences - for a in gbl.tnames.values(): - a.clearSequence() + for a in gbl.tnames.values(): + a.clearSequence() def tempo(ln): - """ Set tempo. """ + """ Set tempo. """ - if not ln or len(ln) >2: - error("Use: Tempo [*,+,-]BperM [BARS].") + if not ln or len(ln) >2: + error("Use: Tempo [*,+,-]BperM [BARS]") - # Get new value. + # Get new value. - a = ln[0][0] - if a in "+-*": - v = stof(ln[0][1:], "Tempo expecting value for rate adjustment, not '%s'." % ln[0]) - if a == '-': - v = gbl.tempo - v - elif a == '+': - v += gbl.tempo - elif a == '*': - v *= gbl.tempo + a = ln[0][0] + if a in "+-*": + v = stof(ln[0][1:], "Tempo expecting value for rate adjustment, not '%s'" % ln[0]) + if a == '-': + v = gbl.tempo - v + elif a == '+': + v += gbl.tempo + elif a == '*': + v *= gbl.tempo - else: - v = stof(ln[0], "Tempo expecting rate, not '%s'." % ln[0]) + else: + v = stof(ln[0], "Tempo expecting rate, not '%s'" % ln[0]) - # is this immediate or over time? + # is this immediate or over time? - if len(ln) == 1: - gbl.tempo = int(v) - gbl.mtrks[0].addTempo(gbl.tickOffset, gbl.tempo) - if gbl.debug: - print "Set Tempo to %s" % gbl.tempo + if len(ln) == 1: + gbl.tempo = int(v) + gbl.mtrks[0].addTempo(gbl.tickOffset, gbl.tempo) + if gbl.debug: + print "Set Tempo to %s" % gbl.tempo - else: # Do a tempo change over bar count - bars = ln[1] + else: # Do a tempo change over bar count + bars = ln[1] - bars = stof(bars, "Expecting value, not %s" % bars ) - numbeats = int(bars * gbl.QperBar) + bars = stof(bars, "Expecting value, not %s" % bars ) + numbeats = int(bars * gbl.QperBar) - if numbeats < 1: - error("Beat count must be greater than 1.") + if numbeats < 1: + error("Beat count must be greater than 1") - # Vary the rate in the meta track + # Vary the rate in the meta track - tincr = (v - gbl.tempo) / float(numbeats) # incr per beat - bstart = gbl.tickOffset # start - boff = 0 - tempo = gbl.tempo + tincr = (v - gbl.tempo) / float(numbeats) # incr per beat + bstart = gbl.tickOffset # start + boff = 0 + tempo = gbl.tempo - for n in range(numbeats): - tempo += tincr - if tempo: - gbl.mtrks[0].addTempo(bstart + boff, int(tempo)) - boff += gbl.BperQ + for n in range(numbeats): + tempo += tincr + if tempo: + gbl.mtrks[0].addTempo(bstart + boff, int(tempo)) + boff += gbl.BperQ - if tempo != v: - gbl.mtrks[0].addTempo(bstart + boff, int(v) ) + if tempo != v: + gbl.mtrks[0].addTempo(bstart + boff, int(v) ) - gbl.tempo = int(v) + gbl.tempo = int(v) - if gbl.debug: - print "Set future Tempo to %s over %s beats" % \ - ( int(tempo), numbeats) + if gbl.debug: + print "Set future Tempo to %s over %s beats" % \ + ( int(tempo), numbeats) def beatAdjust(ln): - """ Delete or insert some beats into the sequence. + """ Delete or insert some beats into the sequence. - This just adjusts the current song position. Nothing is - lost or added to the actual file. - """ + This just adjusts the current song position. Nothing is + lost or added to the actual file. + """ - if len(ln) != 1: - error("Use: BeatAdjust NN") + if len(ln) != 1: + error("Use: BeatAdjust NN") - adj = stof(ln[0], "Expecting a value (not %s) for BeatAdjust." % ln[0]) + adj = stof(ln[0], "Expecting a value (not %s) for BeatAdjust" % ln[0]) - gbl.tickOffset += int(adj * gbl.BperQ) + gbl.tickOffset += int(adj * gbl.BperQ) - if gbl.debug: - print "BeatAdjust: inserted %s at bar %s." % (adj, gbl.barNum + 1) + if gbl.debug: + print "BeatAdjust: inserted %s at bar %s." % (adj, gbl.barNum + 1) def cut(ln): - """ Insert a all-note-off into all tracks. """ + """ Insert a all-note-off into all tracks. """ - if not len(ln): - ln=['0'] + if not len(ln): + ln=['0'] - if len(ln) != 1: - error("Use: Cut Offset") + if len(ln) != 1: + error("Use: Cut Offset") - """ Loop though all the tracks. Note that trackCut() checks + """ Loop though all the tracks. Note that trackCut() checks to make sure that there is a need to insert in specified track. In this loop we create a list of channels as we loop though all the tracks, skipping over any duplicate channels or tracks with no channel assigned. - """ + """ - l=[] - for t in sorted(gbl.tnames.keys()): - c = gbl.tnames[t].channel - if not c or c in l: - continue - l.append(c) - trackCut(t, ln) + l=[] + for t in sorted(gbl.tnames.keys()): + c = gbl.tnames[t].channel + if not c or c in l: + continue + l.append(c) + trackCut(t, ln) def fermata(ln): - """ Apply a fermata timing to the specified beat. """ + """ Apply a fermata timing to the specified beat. """ - if len(ln) != 3: - error("Use: Fermata 'offset' 'duration' 'adjustment'") + if len(ln) != 3: + error("Use: Fermata 'offset' 'duration' 'adjustment'") - offset = stof(ln[0], "Expecting a value (not '%s') " - "for Fermata Offset." % ln[0] ) + offset = stof(ln[0], "Expecting a value (not '%s') " + "for Fermata Offset" % ln[0] ) - if offset < -gbl.QperBar or offset > gbl.QperBar: - warning("Fermata: %s is a large beat offset." % offset) + if offset < -gbl.QperBar or offset > gbl.QperBar: + warning("Fermata: %s is a large beat offset" % offset) - dur = stof(ln[1], "Expecting a value (not '%s') for Fermata " - "Duration." % ln[1]) + dur = stof(ln[1], "Expecting a value (not '%s') for Fermata Duration" % ln[1]) - if dur <= 0: - error("Fermata duration must be greater than 0.") + if dur <= 0: + error("Fermata duration must be greater than 0") - if dur > gbl.QperBar: - warning("Fermata: %s is a large duration.") + if dur > gbl.QperBar: + warning("Fermata: %s is a large duration" % dur) - adj = stof(ln[2], "Expecting a value (not '%s') for Fermata " - "Adjustment." % ln[2]) + adj = stof(ln[2], "Expecting a value (not '%s') for Fermata Adjustment" % ln[2]) - if adj< 100: - warning("Fermata: Adjustment less than 100 is shortening beat value.") + if adj< 100: + warning("Fermata: Adjustment less than 100 is shortening beat value") - if adj == 100: - error("Fermata: using value of 100 makes no difference, " - "must be an error.") + if adj == 100: + error("Fermata: using value of 100 makes no difference, must be an error") - moff=int(gbl.tickOffset + (gbl.BperQ * offset)) + moff=int(gbl.tickOffset + (gbl.BperQ * offset)) - if moff < 0: - error("Fermata offset comes before track start.") + if moff < 0: + error("Fermata offset comes before track start") - gbl.mtrks[0].addTempo(moff, int(gbl.tempo / (adj/100)) ) + gbl.mtrks[0].addTempo(moff, int(gbl.tempo / (adj/100)) ) - tickDur = int(gbl.BperQ * dur) + tickDur = int(gbl.BperQ * dur) - gbl.mtrks[0].addTempo(moff + tickDur, gbl.tempo) + gbl.mtrks[0].addTempo(moff + tickDur, gbl.tempo) - # Clear out NoteOn events in all tracks + # Clear out NoteOn events in all tracks - if offset < 0: - start = moff + int(.05 * gbl.BperQ) - end = moff + tickDur - int(.05 * gbl.BperQ) + if offset < 0: + start = moff + int(.05 * gbl.BperQ) + end = moff + tickDur - int(.05 * gbl.BperQ) - for n, tr in gbl.mtrks.items(): - if n <= 0: continue # skip meta track - tr.zapRangeTrack(start, end ) + for n, tr in gbl.mtrks.items(): + if n <= 0: continue # skip meta track + tr.zapRangeTrack(start, end ) - if gbl.debug: - print "Fermata: Beat %s, Duration %s, Change %s, Bar %s" % \ - (offset, dur, adj, gbl.barNum + 1) - if offset < 0: - print "\tNoteOn Events removed in tick range %s to %s" \ - % (start, end) + if gbl.debug: + print "Fermata: Beat %s, Duration %s, Change %s, Bar %s" % \ + (offset, dur, adj, gbl.barNum + 1) + if offset < 0: + print "\tNoteOn Events removed in tick range %s to %s" \ + % (start, end) ####################################### @@ -806,304 +808,332 @@ def fermata(ln): def grooveDefine(ln): - """ Define a groove. + """ Define a groove. - Current settings are assigned to a groove name. - """ + Current settings are assigned to a groove name. + """ - if not len(ln): - error("Use: DefGroove Name") + if not len(ln): + error("Use: DefGroove Name") - slot=ln[0].upper() + slot=ln[0].upper() - # Slot names can't contain a '/' (reserved) or be an integer (used in groove select). + # Slot names can't contain a '/' (reserved) or be an integer (used in groove select). - if '/' in slot: - error("The '/' is not permitted in a groove name.") + if '/' in slot: + error("The '/' is not permitted in a groove name") - if slot.isdigit(): - error("Invalid slot name '%s'. Cannot be only digits." % slot) + if slot.isdigit(): + error("Invalid slot name '%s'. Cannot be only digits" % slot) - grooveDefineDo(slot) + grooveDefineDo(slot) - if gbl.debug: - print "Groove settings saved to '%s'." % slot + if gbl.debug: + print "Groove settings saved to '%s'." % slot - if gbl.makeGrvDefs: - MMA.auto.updateGrooveList(slot) + if gbl.makeGrvDefs: + MMA.auto.updateGrooveList(slot) - if len(ln) > 1: - MMA.docs.docDefine(ln) + if len(ln) > 1: + MMA.docs.docDefine(ln) def grooveDefineDo(slot): - for n in gbl.tnames.values(): - n.saveGroove(slot) + for n in gbl.tnames.values(): + n.saveGroove(slot) - gbl.settingsGroove[slot] = { - 'SEQSIZE': gbl.seqSize, - 'SEQRNDWT': seqRndWeight[:], - 'QPERBAR': gbl.QperBar, - 'SEQRND': gbl.seqRnd[:], - 'TIMESIG': MMA.midi.timeSig.get(), - '81': MMA.notelen.noteLenTable['81'], - '82': MMA.notelen.noteLenTable['82'], - 'SWINGMODE': gbl.swingMode , - 'SWINGSKEW': gbl.swingSkew, - 'VRATIO': (MMA.volume.vTRatio, MMA.volume.vMRatio)} + gbl.settingsGroove[slot] = { + 'SEQSIZE': gbl.seqSize, + 'SEQRNDWT': seqRndWeight[:], + 'QPERBAR': gbl.QperBar, + 'SEQRND': gbl.seqRnd[:], + 'TIMESIG': MMA.midi.timeSig.get(), + '81': MMA.notelen.noteLenTable['81'], + '82': MMA.notelen.noteLenTable['82'], + 'SWINGMODE': gbl.swingMode , + 'SWINGSKEW': gbl.swingSkew, + 'VRATIO': (MMA.volume.vTRatio, MMA.volume.vMRatio)} def groove(ln): - """ Select a previously defined groove. """ + """ Select a previously defined groove. """ - global groovesList, groovesCount + global groovesList, groovesCount - if not ln: - error("Groove: needs agrument(s)") + if not ln: + error("Groove: needs agrument(s)") - tmpList =[] + tmpList =[] - if ln[0].isdigit(): - wh=stoi(ln[0]) - if wh<1: - error("Groove selection must be > 0, not '%s'." % wh) - ln=ln[1:] - else: - wh = None + if ln[0].isdigit(): + wh=stoi(ln[0]) + if wh<1: + error("Groove selection must be > 0, not '%s'" % wh) + ln=ln[1:] + else: + wh = None - for slot in ln: - slot = slot.upper() - if slot == "/": - if len(tmpList): - slot=tmpList[-1] - else: - error("A previous groove name is needed before a '/'.") + for slot in ln: + slot = slot.upper() + if slot == "/": + if len(tmpList): + slot=tmpList[-1] + else: + error("A previous groove name is needed before a '/'") - if not slot in gbl.settingsGroove: + if not slot in gbl.settingsGroove: - if gbl.debug: - print "Groove '%s' not defined. Trying auto-load from libraries" \ - % slot + if gbl.debug: + print "Groove '%s' not defined. Trying auto-load from libraries" \ + % slot - l=MMA.auto.loadGrooveDir(slot) # name of the lib file with groove + l=MMA.auto.loadGrooveDir(slot) # name of the lib file with groove - if l: - if gbl.debug: - print "Attempting to load groove '%s' from '%s'." \ - % (slot, l) + if l: + if gbl.debug: + print "Attempting to load groove '%s' from '%s'." \ + % (slot, l) - usefile([os.path.join(gbl.autoLib, l)]) + usefile([os.path.join(gbl.autoLib, l)]) - if not slot in gbl.settingsGroove: - error("Groove '%s' not found. Have libraries changed " - "since last 'mma -g' run?" % slot) + if not slot in gbl.settingsGroove: + error("Groove '%s' not found. Have libraries changed " + "since last 'mma -g' run?" % slot) - else: - error("Groove '%s' could not be found in memory or library files" % slot ) + else: + error("Groove '%s' could not be found in memory or library files" % slot ) - tmpList.append(slot) + tmpList.append(slot) - if not len(tmpList): - error("Use: Groove [selection] Name [...]") + if not len(tmpList): + error("Use: Groove [selection] Name [...]") - """ If the first arg to list was an int() (ie: 3 groove1 groove2 grooveFoo) - we select from the list. After the selection, we reset the list to be - just the selected entry. This was, if there are multiple groove names without - a leading int() we process the list as groove list changing with each bar. - """ + """ If the first arg to list was an int() (ie: 3 groove1 groove2 grooveFoo) + we select from the list. After the selection, we reset the list to be + just the selected entry. This was, if there are multiple groove names without + a leading int() we process the list as groove list changing with each bar. + """ - if wh: - wh = (wh-1) % len(tmpList) - tmpList=tmpList[wh:wh+1] + if wh: + wh = (wh-1) % len(tmpList) + tmpList=tmpList[wh:wh+1] - slot=tmpList[0] - grooveDo(slot) + slot=tmpList[0] + grooveDo(slot) - groovesCount = 0 - if len(tmpList)==1: - groovesList=None - else: - groovesList=tmpList + groovesCount = 0 + if len(tmpList)==1: + groovesList=None + else: + groovesList=tmpList - gbl.lastGroove = gbl.currentGroove - gbl.currentGroove = slot - if gbl.lastGroove == '': - gbl.lastGroove = slot + gbl.lastGroove = gbl.currentGroove + gbl.currentGroove = slot + if gbl.lastGroove == '': + gbl.lastGroove = slot - if gbl.debug: - print "Groove settings restored from '%s'." % slot + if gbl.debug: + print "Groove settings restored from '%s'." % slot def grooveDo(slot): - """ This is separate from groove() so we can call it from - usefile() with a qualified name. """ + """ This is separate from groove() so we can call it from + usefile() with a qualified name. """ - global seqRndWeight + global seqRndWeight - oldSeqSize = gbl.seqSize + oldSeqSize = gbl.seqSize - g=gbl.settingsGroove[slot] + g=gbl.settingsGroove[slot] - gbl.seqSize = g['SEQSIZE'] - seqRndWeight = g['SEQRNDWT'] - gbl.QperBar = g['QPERBAR'] - gbl.seqRnd = g['SEQRND'] - MMA.midi.timeSig.set( *g['TIMESIG']) # passing tuple as 2 args. - MMA.notelen.noteLenTable['81'] = g['81'] - MMA.notelen.noteLenTable['82'] = g['82'] - gbl.swingMode = g['SWINGMODE'] - gbl.swingSkew = g['SWINGSKEW'] - MMA.volume.vTRatio, MMA.volume.vMRatio = g['VRATIO'] + gbl.seqSize = g['SEQSIZE'] + seqRndWeight = g['SEQRNDWT'] + gbl.QperBar = g['QPERBAR'] + gbl.seqRnd = g['SEQRND'] + MMA.midi.timeSig.set( *g['TIMESIG']) # passing tuple as 2 args. + MMA.notelen.noteLenTable['81'] = g['81'] + MMA.notelen.noteLenTable['82'] = g['82'] + gbl.swingMode = g['SWINGMODE'] + gbl.swingSkew = g['SWINGSKEW'] + MMA.volume.vTRatio, MMA.volume.vMRatio = g['VRATIO'] - for n in gbl.tnames.values(): - n.restoreGroove(slot) + for n in gbl.tnames.values(): + n.restoreGroove(slot) - """ This is important! Tracks NOT overwritten by saved grooves way - have the wrong sequence length. I don't see any easy way to hit - just the unchanged/unrestored tracks so we do them all. - Only done if a change in seqsize ... doesn't take long to be safe. - """ + """ This is important! Tracks NOT overwritten by saved grooves way + have the wrong sequence length. I don't see any easy way to hit + just the unchanged/unrestored tracks so we do them all. + Only done if a change in seqsize ... doesn't take long to be safe. + """ - if oldSeqSize != gbl.seqSize: - for a in gbl.tnames.values(): - a.setSeqSize() + if oldSeqSize != gbl.seqSize: + for a in gbl.tnames.values(): + a.setSeqSize() - seqRndWeight = MMA.pat.seqBump(seqRndWeight) + seqRndWeight = MMA.pat.seqBump(seqRndWeight) - gbl.seqCount = 0 + gbl.seqCount = 0 +def grooveClear(ln): + """ Delete all previously loaded grooves from memory.""" + + global groovesList, groovesCount + + if ln: + error("GrooveClear does not have any arguments.") + + groovesList = {} + groovesCount = 0 + + try: + a= gbl.settingsGroove[gmagic] + except: + a=None + + gbl.settingsGroove={} + + if a: + gbl.settingsGroove[gmagic]=a + + gbl.lastGroove = '' + gbl.currentGroove = '' + + + if gbl.debug: + print "All grooves deleted." + ####################################### # File and I/O def include(ln): - """ Include a file. """ + """ Include a file. """ - global beginData + global beginData - if beginData: - error("INCLUDE not permitted in Begin/End block") + if beginData: + error("INCLUDE not permitted in Begin/End block") - if len(ln) != 1: - error("Use: Include FILE" ) + if len(ln) != 1: + error("Use: Include FILE" ) - fn = MMA.file.locFile(ln[0], gbl.incPath) - if not fn: - error("Could not find include file '%s'." % ln) + fn = MMA.file.locFile(ln[0], gbl.incPath) + if not fn: + error("Could not find include file '%s'" % ln) - else: - parseFile(fn) + else: + parseFile(fn) def usefile(ln): - """ Include a library file. """ + """ Include a library file. """ - global beginData + global beginData - if beginData: - error("USE not permitted in Begin/End block") + if beginData: + error("USE not permitted in Begin/End block") - if len(ln) != 1: - error("Use: Use FILE" ) + if len(ln) != 1: + error("Use: Use FILE") - ln = ln[0] - fn = MMA.file.locFile(ln, gbl.libPath) + ln = ln[0] + fn = MMA.file.locFile(ln, gbl.libPath) - if not fn: - error("Unable to locate library file '%s'." % ln) + if not fn: + error("Unable to locate library file '%s'" % ln) - """ USE saves current state, just like defining a groove. + """ USE saves current state, just like defining a groove. Here we use a magic number which can't be created with a defgroove ('cause it's an integer). Save, read, restore. - """ + """ - slot = 9988 - grooveDefineDo(slot) - parseFile(fn) - grooveDo(slot) + slot = gmagic + grooveDefineDo(slot) + parseFile(fn) + grooveDo(slot) def mmastart(ln): - if not ln: - error ("Use: MMAstart FILE [file...]") + if not ln: + error ("Use: MMAstart FILE [file...]") - gbl.mmaStart.extend(ln) + gbl.mmaStart.extend(ln) - if gbl.debug: - print "MMAstart set to:", - printList(ln) + if gbl.debug: + print "MMAstart set to:", + printList(ln) def mmaend(ln): - if not ln: - error ("Use: MMAend FILE [file...]") + if not ln: + error ("Use: MMAend FILE [file...]") - gbl.mmaEnd.extend(ln) + gbl.mmaEnd.extend(ln) - if gbl.debug: - print "MMAend set to:", - printList(ln) + if gbl.debug: + print "MMAend set to:", + printList(ln) def setLibPath(ln): - """ Set the LibPath variable. """ + """ Set the LibPath variable. """ - if len(ln) > 1: - error("Only one path can be entered for LibPath.") + if len(ln) > 1: + error("Only one path can be entered for LibPath") - f = os.path.expanduser(ln[0]) + f = os.path.expanduser(ln[0]) - if gbl.debug: - print "LibPath set to", f + if gbl.debug: + print "LibPath set to", f - gbl.libPath = f + gbl.libPath = f def setAutoPath(ln): - """ Set the autoPath variable. """ + """ Set the autoPath variable. """ - if len(ln) > 1: - error("Only one path can be entered for AutoLibPath.") + if len(ln) > 1: + error("Only one path can be entered for AutoLibPath") - f = os.path.expanduser(ln[0]) + f = os.path.expanduser(ln[0]) - MMA.auto.grooveDir = {} + MMA.auto.grooveDir = {} - # To avoid conflicts, delete all existing grooves (current seq not effected) + # To avoid conflicts, delete all existing grooves (current seq not effected) - gbl.settingsGroove = {} - gbl.lastGroove = '' - gbl.currentGroove = '' + gbl.settingsGroove = {} + gbl.lastGroove = '' + gbl.currentGroove = '' - if gbl.debug: - print "AutoLibPath set to", f + if gbl.debug: + print "AutoLibPath set to", f - gbl.autoLib = f + gbl.autoLib = f def setIncPath(ln): - """ Set the IncPath variable. """ + """ Set the IncPath variable. """ - if len(ln)>1: - error("Only one path is permitted in SetIncPath.") + if len(ln)>1: + error("Only one path is permitted in SetIncPath") - f = os.path.expanduser(ln[0]) + f = os.path.expanduser(ln[0]) - if gbl.debug: - print "IncPath set to", f + if gbl.debug: + print "IncPath set to", f - gbl.incPath=f + gbl.incPath=f def setOutPath(ln): - """ Set the Outpath variable. """ + """ Set the Outpath variable. """ - if not ln: - gbl.outPath = "" + if not ln: + gbl.outPath = "" - elif len(ln) > 1: - error ("Use: SetOutPath PATH.") + elif len(ln) > 1: + error ("Use: SetOutPath PATH") - else: - gbl.outPath = os.path.expanduser(ln[0]) + else: + gbl.outPath = os.path.expanduser(ln[0]) @@ -1111,306 +1141,306 @@ def setOutPath(ln): # Sequence def seqsize(ln): - """ Set the length of sequences. """ + """ Set the length of sequences. """ - global seqRndWeight + global seqRndWeight - if len(ln) !=1: - error("Usage 'SeqSize N'.") + if len(ln) !=1: + error("Usage 'SeqSize N'") - n = stoi(ln[0], "Argument for SeqSize must be integer.") + n = stoi(ln[0], "Argument for SeqSize must be integer") - # Setting the sequence size always resets the seq point + # Setting the sequence size always resets the seq point - gbl.seqCount = 0 + gbl.seqCount = 0 - """ Now set the sequence size for each track. The class call - will expand/contract existing patterns to match the new - size. - """ + """ Now set the sequence size for each track. The class call + will expand/contract existing patterns to match the new + size. + """ - if n != gbl.seqSize: - gbl.seqSize = n - for a in gbl.tnames.values(): - a.setSeqSize() + if n != gbl.seqSize: + gbl.seqSize = n + for a in gbl.tnames.values(): + a.setSeqSize() - seqRndWeight = seqBump(seqRndWeight) + seqRndWeight = seqBump(seqRndWeight) - if gbl.debug: - print "Set SeqSize to ", n + if gbl.debug: + print "Set SeqSize to ", n def seq(ln): - """ Set the sequence point. """ + """ Set the sequence point. """ - if len(ln) == 0: - s = 0 - elif len(ln)==1: - s = stoi(ln[0], "Expecting integer value after SEQ") - else: - error("Use: SEQ or SEQ NN to reset seq point.") + if len(ln) == 0: + s = 0 + elif len(ln)==1: + s = stoi(ln[0], "Expecting integer value after SEQ") + else: + error("Use: SEQ or SEQ NN to reset seq point") - if s > gbl.seqSize: - error("Sequence size is '%d', you can't set to '%d'." % - (gbl.seqSize, s)) + if s > gbl.seqSize: + error("Sequence size is '%d', you can't set to '%d'" % + (gbl.seqSize, s)) - if s==0: - s=1 + if s==0: + s=1 - if s<0: - error("Seq parm must be greater than 0, not %s", s) + if s<0: + error("Seq parm must be greater than 0, not %s", s) - gbl.seqCount = s-1 + gbl.seqCount = s-1 - if gbl.seqRnd[0] == 1: - warning("SeqRnd has been disabled by a Seq command.") - seqRnd = [0] + if gbl.seqRnd[0] == 1: + warning("SeqRnd has been disabled by a Seq command") + seqRnd = [0] def seqClear(ln): - """ Clear all sequences (except SOLO tracks). """ + """ Clear all sequences (except SOLO tracks). """ - if ln: - error ("Use: 'SeqClear' with no args") + if ln: + error ("Use: 'SeqClear' with no args") - for n in gbl.tnames.values(): - if n.vtype != "SOLO": - n.clearSequence() - MMA.volume.futureVol = [] + for n in gbl.tnames.values(): + if n.vtype != "SOLO": + n.clearSequence() + MMA.volume.futureVol = [] - setSeqRndWeight(['1']) + setSeqRndWeight(['1']) def setSeqRnd(ln): - """ Set random order for all tracks. """ + """ Set random order for all tracks. """ - emsg = "use [ON, OFF | TrackList ]." - if not ln: - error("SeqRnd:" + emsg) + emsg = "use [ON, OFF | TrackList ]" + if not ln: + error("SeqRnd:" + emsg) - a=ln[0].upper() + a=ln[0].upper() - if a in ("ON", "1") and len(ln) == 1: - gbl.seqRnd = [1] + if a in ("ON", "1") and len(ln) == 1: + gbl.seqRnd = [1] - elif a in ("OFF", "0") and len(ln) == 1: - gbl.seqRnd = [0] + elif a in ("OFF", "0") and len(ln) == 1: + gbl.seqRnd = [0] - else: - gbl.seqRnd=[2] - for a in ln: - a = a.upper() - if not a in gbl.tnames: - error("SeqRnd: Track '%s' does not exist, %s." % (a, emsg)) - if a in gbl.seqRnd: - error("SeqRnd: Duplicate track '%s' specified, %s" % (a, emsg)) - gbl.seqRnd.append(a) + else: + gbl.seqRnd=[2] + for a in ln: + a = a.upper() + if not a in gbl.tnames: + error("SeqRnd: Track '%s' does not exist, %s" % (a, emsg)) + if a in gbl.seqRnd: + error("SeqRnd: Duplicate track '%s' specified, %s" % (a, emsg)) + gbl.seqRnd.append(a) - if gbl.debug: - print "SeqRnd:", - if gbl.seqRnd[0] == 2: - for a in gbl.seqRnd[1:]: - print a, - print - else: - if gbl.seqRnd[0] == 1: - print "On" - else: - print "Off" + if gbl.debug: + print "SeqRnd:", + if gbl.seqRnd[0] == 2: + for a in gbl.seqRnd[1:]: + print a, + print + else: + if gbl.seqRnd[0] == 1: + print "On" + else: + print "Off" def setSeqRndWeight(ln): - """ Set global rnd weight. """ + """ Set global rnd weight. """ - global seqRndWeight + global seqRndWeight - if not ln: - error("Use: RndWeight .") + if not ln: + error("Use: RndWeight ") - tmp = [] - for n in ln: - n = stoi(n) - if n < 0: error("RndWeight: Values must be 0 or greater.") - tmp.append(n) + tmp = [] + for n in ln: + n = stoi(n) + if n < 0: error("RndWeight: Values must be 0 or greater") + tmp.append(n) - seqRndWeight = seqBump(tmp) + seqRndWeight = seqBump(tmp) - if gbl.debug: - print "RndWeight: ", - printList(seqRndWeight) + if gbl.debug: + print "RndWeight: ", + printList(seqRndWeight) def restart(ln): - """ Restart all tracks to almost-default condidions. """ + """ Restart all tracks to almost-default condidions. """ - if ln: - error ("Use: 'Restart' with no args") + if ln: + error ("Use: 'Restart' with no args") - for n in gbl.tnames.values(): - n.restart() + for n in gbl.tnames.values(): + n.restart() ####################################### # Midi def midiMarker(ln): - """ Parse off midi marker. """ + """ Parse off midi marker. """ - if len(ln) == 2: - offset = stof(ln[0]) - msg = ln[1] - elif len(ln) == 1: - offset = 0 - msg = ln[0] - else: - error("Usage: MidiMark [offset] Label.") + if len(ln) == 2: + offset = stof(ln[0]) + msg = ln[1] + elif len(ln) == 1: + offset = 0 + msg = ln[0] + else: + error("Usage: MidiMark [offset] Label") - offset = int(gbl.tickOffset + (gbl.BperQ * offset)) - if offset < 0: - error("MidiMark offset points before start of file.") + offset = int(gbl.tickOffset + (gbl.BperQ * offset)) + if offset < 0: + error("MidiMark offset points before start of file") - gbl.mtrks[0].addMarker(offset, msg) + gbl.mtrks[0].addMarker(offset, msg) def rawMidi(ln): - """ Send hex bytes as raw midi stream. """ + """ Send hex bytes as raw midi stream. """ - mb='' - for a in ln: - a=stoi(a) + mb='' + for a in ln: + a=stoi(a) - if a<0 or a >0xff: - error("All values must be in the range " - "0 to 0xff, not '%s'" % a) + if a<0 or a >0xff: + error("All values must be in the range " + "0 to 0xff, not '%s'" % a) - mb += chr(a) + mb += chr(a) - gbl.mtrks[0].addToTrack(gbl.tickOffset, mb) + gbl.mtrks[0].addToTrack(gbl.tickOffset, mb) - if gbl.debug: - print "Inserted raw midi in metatrack: ", - for b in mb: - print '%02x' % ord(b), - print + if gbl.debug: + print "Inserted raw midi in metatrack: ", + for b in mb: + print '%02x' % ord(b), + print def mdefine(ln): - """ Set a midi seq pattern. """ + """ Set a midi seq pattern. """ - if not ln: - error("MDefine needs arguments.") + if not ln: + error("MDefine needs arguments") - name = ln[0] - if name.startswith('_'): - error("Names with a leading underscore are reserved.") + name = ln[0] + if name.startswith('_'): + error("Names with a leading underscore are reserved") - if name.upper() == 'Z': - error("The name 'Z' is reserved.") + if name.upper() == 'Z': + error("The name 'Z' is reserved") - MMA.mdefine.mdef.set(name, ' '.join(ln[1:])) + MMA.mdefine.mdef.set(name, ' '.join(ln[1:])) def setMidiFileType(ln): - """ Set some MIDI file generation flags. """ + """ Set some MIDI file generation flags. """ - if not ln: - error("USE: MidiFile [SMF=0/1] [RUNNING=0/1]") + if not ln: + error("USE: MidiFile [SMF=0/1] [RUNNING=0/1]") - for l in ln: - try: - mode, val = l.upper().split('=') - except: - error("Each arg must contain an '=', not '%s'." % l) + for l in ln: + try: + mode, val = l.upper().split('=') + except: + error("Each arg must contain an '=', not '%s'" % l) - if mode == 'SMF': - if val == '0': - gbl.midiFileType = 0 - elif val == '1': - gbl.midiFileType = 1 - else: - error("Use: MIDIFile SMF=0/1") + if mode == 'SMF': + if val == '0': + gbl.midiFileType = 0 + elif val == '1': + gbl.midiFileType = 1 + else: + error("Use: MIDIFile SMF=0/1") - if gbl.debug: - print "Midi Filetype set to", gbl.midiFileType + if gbl.debug: + print "Midi Filetype set to", gbl.midiFileType - elif mode == 'RUNNING': - if val == '0': - gbl.runningStatus = 0 - elif val == '1': - gbl.runningStatus = 1 - else: - error("Use: MIDIFile RUNNING=0/1") + elif mode == 'RUNNING': + if val == '0': + gbl.runningStatus = 0 + elif val == '1': + gbl.runningStatus = 1 + else: + error("Use: MIDIFile RUNNING=0/1") - if gbl.debug: - print "Midi Running Status Generation set to", - if gbl.runningStatus: - print 'ON (Default)' - else: - print 'OFF' + if gbl.debug: + print "Midi Running Status Generation set to", + if gbl.runningStatus: + print 'ON (Default)' + else: + print 'OFF' - else: - error("Use: MIDIFile [SMF=0/1] [RUNNING=0/1]") + else: + error("Use: MIDIFile [SMF=0/1] [RUNNING=0/1]") def setChPref(ln): - """ Set MIDI Channel Preference. """ + """ Set MIDI Channel Preference. """ - if not ln: - error("Use: ChannelPref TRACKNAME=CHANNEL [...]") + if not ln: + error("Use: ChannelPref TRACKNAME=CHANNEL [...]") - for i in ln: - if '=' not in i: - error("Each item in ChannelPref must have an '='.") + for i in ln: + if '=' not in i: + error("Each item in ChannelPref must have an '='") - n,c = i.split('=') + n,c = i.split('=') - c = stoi(c, "Expecting an integer for ChannelPref, not '%s'." % c) + c = stoi(c, "Expecting an integer for ChannelPref, not '%s'" % c) - if c<1 or c>16: - error("Channel for ChannelPref must be 1..16, not %s." % c) + if c<1 or c>16: + error("Channel for ChannelPref must be 1..16, not %s" % c) - gbl.midiChPrefs[n.upper()]=c + gbl.midiChPrefs[n.upper()]=c - if gbl.debug: - print "ChannelPref:", - for n,c in gbl.midiChPrefs.items(): - print "%s=%s" % (n,c), - print + if gbl.debug: + print "ChannelPref:", + for n,c in gbl.midiChPrefs.items(): + print "%s=%s" % (n,c), + print def setTimeSig(ln): - """ Set the midi time signature. """ + """ Set the midi time signature. """ - if len(ln) == 1: - a=ln[0].upper() - if a == 'COMMON': - ln=('4','4') - elif a == 'CUT': - ln=('2','2') + if len(ln) == 1: + a=ln[0].upper() + if a == 'COMMON': + ln=('4','4') + elif a == 'CUT': + ln=('2','2') - if len(ln) != 2: - error("TimeSig: Usage (num dem) or ('cut' or 'common').") + if len(ln) != 2: + error("TimeSig: Usage (num dem) or ('cut' or 'common')") - nn = stoi(ln[0]) + nn = stoi(ln[0]) - if nn<1 or nn>126: - error("Timesig NN must be 1..126") + if nn<1 or nn>126: + error("Timesig NN must be 1..126") - dd = stoi(ln[1]) - if dd == 1: dd = 0 - elif dd == 2: dd = 1 - elif dd == 4: dd = 2 - elif dd == 8: dd = 3 - elif dd == 16: dd = 4 - elif dd == 32: dd = 5 - elif dd == 64: dd = 6 - else: - error("Unknown value for timesig denominator") + dd = stoi(ln[1]) + if dd == 1: dd = 0 + elif dd == 2: dd = 1 + elif dd == 4: dd = 2 + elif dd == 8: dd = 3 + elif dd == 16: dd = 4 + elif dd == 32: dd = 5 + elif dd == 64: dd = 6 + else: + error("Unknown value for timesig denominator") - MMA.midi.timeSig.set(nn,dd) + MMA.midi.timeSig.set(nn,dd) @@ -1420,125 +1450,125 @@ def setTimeSig(ln): def rndseed(ln): - """ Reseed the random number generator. """ + """ Reseed the random number generator. """ - if not ln: - random.seed() + if not ln: + random.seed() - elif len(ln)>1: - error("RNDSEED: requires 0 or 1 arguments.") - else: - random.seed(stof(ln[0])) + elif len(ln)>1: + error("RNDSEED: requires 0 or 1 arguments") + else: + random.seed(stof(ln[0])) def transpose(ln): - """ Set transpose value. """ + """ Set transpose value. """ - if len(ln) != 1: - error("Use: Transpose N.") + if len(ln) != 1: + error("Use: Transpose N") - t = stoi(ln[0], "Argument for Tranpose must be an integer, not '%s'" % ln[0]) - if t < -12 or t > 12: - error("Tranpose %s out-of-range; must be -12..12." % t) + t = stoi(ln[0], "Argument for Tranpose must be an integer, not '%s'" % ln[0]) + if t < -12 or t > 12: + error("Tranpose %s out-of-range; must be -12..12" % t) - gbl.transpose = t + gbl.transpose = t - if gbl.debug: - print "Set Transpose to %s" % t + if gbl.debug: + print "Set Transpose to %s" % t def lnPrint(ln): - """ Print stuff in a "print" command. """ + """ Print stuff in a "print" command. """ - print " ".join(ln) + print " ".join(ln) def printActive(ln): - """ Print a list of the active tracks. """ + """ Print a list of the active tracks. """ - print "Active tracks, groove:", gbl.currentGroove, ' '.join(ln) + print "Active tracks, groove:", gbl.currentGroove, ' '.join(ln) - for a in sorted(gbl.tnames.keys()): - f=gbl.tnames[a] - if f.sequence: - print " ",a - print + for a in sorted(gbl.tnames.keys()): + f=gbl.tnames[a] + if f.sequence: + print " ",a + print def setDebug(ln): - """ Set debugging options dynamically. """ + """ Set debugging options dynamically. """ - msg=( "Use: Debug MODE=On/Off where MODE is one or more of " - "DEBUG, FILENAMES, PATTERNS, SEQUENCE, " - "RUNTIME, WARNINGS or EXPAND." ) + msg=( "Use: Debug MODE=On/Off where MODE is one or more of " + "DEBUG, FILENAMES, PATTERNS, SEQUENCE, " + "RUNTIME, WARNINGS or EXPAND" ) - if not len(ln): - error(msg) + if not len(ln): + error(msg) - # save current flags + # save current flags - gbl.Ldebug = gbl.debug - gbl.LshowFilenames = gbl.showFilenames - gbl.Lpshow = gbl.pshow - gbl.Lseqshow = gbl.seqshow - gbl.Lshowrun = gbl.showrun - gbl.LnoWarn = gbl.noWarn - gbl.LnoOutput = gbl.noOutput - gbl.LshowExpand = gbl.showExpand - gbl.Lchshow = gbl.chshow + gbl.Ldebug = gbl.debug + gbl.LshowFilenames = gbl.showFilenames + gbl.Lpshow = gbl.pshow + gbl.Lseqshow = gbl.seqshow + gbl.Lshowrun = gbl.showrun + gbl.LnoWarn = gbl.noWarn + gbl.LnoOutput = gbl.noOutput + gbl.LshowExpand = gbl.showExpand + gbl.Lchshow = gbl.chshow - for l in ln: - try: - mode, val = l.upper().split('=') - except: - error("Each debug option must contain a '=', not '%s'" % l) + for l in ln: + try: + mode, val = l.upper().split('=') + except: + error("Each debug option must contain a '=', not '%s'" % l) - if val == 'ON' or val == '1': - setting = 1 - elif val == 'OFF' or val == '0': - setting = 0 - else: - error(msg) + if val == 'ON' or val == '1': + setting = 1 + elif val == 'OFF' or val == '0': + setting = 0 + else: + error(msg) - if mode == 'DEBUG': - gbl.debug = setting - if gbl.debug: - print "Debug=%s." % val + if mode == 'DEBUG': + gbl.debug = setting + if gbl.debug: + print "Debug=%s." % val - elif mode == 'FILENAMES': - gbl.showFilenames = setting - if gbl.debug: - print "ShowFilenames=%s." % val + elif mode == 'FILENAMES': + gbl.showFilenames = setting + if gbl.debug: + print "ShowFilenames=%s." % val - elif mode == 'PATTERNS': - gbl.pshow = setting - if gbl.debug: - print "Pattern display=%s." % val + elif mode == 'PATTERNS': + gbl.pshow = setting + if gbl.debug: + print "Pattern display=%s." % val - elif mode == 'SEQUENCE': - gbl.seqshow = setting - if gbl.debug: - print "Sequence display=%s." % val + elif mode == 'SEQUENCE': + gbl.seqshow = setting + if gbl.debug: + print "Sequence display=%s." % val - elif mode == 'RUNTIME': - gbl.showrun = setting - if gbl.debug: - print "Runtime display=%s." % val + elif mode == 'RUNTIME': + gbl.showrun = setting + if gbl.debug: + print "Runtime display=%s." % val - elif mode == 'WARNINGS': - gbl.noWarn = not(setting) - if gbl.debug: - print "Warning display=%s." % val + elif mode == 'WARNINGS': + gbl.noWarn = not(setting) + if gbl.debug: + print "Warning display=%s" % val - elif mode == 'EXPAND': - gbl.showExpand = setting - if gbl.debug: - print "Expand display=%s." % val + elif mode == 'EXPAND': + gbl.showExpand = setting + if gbl.debug: + print "Expand display=%s." % val - else: - error(msg) + else: + error(msg) @@ -1551,187 +1581,187 @@ def setDebug(ln): # Pattern/Groove def trackDefPattern(name, ln): - """ Define a pattern for a track. + """ Define a pattern for a track. - Use the type-name for all defines.... check the track - names and if it has a '-' in it, we use only the - part BEFORE the '-'. So DRUM-Snare becomes DRUM. - """ + Use the type-name for all defines.... check the track + names and if it has a '-' in it, we use only the + part BEFORE the '-'. So DRUM-Snare becomes DRUM. + """ - ln=ln[:] + ln=ln[:] - name=name.split('-')[0] + name=name.split('-')[0] - trackAlloc(name, 1) + trackAlloc(name, 1) - if ln: - pattern = ln.pop(0).upper() - else: - error("Define is expecting a pattern name.") + if ln: + pattern = ln.pop(0).upper() + else: + error("Define is expecting a pattern name") - if pattern in ('z', 'Z', '-'): - error("Pattern name '%s' is reserved." % pattern) + if pattern in ('z', 'Z', '-'): + error("Pattern name '%s' is reserved" % pattern) - if pattern.startswith('_'): - error("Names with a leading underscore are reserved.") + if pattern.startswith('_'): + error("Names with a leading underscore are reserved") - if not ln: - error("No pattern list given for '%s %s'." % (name, pattern) ) + if not ln: + error("No pattern list given for '%s %s'" % (name, pattern) ) - ln=' '.join(ln) - gbl.tnames[name].definePattern(pattern, ln) + ln=' '.join(ln) + gbl.tnames[name].definePattern(pattern, ln) def trackSequence(name, ln): - """ Define a sequence for a track. + """ Define a sequence for a track. - The format for a sequence: - TrackName Seq1 [Seq2 ... ] + The format for a sequence: + TrackName Seq1 [Seq2 ... ] - Note, that SeqX can be a predefined seq or { seqdef } - The {} is dynamically interpreted into a def. - """ + Note, that SeqX can be a predefined seq or { seqdef } + The {} is dynamically interpreted into a def. + """ - if not ln: - error ("Use: %s Sequence NAME [...]" % name) + if not ln: + error ("Use: %s Sequence NAME [...]" % name) - ln = ' '.join(ln) + ln = ' '.join(ln) - """ Extract out any {} definitions and assign them to new - define variables (__1, __99, etc) and melt them - back into the string. - """ + """ Extract out any {} definitions and assign them to new + define variables (__1, __99, etc) and melt them + back into the string. + """ - ids=1 - while 1: - sp = ln.find("{") + ids=1 + while 1: + sp = ln.find("{") - if sp<0: - break + if sp<0: + break - ln, s = pextract(ln, "{", "}", 1) - if not s: - error("Did not find matching '}' for '{'") + ln, s = pextract(ln, "{", "}", 1) + if not s: + error("Did not find matching '}' for '{'") - pn = "_%s" % ids - ids+=1 + pn = "_%s" % ids + ids+=1 - trk=name.split('-')[0] - trackAlloc(trk, 1) + trk=name.split('-')[0] + trackAlloc(trk, 1) - gbl.tnames[trk].definePattern(pn, s[0]) - ln = ln[:sp] + ' ' + pn + ' ' + ln[sp:] + gbl.tnames[trk].definePattern(pn, s[0]) + ln = ln[:sp] + ' ' + pn + ' ' + ln[sp:] - ln=ln.split() + ln=ln.split() - gbl.tnames[name].setSequence(ln) + gbl.tnames[name].setSequence(ln) -def trackSeqClear(name, ln): - """ Clear sequence for specified tracks. +def trackSeqClear(name, ln): + """ Clear sequence for specified tracks. - Note: "Drum SeqClear" clears all Drum tracks, - "Drum-3 SeqClear" clears track Drum-3. - """ + Note: "Drum SeqClear" clears all Drum tracks, + "Drum-3 SeqClear" clears track Drum-3. + """ - if ln: - error("No args permitted. Use %s SEQCLEAR" % name) + if ln: + error("No args permitted. Use %s SEQCLEAR" % name) - for n in gbl.tnames: - if n.find(name) == 0: - if gbl.debug: - print "SeqClear: Track %s cleared." % n - gbl.tnames[n].clearSequence() + for n in gbl.tnames: + if n.find(name) == 0: + if gbl.debug: + print "SeqClear: Track %s cleared." % n + gbl.tnames[n].clearSequence() def trackSeqRnd(name, ln): - """ Set random order for specified track. """ + """ Set random order for specified track. """ - if len(ln) != 1: - error("Use: %s SeqRnd [On, Off]." % name) + if len(ln) != 1: + error("Use: %s SeqRnd [On, Off]" % name) - gbl.tnames[name].setRnd(ln[0].upper()) + gbl.tnames[name].setRnd(ln[0].upper()) def trackSeqRndWeight(name, ln): - """ Set rnd weight for track. """ + """ Set rnd weight for track. """ - if not ln: - error("Use: %s RndWeight ." % name) + if not ln: + error("Use: %s RndWeight " % name) - gbl.tnames[name].setRndWeight(ln) + gbl.tnames[name].setRndWeight(ln) def trackRestart(name, ln): - """ Restart track to almost-default condidions. """ + """ Restart track to almost-default condidions. """ - if ln: - error ("Use: '%s Resart' with no args", name) + if ln: + error ("Use: '%s Resart' with no args", name) - gbl.tnames[name].restart() + gbl.tnames[name].restart() def trackGroove(name, ln): - """ Select a previously defined groove for a single track. """ + """ Select a previously defined groove for a single track. """ - if len(ln) != 1: - error("Use: %s Groove Name" % name) + if len(ln) != 1: + error("Use: %s Groove Name" % name) - slot = ln[0].upper() + slot = ln[0].upper() - if not slot in gbl.settingsGroove: - error("Groove '%s' not defined" % slot) + if not slot in gbl.settingsGroove: + error("Groove '%s' not defined" % slot) - g=gbl.tnames[name] - g.restoreGroove(slot) + g=gbl.tnames[name] + g.restoreGroove(slot) - if g.sequence == [None] * len(g.sequence): - warning("'%s' Track Groove has no sequence. Track name error?" % name) + if g.sequence == [None] * len(g.sequence): + warning("'%s' Track Groove has no sequence. Track name error?" % name) - g.setSeqSize() + g.setSeqSize() - if gbl.debug: - print "%s Groove settings restored from '%s'." % (name, slot) + if gbl.debug: + print "%s Groove settings restored from '%s'." % (name, slot) def trackRiff(name, ln): - """ Set a riff for a track. """ + """ Set a riff for a track. """ - gbl.tnames[name].setRiff(' '.join(ln)) + gbl.tnames[name].setRiff(' '.join(ln)) def deleteTrks(ln): - """ Delete a track and free the MIDI track. """ + """ Delete a track and free the MIDI track. """ - if not len(ln): - error("Use Delete Track [...]") + if not len(ln): + error("Use Delete Track [...]") - for name in ln: - name=name.upper() - if name in gbl.tnames: - tr = gbl.tnames[name] - else: - error("Track '%s' does not exist" % name) + for name in ln: + name=name.upper() + if name in gbl.tnames: + tr = gbl.tnames[name] + else: + error("Track '%s' does not exist" % name) - if tr.channel: - tr.doMidiClear() - tr.clearPending() + if tr.channel: + tr.doMidiClear() + tr.clearPending() - if tr.riff: - warning("%s has pending RIFF(s)" % name) - gbl.midiAvail[tr.channel] -= 1 + if tr.riff: + warning("%s has pending RIFF(s)" % name) + gbl.midiAvail[tr.channel] -= 1 - # NOTE: Don't try deleting 'tr' since it's just a copy!! + # NOTE: Don't try deleting 'tr' since it's just a copy!! - del gbl.tnames[name] + del gbl.tnames[name] - if not name in gbl.deletedTracks: - gbl.deletedTracks.append(name) + if not name in gbl.deletedTracks: + gbl.deletedTracks.append(name) - if gbl.debug: - print "Track '%s' deleted" % name + if gbl.debug: + print "Track '%s' deleted" % name @@ -1739,127 +1769,126 @@ def deleteTrks(ln): # Volume def trackRvolume(name, ln): - """ Set random volume for specific track. """ + """ Set random volume for specific track. """ - if not ln: - error ("Use: %s RVolume N [...]." % name) + if not ln: + error ("Use: %s RVolume N [...]" % name) - gbl.tnames[name].setRVolume(ln) + gbl.tnames[name].setRVolume(ln) def trackCresc(name, ln): - gbl.tnames[name].setCresc(1, ln) - #error("(De)Crescendo only supported in master context.") + gbl.tnames[name].setCresc(1, ln) def trackDeCresc(name, ln): - gbl.tnames[name].setCresc(-1, ln) + gbl.tnames[name].setCresc(-1, ln) def trackVolume(name, ln): - """ Set volume for specific track. """ + """ Set volume for specific track. """ - if not ln: - error ("Use: %s Volume DYN [...]." % name) + if not ln: + error ("Use: %s Volume DYN [...]" % name) - gbl.tnames[name].setVolume(ln) + gbl.tnames[name].setVolume(ln) def trackChannelVol(name, ln): - """ Set the channel volume for a track.""" + """ Set the channel volume for a track.""" - if len(ln) != 1: - error("Use: %s ChannelVolume." % name) + if len(ln) != 1: + error("Use: %s ChannelVolume" % name) - v=stoi(ln[0], "Expecting integer arg, not %s." % ln[0]) + v=stoi(ln[0], "Expecting integer arg, not %s" % ln[0]) - if v<0 or v>127: - error("ChannelVolume must be 0..127") + if v<0 or v>127: + error("ChannelVolume must be 0..127") - gbl.tnames[name].setChannelVolume(v) + gbl.tnames[name].setChannelVolume(v) def trackAccent(name, ln): - """ Set emphasis beats for track.""" + """ Set emphasis beats for track.""" - gbl.tnames[name].setAccent(ln) + gbl.tnames[name].setAccent(ln) ####################################### # Timing def trackCut(name, ln): - """ Insert a ALL NOTES OFF at the given offset. """ + """ Insert a ALL NOTES OFF at the given offset. """ - if not len(ln): - ln=['0'] + if not len(ln): + ln=['0'] - if len(ln) != 1: - error("Use: %s Cut Offset" % name) + if len(ln) != 1: + error("Use: %s Cut Offset" % name) - offset = stof(ln[0], "Cut offset expecting value, (not '%s')." % ln[0]) + offset = stof(ln[0], "Cut offset expecting value, (not '%s')" % ln[0]) - if offset < -gbl.QperBar or offset > gbl.QperBar: - warning("Cut: %s is a large beat offset." % offset) + if offset < -gbl.QperBar or offset > gbl.QperBar: + warning("Cut: %s is a large beat offset" % offset) - moff = int(gbl.tickOffset + (gbl.BperQ * offset)) + moff = int(gbl.tickOffset + (gbl.BperQ * offset)) - if moff < 0: - error("Calculated offset for Cut comes before start of track.") + if moff < 0: + error("Calculated offset for Cut comes before start of track") - """ Insert allnoteoff directly in track. This skips the normal - queueing in pats because it would never take if at the end - of a track. - """ + """ Insert allnoteoff directly in track. This skips the normal + queueing in pats because it would never take if at the end + of a track. + """ - m = gbl.tnames[name].channel - if m and len(gbl.mtrks[m].miditrk) > 1: - gbl.mtrks[m].addNoteOff(moff) + m = gbl.tnames[name].channel + if m and len(gbl.mtrks[m].miditrk) > 1: + gbl.mtrks[m].addNoteOff(moff) - if gbl.debug: - print "%s Cut: Beat %s, Bar %s" % (name, offset, gbl.barNum + 1) + if gbl.debug: + print "%s Cut: Beat %s, Bar %s" % (name, offset, gbl.barNum + 1) def trackMallet(name, ln): - """ Set repeating-mallet options for solo/melody track. """ + """ Set repeating-mallet options for solo/melody track. """ - if not ln: - error("Use: %s Mallet [...]." % name) + if not ln: + error("Use: %s Mallet [...]" % name) - gbl.tnames[name].setMallet(ln) + gbl.tnames[name].setMallet(ln) def trackRtime(name, ln): - """ Set random timing for specific track. """ + """ Set random timing for specific track. """ - if not ln: - error ("Use: %s RTime N [...]." % name) + if not ln: + error ("Use: %s RTime N [...]" % name) - gbl.tnames[name].setRTime(ln) + gbl.tnames[name].setRTime(ln) def trackRskip(name, ln): - """ Set random skip for specific track. """ + """ Set random skip for specific track. """ - if not ln: - error ("Use: %s RSkip N [...]." % name) + if not ln: + error ("Use: %s RSkip N [...]" % name) - gbl.tnames[name].setRSkip(ln) + gbl.tnames[name].setRSkip(ln) def trackArtic(name, ln): - """ Set articulation. """ + """ Set articulation. """ - if not ln: - error("Use: %s Articulation N [...]." % name) + if not ln: + error("Use: %s Articulation N [...]" % name) - gbl.tnames[name].setArtic(ln) + gbl.tnames[name].setArtic(ln) ####################################### @@ -1867,129 +1896,129 @@ def trackArtic(name, ln): def trackCompress(name, ln): - """ Set (unset) compress for track. """ + """ Set (unset) compress for track. """ - if not ln: - error("Use: %s Compress " % name) + if not ln: + error("Use: %s Compress " % name) - gbl.tnames[name].setCompress(ln) + gbl.tnames[name].setCompress(ln) def trackVoicing(name, ln): - """ Set Voicing options. Only valid for chord tracks at this time.""" + """ Set Voicing options. Only valid for chord tracks at this time.""" - if not ln: - error("Use: %s Voicing [...]" % name) + if not ln: + error("Use: %s Voicing [...]" % name) - gbl.tnames[name].setVoicing(ln) + gbl.tnames[name].setVoicing(ln) def trackDupRoot(name, ln): - """ Set (unset) the root note duplication. Only applies to chord tracks. """ + """ Set (unset) the root note duplication. Only applies to chord tracks. """ - if not ln: - error("Use: %s DupRoot ..." % name) + if not ln: + error("Use: %s DupRoot ..." % name) - gbl.tnames[name].setDupRoot(ln) + gbl.tnames[name].setDupRoot(ln) def trackChordLimit(name, ln): - """ Set (unset) ChordLimit for track. """ + """ Set (unset) ChordLimit for track. """ - if len(ln) != 1: - error("Use: %s ChordLimit " % name) + if len(ln) != 1: + error("Use: %s ChordLimit " % name) - gbl.tnames[name].setChordLimit(ln[0]) + gbl.tnames[name].setChordLimit(ln[0]) def trackRange(name, ln): - """ Set (unset) Range for track. Only effects arp and scale. """ + """ Set (unset) Range for track. Only effects arp and scale. """ - if not ln: - error("Use: %s Range ... " % name) + if not ln: + error("Use: %s Range ... " % name) - gbl.tnames[name].setRange(ln) + gbl.tnames[name].setRange(ln) def trackInvert(name, ln): - """ Set invert for track.""" + """ Set invert for track.""" - if not ln: - error("Use: %s Invert N [...]." % name) + if not ln: + error("Use: %s Invert N [...]" % name) - gbl.tnames[name].setInvert(ln) + gbl.tnames[name].setInvert(ln) def trackSpan(name, ln): - """ Set midi note span for track. """ + """ Set midi note span for track. """ - if len(ln) != 2: - error("Use: %s Start End" % name) + if len(ln) != 2: + error("Use: %s Start End" % name) - start = stoi(ln[0], "Expecting integer for SPAN 1st arg.") - if start <0 or start >127: - error("Start arg for Span must be 0..127, not %s." % start) + start = stoi(ln[0], "Expecting integer for SPAN 1st arg") + if start <0 or start >127: + error("Start arg for Span must be 0..127, not %s" % start) - end = stoi(ln[1], "Expecting integer for SPAN 2nd arg.") - if end <0 or end >127: - error("End arg for Span must be 0..127, not %s." % end) + end = stoi(ln[1], "Expecting integer for SPAN 2nd arg") + if end <0 or end >127: + error("End arg for Span must be 0..127, not %s" % end) - if end <= start: - error("End arg for Span must be greater than start.") + if end <= start: + error("End arg for Span must be greater than start") - if end-start < 11: - error("Span range must be at least 12.") + if end-start < 11: + error("Span range must be at least 12") - gbl.tnames[name].setSpan(start, end) + gbl.tnames[name].setSpan(start, end) def trackOctave(name, ln): - """ Set octave for specific track. """ + """ Set octave for specific track. """ - if not ln: - error ("Use: %s Octave N [...], (n=0..10)" % name) + if not ln: + error ("Use: %s Octave N [...], (n=0..10)" % name) - gbl.tnames[name].setOctave( ln ) + gbl.tnames[name].setOctave( ln ) def trackStrum(name, ln): - """ Set all specified track strum. """ + """ Set all specified track strum. """ - if not ln: - error ("Use: %s Strum N [...]" % name) + if not ln: + error ("Use: %s Strum N [...]" % name) - gbl.tnames[name].setStrum( ln ) + gbl.tnames[name].setStrum( ln ) def trackHarmony(name, ln): - """ Set harmony value. """ + """ Set harmony value. """ - if not ln: - error("Use: %s Harmony N [...]" % name) + if not ln: + error("Use: %s Harmony N [...]" % name) - gbl.tnames[name].setHarmony(ln) + gbl.tnames[name].setHarmony(ln) def trackHarmonyOnly(name, ln): - """ Set harmony only for track. """ + """ Set harmony only for track. """ - if not ln: - error("Use: %s HarmonyOnly N [...]" % name) + if not ln: + error("Use: %s HarmonyOnly N [...]" % name) - gbl.tnames[name].setHarmonyOnly(ln) + gbl.tnames[name].setHarmonyOnly(ln) def trackHarmonyVolume(name, ln): - """ Set harmony volume for track.""" + """ Set harmony volume for track.""" - if not ln: - error("Use: %s HarmonyVolume N [...]" % name) + if not ln: + error("Use: %s HarmonyVolume N [...]" % name) - gbl.tnames[name].setHarmonyVolume(ln) + gbl.tnames[name].setHarmonyVolume(ln) ####################################### @@ -1997,364 +2026,367 @@ def trackHarmonyVolume(name, ln): def trackChannel(name, ln): - """ Set the midi channel for a track.""" + """ Set the midi channel for a track.""" - if not ln: - error("Use: %s Channel" % name) + if not ln: + error("Use: %s Channel" % name) - gbl.tnames[name].setChannel(ln[0]) + gbl.tnames[name].setChannel(ln[0]) def trackMdefine(name, ln): - """ Set a midi seq pattern. Ignore track name.""" + """ Set a midi seq pattern. Ignore track name.""" - mdefine(ln) + mdefine(ln) def trackMidiExt(ln): - """ Helper for trackMidiSeq() and trackMidiVoice().""" + """ Helper for trackMidiSeq() and trackMidiVoice().""" - ids=1 - while 1: - sp = ln.find("{") + ids=1 + while 1: + sp = ln.find("{") - if sp<0: - break + if sp<0: + break - ln, s = pextract(ln, "{", "}", 1) - if not s: - error("Did not find matching '}' for '{'") + ln, s = pextract(ln, "{", "}", 1) + if not s: + error("Did not find matching '}' for '{'") - pn = "_%s" % ids - ids+=1 + pn = "_%s" % ids + ids+=1 - MMA.mdefine.mdef.set(pn, s[0]) - ln = ln[:sp] + ' ' + pn + ' ' + ln[sp:] + MMA.mdefine.mdef.set(pn, s[0]) + ln = ln[:sp] + ' ' + pn + ' ' + ln[sp:] - return ln.split() + return ln.split() def trackMidiClear(name, ln): - """ Set MIDI command to send at end of groove. """ + """ Set MIDI command to send at end of groove. """ - if not ln: - error("Use %s MIDIClear Controller Data" % name) + if not ln: + error("Use %s MIDIClear Controller Data" % name) - if len(ln) == 1 and ln[0] == '-': - gbl.tnames[name].setMidiClear( '-' ) - else: - ln=' '.join(ln) - if '{' in ln or '}' in ln: - error("{}s are not permitted in %s MIDIClear command." % name) - gbl.tnames[name].setMidiClear( trackMidiExt( '{' + ln + '}' )) + if len(ln) == 1 and ln[0] == '-': + gbl.tnames[name].setMidiClear( '-' ) + else: + ln=' '.join(ln) + if '{' in ln or '}' in ln: + error("{}s are not permitted in %s MIDIClear command" % name) + gbl.tnames[name].setMidiClear( trackMidiExt( '{' + ln + '}' )) def trackMidiSeq(name, ln): - """ Set reoccurring MIDI command for track. """ + """ Set reoccurring MIDI command for track. """ - if not ln: - error("Use %s MidiSeq Controller Data " % name) + if not ln: + error("Use %s MidiSeq Controller Data" % name) - if len(ln) == 1 and ln[0]== '-': - gbl.tnames[name].setMidiSeq('-') - else: - gbl.tnames[name].setMidiSeq( trackMidiExt(' '.join(ln) )) + if len(ln) == 1 and ln[0]== '-': + gbl.tnames[name].setMidiSeq('-') + else: + gbl.tnames[name].setMidiSeq( trackMidiExt(' '.join(ln) )) def trackMidiVoice(name, ln): - """ Set single shot MIDI command for track. """ + """ Set single shot MIDI command for track. """ - if not ln: - error("Use %s MidiVoice Controller Data" % name) + if not ln: + error("Use %s MidiVoice Controller Data" % name) - if len(ln) == 1 and ln[0] == '-': - gbl.tnames[name].setMidiVoice( '-' ) - else: - gbl.tnames[name].setMidiVoice( trackMidiExt(' '.join(ln) )) + if len(ln) == 1 and ln[0] == '-': + gbl.tnames[name].setMidiVoice( '-' ) + else: + gbl.tnames[name].setMidiVoice( trackMidiExt(' '.join(ln) )) def trackChShare(name, ln): - """ Set MIDI channel sharing.""" + """ Set MIDI channel sharing.""" - if len(ln) !=1: - error("Use: %s ChShare TrackName" % name) + if len(ln) !=1: + error("Use: %s ChShare TrackName" % name) - gbl.tnames[name].setChShare(ln[0]) + gbl.tnames[name].setChShare(ln[0]) def trackVoice(name, ln): - """ Set voice for specific track. """ + """ Set voice for specific track. """ - if not ln: - error ("Use: %s Voice NN [...]" % name) + if not ln: + error ("Use: %s Voice NN [...]" % name) - gbl.tnames[name].setVoice(ln) + gbl.tnames[name].setVoice(ln) def trackPan(name, ln): - """ Set the Midi Pan value for a track.""" + """ Set the Midi Pan value for a track.""" - if len(ln) != 1: - error("Use: %s PAN NN" % name) + if len(ln) != 1: + error("Use: %s PAN NN" % name) - gbl.tnames[name].setPan(ln[0]) + gbl.tnames[name].setPan(ln[0]) def trackOff(name, ln): - """ Turn a track off """ + """ Turn a track off """ - if ln: - error("Use: %s OFF with no paramater." % name) + if ln: + error("Use: %s OFF with no paramater" % name) - gbl.tnames[name].setOff() + gbl.tnames[name].setOff() def trackOn(name, ln): - """ Turn a track on """ + """ Turn a track on """ - if ln: - error("Use: %s ON with no paramater." % name) + if ln: + error("Use: %s ON with no paramater" % name) - gbl.tnames[name].setOn() + gbl.tnames[name].setOn() def trackMidiName(name,ln): - """ Set channel track name.""" + """ Set channel track name.""" - if not ln: - error("Use: %s TrackName." % name) + if not ln: + error("Use: %s TrackName" % name) - gbl.tnames[name].setTname(ln[0]) + gbl.tnames[name].setTname(ln[0]) def trackTone(name, ln): - """ Set the tone (note). Only valid in drum tracks.""" + """ Set the tone (note). Only valid in drum tracks.""" - if not ln: - error("Use: %s Tone N [...]." % name) + if not ln: + error("Use: %s Tone N [...]" % name) - gbl.tnames[name].setTone(ln) + gbl.tnames[name].setTone(ln) def trackGlis(name, ln): - """ Enable/disable portamento. """ + """ Enable/disable portamento. """ - if len(ln) != 1: - error("Use: %s Portamento NN, off=0, 1..127==on." % name) + if len(ln) != 1: + error("Use: %s Portamento NN, off=0, 1..127==on" % name) - gbl.tnames[name].setGlis(ln[0]) + gbl.tnames[name].setGlis(ln[0]) def trackForceOut(name, ln): - """ Force output of voice settings. """ + """ Force output of voice settings. """ - if len(ln): - error("Use %s ForceOut (no options)." % name) + if len(ln): + error("Use %s ForceOut (no options)" % name) - gbl.tnames[name].setForceOut() + gbl.tnames[name].setForceOut() ####################################### # Misc def trackDrumType(name, ln): - """ Set a melody or solo track to be a drum solo track.""" + """ Set a melody or solo track to be a drum solo track.""" - tr = gbl.tnames[name] - if tr.vtype not in ('SOLO', 'MELODY'): - error ("Only Solo and Melody tracks can be to DrumType, not '%s'." - % name) - if ln: - error("No parmeters permitted for DrumType command.") + tr = gbl.tnames[name] + if tr.vtype not in ('SOLO', 'MELODY'): + error ("Only Solo and Melody tracks can be to DrumType, not '%s'" % name) + if ln: + error("No parmeters permitted for DrumType command") - tr.setDrumType() + tr.setDrumType() def trackDirection(name, ln): - """ Set scale/arp direction. """ + """ Set scale/arp direction. """ - if not ln: - error("Use: %s Direction OPT" % name) + if not ln: + error("Use: %s Direction OPT" % name) - gbl.tnames[name].setDirection(ln) + gbl.tnames[name].setDirection(ln) def trackScaletype(name, ln): - """ Set the scale type. """ + """ Set the scale type. """ - if not ln: - error("Use: %s ScaleType OPT" % name) + if not ln: + error("Use: %s ScaleType OPT" % name) - gbl.tnames[name].setScaletype(ln) + gbl.tnames[name].setScaletype(ln) def trackCopy(name, ln): - """ Copy setting in 'ln' to 'name'. """ + """ Copy setting in 'ln' to 'name'. """ - if len(ln) != 1: - error("Use: %s Copy ExistingTrack" % name) + if len(ln) != 1: + error("Use: %s Copy ExistingTrack" % name) - gbl.tnames[name].copySettings(ln[0].upper()) + gbl.tnames[name].copySettings(ln[0].upper()) def trackUnify(name, ln): - """ Set UNIFY for track.""" + """ Set UNIFY for track.""" - if not len(ln): - error("Use %s UNIFY 1 [...]" % name) + if not len(ln): + error("Use %s UNIFY 1 [...]" % name) - gbl.tnames[name].setUnify(ln) + gbl.tnames[name].setUnify(ln) """ ================================================================= - Command jump tables. These need to be at the end of this module - to avoid undefined name errors. The tables are only used in - the parse() function. + Command jump tables. These need to be at the end of this module + to avoid undefined name errors. The tables are only used in + the parse() function. - The first table is for the simple commands ... those which DO NOT - have a leading trackname. The second table is for commands which - require a leading track name. + The first table is for the simple commands ... those which DO NOT + have a leading trackname. The second table is for commands which + require a leading track name. - The alphabetic order is NOT needed, just convenient. + The alphabetic order is NOT needed, just convenient. """ simpleFuncs={ - 'ADJUSTVOLUME': MMA.volume.adjvolume, - 'ALLTRACKS': allTracks, - 'AUTHOR': MMA.docs.docAuthor, - 'AUTOSOLOTRACKS': MMA.patSolo.setAutoSolo, - 'BEATADJUST': beatAdjust, - 'CHANNELPREF': setChPref, - 'COMMENT': comment, - 'CRESC': MMA.volume.setCresc, - 'CUT': cut, - 'DEBUG': setDebug, - 'DEC': macros.vardec, - 'DECRESC': MMA.volume.setDecresc, - 'DEFCHORD': MMA.chords.defChord, - 'DEFGROOVE': grooveDefine, - 'DELETE': deleteTrks, - 'DOC': MMA.docs.docNote, - 'DRUMVOLTR': MMA.translate.drumVolTable.set, - 'ELSE': ifelse, - 'ENDIF': ifend, - 'ENDMSET': endmset, - 'ENDREPEAT': repeatend, - 'EOF': eof, - 'FERMATA': fermata, - 'GOTO': goto, - 'GROOVE': groove, - 'IF': macros.varIF, - 'IFEND': ifend, - 'INC': macros.varinc, - 'INCLUDE': include, - 'KEYSIG': MMA.patSolo.keySig.set, - 'LABEL': comment, - 'LYRIC': lyric.option, - 'MIDIDEF': mdefine, - 'MIDI': rawMidi, - 'MIDIFILE': setMidiFileType, - 'MIDIINC': MMA.midiIn.midiinc, - 'MIDIMARK': midiMarker, - 'MIDISPLIT': MMA.midi.setSplitChannels, - 'MMAEND': mmaend, - 'MMASTART': mmastart, - 'MSET': macros.msetvar, - 'MSETEND': endmset, - 'CHORDADJUST': MMA.chords.chordAdjust, - 'PRINT': lnPrint, - 'PRINTACTIVE': printActive, - 'PRINTCHORD': MMA.chords.printChord, - 'REPEAT': repeat, - 'REPEATEND': repeatend, - 'REPEATENDING': repeatending, - 'RESTART': restart, - 'RNDSEED': rndseed, - 'RNDSET': macros.rndvar, - 'SEQ': seq, - 'SEQCLEAR': seqClear, - 'SEQRND': setSeqRnd, - 'SEQRNDWEIGHT': setSeqRndWeight, - 'SEQSIZE': seqsize, - 'SET': macros.setvar, - 'SETAUTOLIBPATH': setAutoPath, - 'SETINCPATH': setIncPath, - 'SETLIBPATH': setLibPath, - 'SETOUTPATH': setOutPath, - 'SHOWVARS': macros.showvars, - 'STACKVALUE': macros.stackValue, - 'SWINGMODE': MMA.notelen.swingMode, - 'TEMPO': tempo, - 'TIME': setTime, - 'TIMESIG': setTimeSig, - 'TONETR': MMA.translate.dtable.set, - 'UNSET': macros.unsetvar, - 'USE': usefile, - 'VEXPAND': macros.vexpand, - 'VOICEVOLTR': MMA.translate.voiceVolTable.set, - 'VOICETR': MMA.translate.vtable.set, - 'VOLUME': MMA.volume.setVolume, - 'TRANSPOSE': transpose + 'ADJUSTVOLUME': MMA.volume.adjvolume, + 'ALLTRACKS': allTracks, + 'AUTHOR': MMA.docs.docAuthor, + 'AUTOSOLOTRACKS': MMA.patSolo.setAutoSolo, + 'BEATADJUST': beatAdjust, + 'CHANNELPREF': setChPref, + 'COMMENT': comment, + 'CRESC': MMA.volume.setCresc, + 'CUT': cut, + 'DEBUG': setDebug, + 'DEC': macros.vardec, + 'DECRESC': MMA.volume.setDecresc, + 'DEFCHORD': MMA.chords.defChord, + 'DEFGROOVE': grooveDefine, + 'DELETE': deleteTrks, + 'DOC': MMA.docs.docNote, + 'DOCVAR': MMA.docs.docVars, + 'DRUMVOLTR': MMA.translate.drumVolTable.set, + 'ELSE': ifelse, + 'ENDIF': ifend, + 'ENDMSET': endmset, + 'ENDREPEAT': repeatend, + 'EOF': eof, + 'FERMATA': fermata, + 'GOTO': goto, + 'GROOVE': groove, + 'GROOVECLEAR': grooveClear, + 'IF': macros.varIF, + 'IFEND': ifend, + 'INC': macros.varinc, + 'INCLUDE': include, + 'KEYSIG': MMA.patSolo.keySig.set, + 'LABEL': comment, + 'LYRIC': lyric.option, + 'MIDIDEF': mdefine, + 'MIDI': rawMidi, + 'MIDIFILE': setMidiFileType, + 'MIDIINC': MMA.midiIn.midiinc, + 'MIDIMARK': midiMarker, + 'MIDISPLIT': MMA.midi.setSplitChannels, + 'MMAEND': mmaend, + 'MMASTART': mmastart, + 'MSET': macros.msetvar, + 'MSETEND': endmset, + 'NEWSET': macros.newsetvar, + 'CHORDADJUST': MMA.chords.chordAdjust, + 'PRINT': lnPrint, + 'PRINTACTIVE': printActive, + 'PRINTCHORD': MMA.chords.printChord, + 'REPEAT': repeat, + 'REPEATEND': repeatend, + 'REPEATENDING': repeatending, + 'RESTART': restart, + 'RNDSEED': rndseed, + 'RNDSET': macros.rndvar, + 'SEQ': seq, + 'SEQCLEAR': seqClear, + 'SEQRND': setSeqRnd, + 'SEQRNDWEIGHT': setSeqRndWeight, + 'SEQSIZE': seqsize, + 'SET': macros.setvar, + 'SETAUTOLIBPATH': setAutoPath, + 'SETINCPATH': setIncPath, + 'SETLIBPATH': setLibPath, + 'SETOUTPATH': setOutPath, + 'SHOWVARS': macros.showvars, + 'STACKVALUE': macros.stackValue, + 'SWINGMODE': MMA.notelen.swingMode, + 'TEMPO': tempo, + 'TIME': setTime, + 'TIMESIG': setTimeSig, + 'TONETR': MMA.translate.dtable.set, + 'UNSET': macros.unsetvar, + 'USE': usefile, + 'VARCLEAR': macros.clear, + 'VEXPAND': macros.vexpand, + 'VOICEVOLTR': MMA.translate.voiceVolTable.set, + 'VOICETR': MMA.translate.vtable.set, + 'VOLUME': MMA.volume.setVolume, + 'TRANSPOSE': transpose } trackFuncs={ - 'ACCENT': trackAccent, - 'ARTICULATE': trackArtic, - 'CHANNEL': trackChannel, - 'MIDIVOLUME': trackChannelVol, - 'CHSHARE': trackChShare, - 'COMPRESS': trackCompress, - 'COPY': trackCopy, - 'CRESC': trackCresc, - 'CUT': trackCut, - 'DECRESC': trackDeCresc, - 'DIRECTION': trackDirection, - 'DRUMTYPE': trackDrumType, - 'DUPROOT': trackDupRoot, - 'FORCEOUT': trackForceOut, - 'GROOVE': trackGroove, - 'HARMONY': trackHarmony, - 'HARMONYONLY': trackHarmonyOnly, - 'HARMONYVOLUME': trackHarmonyVolume, - 'INVERT': trackInvert, - 'LIMIT': trackChordLimit, - 'MALLET': trackMallet, - 'MIDIDEF': trackMdefine, - 'MIDIGLIS': trackGlis, - 'MIDICLEAR': trackMidiClear, - 'MIDIPAN': trackPan, - 'MIDIGLIS': trackGlis, - 'MIDISEQ': trackMidiSeq, - 'MIDITNAME': trackMidiName, - 'MIDIVOICE': trackMidiVoice, - 'OCTAVE': trackOctave, - 'OFF': trackOff, - 'ON': trackOn, - 'RANGE': trackRange, - 'RESTART': trackRestart, - 'RIFF': trackRiff, - 'RSKIP': trackRskip, - 'RTIME': trackRtime, - 'RVOLUME': trackRvolume, - 'SCALETYPE': trackScaletype, - 'SEQCLEAR': trackSeqClear, - 'SEQRND': trackSeqRnd, - 'SEQUENCE': trackSequence, - 'SEQRNDWEIGHT': trackSeqRndWeight, - 'NOTESPAN': trackSpan, - 'STRUM': trackStrum, - 'TONE': trackTone, - 'UNIFY': trackUnify, - 'VOICE': trackVoice, - 'VOICING': trackVoicing, - 'VOLUME': trackVolume, - 'DEFINE': trackDefPattern + 'ACCENT': trackAccent, + 'ARTICULATE': trackArtic, + 'CHANNEL': trackChannel, + 'MIDIVOLUME': trackChannelVol, + 'CHSHARE': trackChShare, + 'COMPRESS': trackCompress, + 'COPY': trackCopy, + 'CRESC': trackCresc, + 'CUT': trackCut, + 'DECRESC': trackDeCresc, + 'DIRECTION': trackDirection, + 'DRUMTYPE': trackDrumType, + 'DUPROOT': trackDupRoot, + 'FORCEOUT': trackForceOut, + 'GROOVE': trackGroove, + 'HARMONY': trackHarmony, + 'HARMONYONLY': trackHarmonyOnly, + 'HARMONYVOLUME': trackHarmonyVolume, + 'INVERT': trackInvert, + 'LIMIT': trackChordLimit, + 'MALLET': trackMallet, + 'MIDIDEF': trackMdefine, + 'MIDIGLIS': trackGlis, + 'MIDICLEAR': trackMidiClear, + 'MIDIPAN': trackPan, + 'MIDIGLIS': trackGlis, + 'MIDISEQ': trackMidiSeq, + 'MIDITNAME': trackMidiName, + 'MIDIVOICE': trackMidiVoice, + 'OCTAVE': trackOctave, + 'OFF': trackOff, + 'ON': trackOn, + 'RANGE': trackRange, + 'RESTART': trackRestart, + 'RIFF': trackRiff, + 'RSKIP': trackRskip, + 'RTIME': trackRtime, + 'RVOLUME': trackRvolume, + 'SCALETYPE': trackScaletype, + 'SEQCLEAR': trackSeqClear, + 'SEQRND': trackSeqRnd, + 'SEQUENCE': trackSequence, + 'SEQRNDWEIGHT': trackSeqRndWeight, + 'NOTESPAN': trackSpan, + 'STRUM': trackStrum, + 'TONE': trackTone, + 'UNIFY': trackUnify, + 'VOICE': trackVoice, + 'VOICING': trackVoicing, + 'VOLUME': trackVolume, + 'DEFINE': trackDefPattern } diff --git a/mma/MMA/pat.py b/mma/MMA/pat.py index b3f7577..3a6791f 100644 --- a/mma/MMA/pat.py +++ b/mma/MMA/pat.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -39,2076 +39,1940 @@ import MMA.mdefine import MMA.volume class Voicing: - def __init__(self): - self.mode = None - self.range = 12 - self.center = 4 - self.random = 0 - self.percent = 0 - self.bcount = 0 - self.dir = 0 + def __init__(self): + self.mode = None + self.range = 12 + self.center = 4 + self.random = 0 + self.percent = 0 + self.bcount = 0 + self.dir = 0 def seqBump(l): - """ Expand/contract an existing sequence list to the current seqSize.""" + """ Expand/contract an existing sequence list to the current seqSize.""" - while len(l) < gbl.seqSize: - l += l - return l[:gbl.seqSize] + while len(l) < gbl.seqSize: + l += l + return l[:gbl.seqSize] -pats = {} # Storage for all pattern defines +pats = {} # Storage for all pattern defines class PC: - """ Pattern class. + """ Pattern class. - Define classes for processing drum, chord, arp, and chord track. - These are mostly the same, so we create a base class and derive - the others from it. + Define classes for processing drum, chord, arp, and chord track. + These are mostly the same, so we create a base class and derive + the others from it. - We have a class for each track type. They are all derived - from the base 'Pats' class. These classes do special processing - like parsing a pattern tuple and creating a chord. + We have a class for each track type. They are all derived + from the base 'Pats' class. These classes do special processing + like parsing a pattern tuple and creating a chord. - No functions ever link to the code in this module, it is - only included into the real track class modules. + No functions ever link to the code in this module, it is + only included into the real track class modules. - """ + """ - def __init__(self, nm): + def __init__(self, nm): - self.inited = 0 - self.name = nm - self.channel = 0 - self.grooves = {} - self.saveVols = {} - self.ssvoice = -1 # Track the voice set for the track - self.smidiVoice = () # Track MIDIVoice cmds to avoid dups - self.midiSent = 0 # if set, MIDICLEAR invoked. + self.inited = 0 + self.name = nm + self.channel = 0 + self.grooves = {} + self.saveVols = {} + self.ssvoice = -1 # Track the voice set for the track + self.smidiVoice = () # Track MIDIVoice cmds to avoid dups + self.midiSent = 0 # if set, MIDICLEAR invoked. - """ Midi commands like Pan, Glis, etc. are stacked until musical - data is actually written to the track. Each item in - the midiPending list is a name (PAN, GLIS, etc), timeoffset, value. - """ + """ Midi commands like Pan, Glis, etc. are stacked until musical + data is actually written to the track. Each item in + the midiPending list is a name (PAN, GLIS, etc), timeoffset, value. + """ - self.midiPending = [] + self.midiPending = [] - self.riff = [] + self.riff = [] - self.disable = 0 + self.disable = 0 - if self.vtype == 'DRUM': - self.setChannel('10') - if not gbl.mtrks[self.channel].trackname: - gbl.mtrks[self.channel].addTrkName(0, 'Drum') + self.clearSequence() + - self.clearSequence() + self.inited = 1 - self.inited = 1 + ########################################## + ## These are called from process() to set options - ########################################## - ## These are called from process() to set options + def setCompress(self, ln): + """ set/unset the compress flag. """ - def setCompress(self, ln): - """ set/unset the compress flag. """ + ln=self.lnExpand(ln, 'Compress') - ln=self.lnExpand(ln, 'Compress') + tmp = [] - tmp = [] + for n in ln: - for n in ln: + n = stoi(n, "Argument for %s Compress must be a value" \ + % self.name) - n = stoi(n, "Argument for %s Compress must be a value." \ - % self.name) + if n < 0 or n > 5: + error("Compress %s out-of-range; must be 0 to 5" % n) - if n < 0 or n > 5: - error("Compress %s out-of-range; must be 0 to 5." % n) + if n and self.vtype=='CHORD' and self.voicing.mode: + vwarn = 1 - if n and self.vtype=='CHORD' and self.voicing.mode: - vwarn = 1 + tmp.append(n) - tmp.append(n) + self.compress = seqBump(tmp) - self.compress = seqBump(tmp) + if self.vtype not in ("CHORD", "ARPEGGIO"): + warning ("Compress is ignored in %s tracks" % self.vtype) - if self.vtype not in ("CHORD", "ARPEGGIO"): - warning ("Compress is ignored in %s tracks." % self.vtype) + if gbl.debug: + print "Set %s Compress to:" % self.name, + printList(self.compress) - if gbl.debug: - print "Set %s Compress to " % self.name, - printList(ln) + def setRange(self, ln): + """ set range. """ - def setRange(self, ln): - """ set range. """ + ln=self.lnExpand(ln, 'Range') - ln=self.lnExpand(ln, 'Range') + tmp = [] - tmp = [] + for n in ln: - for n in ln: + n = stof(n) + if n == 0: + n=1 + if n <= 0 or n >= 6: + error("Range %s out-of-range; must be between 0..6, not %s" % (self.name, n)) - n = stof(n) - if n == 0: - n=1 - if n <= 0 or n >= 6: - error("Range %s out-of-range; must be between 0..6, not %s." % (self.name, n)) + tmp.append(n) - tmp.append(n) + self.chordRange = seqBump(tmp) - self.chordRange = seqBump(tmp) + if self.vtype not in ("SCALE", "ARPEGGIO", "ARIA"): + warning ("Range ignored in '%s' tracks" % self.vtype) - if self.vtype not in ("SCALE", "ARPEGGIO"): - warning ("Range has no effect in '%s' tracks." % self.vtype) + if gbl.debug: + print "Set %s Range to:" % self.name, + printList(self.chordRange) - if gbl.debug: - print "Set %s Range to " % self.name, - printList(ln) + def setVoicing(self, ln): + """ set the Voicing Mode options. - def setVoicing(self, ln): - """ set the Voicing Mode options. """ + This is a stub. The real code is in patChord.py (settings are + only valid for that type). """ - if self.vtype != "CHORD": - error("Voicing is not supported for %s tracks." % self.vtype) + error("Voicing is not supported for %s tracks" % self.vtype) - for l in ln: - try: - mode, val = l.upper().split('=') - except: - error("Each Voicing option must contain a '=', not '%s'" % l) - if mode == 'MODE': - valid= ("-", "OPTIMAL", "NONE", "ROOT", "COMPRESSED", "INVERT") + def setForceOut(self): + """ Set the force output flag. This does 2 things: assigns + a midi channel and sends the voicing setting to the track. + """ - if not val in valid: - error("Valid Voicing Modes are: %s" % " ".join(valid)) + if not self.channel: + self.setChannel() + self.clearPending() - if val in ('-', 'NONE',"ROOT"): - val = None + self.insertVoice() - if val and (max(self.invert) + max(self.compress)): - warning("Setting both VoicingMode and Invert/Compress " - "is not a good idea") + def setDupRoot(self, ln): + """ set/unset root duplication. - """ When we set voicing mode we always reset this. This forces - the voicingmode code to restart its rotations. - """ + This is a stub. Only valid for CHORDs and that is where the code is.""" - self.lastChord = [] - self.voicing.mode = val + warning("RootDup has no effect in %s tracks" % self.vtype) - elif mode == 'RANGE': - val = stoi(val, "Argument for %s Voicing Range " - "must be a value." % self.name) + def setChordLimit(self, ln): + """ set/unset the chordLimit flag. """ - if val < 1 or val > 30: - error("Voicing Range '%s' out-of-range; " - "must be 1 to 30." % val) + n = stoi(ln, "Argument for %s ChordLimit must be a value" % self.name) - self.voicing.range = val + if n < 0 or n > 8: + error("ChordLimit %s out-of-range; must be 0 to 8" % n) + self.chordLimit = n - elif mode == 'CENTER': - val = stoi(val, "Argument for %s Voicing Center " - "must be a value." % self.name) + if self.vtype not in ("CHORD", "ARPEGGIO"): + warning ("Limit is ignored in %s tracks" % self.vtype) - if val < 1 or val > 12: - error("Voicing Center %s out-of-range; " - "must be 1 to 12." % val) + if gbl.debug: + print "Set %s ChordLimit to %s" % (self.name, n) - self.voicing.center = val - elif mode == 'RMOVE': - val = stoi(val, "Argument for %s Voicing Random " - "must be a value." % self.name) + def setChannel(self, ln=None): + """ Set the midi-channel number for a track. - if val < 0 or val > 100: - error("Voicing Random value must be 0 to 100 " - "not %s" % val) + - Checks for channel duplication + - Auto assigns channel number if ln=='' - self.voicing.random = val - self.voicing.bcount = 0 - elif mode == 'MOVE': - val = stoi(val, "Argument for %s Voicing Move " - "must be a value." % self.name) + If no track number was passed, then we try to + auto-alloc a track. First, we see if a preference + was set via MidiChPref. If these is no preference, + or if the preferred channel is already allocated + we go though the list, top to bottom, to find + an available channel. + """ - if val < 0 : - error("Voicing Move (bar count) must >= 0, not %s" % val) - if val > 20: - warning("Voicing Move (bar count) %s is quite large" % val) + if not ln: + try: + c=gbl.midiChPrefs[self.name] + except: + c=0 - self.voicing.bcount = val - self.voicing.random = 0 + if not c or gbl.midiAvail[c]: + c=-1 + for a in range(16, 0, -1): + if a!=10 and not gbl.midiAvail[a]: + c=a + break - elif mode == 'DIR': - val = stoi(val, "Argument for %s Voicing Dir (move direction) " - "must be a value." % self.name) + if c < 0: + error("No MIDI channel is available for %s,\n" + "Try CHShare or Delete unused tracks" % self.name) - if not val in (1,0,-1): - error("Voicing Move Dir -1, 0 or 1, not %s" % val) + else: + c = stoi(ln, "%s Channel assignment expecting Value, not %s" % + (self.name, ln)) - self.voicing.dir = val + if c<0 or c>16: + error("%s Channel must be 0..16, not %s" % (self.name, ln)) + if c == 10: + if self.vtype == 'DRUM': + pass + elif self.vtype in ('SOLO', 'MELODY') and self.drumType: + pass + else: + error("Channel 10 is reserved for DRUM, not %s" % self.name) - if gbl.debug: - v=self.voicing - print "Set %s Voicing MODE=%s" % (self.name, v.mode), - print "RANGE=%s CENTER=%s" % (v.range, v.center), - print "RMOVE=%s MOVE=%s DIR=%s" % (v.random, v.bcount, v.dir) + if self.vtype == 'DRUM' and c != 10: + error("DRUM tracks must be assigned to channel 10") + # Disable the channel. - def setForceOut(self): - """ Set the force output flag. This does 2 things: assigns - a midi channel and sends the voicing setting to the track. - """ + if c == 0: + if gbl.midiAvail[self.channel]: + gbl.midiAvail[self.channel] -= 1 + s="%s channel disabled" % self.name + if gbl.midiAvail[self.channel]: + s+=" Other tracks are still using channel %s" % self.channel + else: + s+=" Channel %s available" % self.channel + warning(s) + self.channel = 0 + self.disable = 1 + return - if not self.channel: - self.setChannel() - self.clearPending() - self.insertVoice() + if c != 10: + for a, tr in gbl.tnames.items(): + if a == self.name: # okay to reassign same number + continue + if tr.channel == c: + error("Channel %s is assigned to %s" % (c, tr.name ) ) - def setDupRoot(self, ln): - """ set/unset root duplication. """ + self.channel = c + if not self.name in gbl.midiAssigns[c]: + gbl.midiAssigns[c].append(self.name) - if self.vtype != 'CHORD': - error("RootDup can only be applied to CHORD tracks.") + gbl.midiAvail[c]+=1 - ln=self.lnExpand(ln, 'DupRoot') - tmp = [] + if not c in gbl.mtrks: + gbl.mtrks[c]=MMA.midi.Mtrk(c) + offset=0 + if gbl.debug: + print "MIDI channel %s buffer created" % c + else: + offset = gbl.tickOffset - for n in ln: - n = stoi(n, "Argument for %s DupRoot must be a value." % self.name) + if c != 10: + f=0 + for a, i in enumerate(self.midiPending): + if i[0]=='TNAME': + f=1 + if not f: + self.midiPending.append(('TNAME', 0, self.name.title() )) - if n < -9 or n > 9: - error("DupRoot %s out-of-range; must be -9 to 9." % n) + if gbl.debug: + print "MIDI Channel %s assigned to %s" % (self.channel, self.name) - tmp.append( n * 12 ) - self.dupRoot = seqBump(tmp) + def setChShare(self, ln): + """ Share midi-channel setting. """ - if gbl.debug: - print "Set %s DupRoot to " % self.name, - printList(ln) + if self.channel: # If channel already assigned, ignore + warning("Channel for %s has previously been assigned " + "(can't ChShare)" % self.name) + return + """ Get name of track to share with and make sure it exists. + If not, trackAlloc() will create the track. Do some + sanity checks and ensure that the shared track has + a channel assigned. + """ - def setChordLimit(self, ln): - """ set/unset the chordLimit flag. """ + sc = ln.upper() - n = stoi(ln, "Argument for %s ChordLimit must be a value." % self.name) + MMA.alloc.trackAlloc(sc, 1) - if n < 0 or n > 8: - error("ChordLimit %s out-of-range; must be 0 to 8." % n) + if not sc in gbl.tnames: + error("Channel '%s' does not exist. No such name" % sc) - self.chordLimit = n + if sc == self.name: + error("%s can't share MIDI channel with itself" % sc) - if self.vtype not in ("CHORD", "ARPEGGIO"): - warning ("Limit is ignored in %s tracks." % self.vtype) + if not gbl.tnames[sc].channel: + gbl.tnames[sc].setChannel() - if gbl.debug: - print "Set %s ChordLimit to %s" % (self.name, n) + schannel = gbl.tnames[sc].channel + if not schannel: + error("CHShare attempted to assign MIDI channel for %s, but " + "none avaiable" % self.name) - def setChannel(self, ln=None): - """ Set the midi-channel number for a track. - - Checks for channel duplication - - Auto assigns channel number if ln=='' + """ Actually do the assignment. Also copy voice/octave from + base track to this one ... it's going to use that voice anyway? + """ + self.channel = schannel - If no track number was passed, then we try to - auto-alloc a track. First, we see if a preference - was set via MidiChPref. If these is no preference, - or if the preferred channel is already allocated - we go though the list, top to bottom, to find - an available channel. - """ + self.voice = gbl.tnames[sc].voice[:] + self.octave = gbl.tnames[sc].octave[:] - if not ln: - try: - c=gbl.midiChPrefs[self.name] - except: - c=0 - if not c or gbl.midiAvail[c]: - c=-1 - for a in range(16, 0, -1): - if a!=10 and not gbl.midiAvail[a]: - c=a - break + # Update the avail. lists - if c < 0: - error("No MIDI channel is available for %s.\n" - "Try CHShare or Delete unused tracks." % self.name) + gbl.midiAssigns[self.channel].append(self.name) + gbl.midiAvail[self.channel]+=1 - else: - c = stoi(ln, "%s Channel assignment expecting Value, not %s" % - (self.name, ln)) - if c<0 or c>16: - error("%s Channel must be 0..16, not %s" % (self.name, ln)) + def setChannelVolume(self, v): + """ LowLevel MIDI command. Set Channel Voice. """ - if c == 10: - if self.vtype == 'DRUM': - pass - elif self.vtype in ('SOLO', 'MELODY') and self.drumType: - pass - else: - error("Channel 10 is reserved for DRUM, not %s." % self.name) + self.midiPending.append(( "CVOLUME", gbl.tickOffset, v) ) - if self.vtype == 'DRUM' and c != 10: - error("DRUM tracks must be assigned to channel 10.") + if gbl.debug: + print "Set %s MIDIChannelVolume to %s" % (self.name, v) - # Disable the channel. + def setTname(self, n): + """ Set the track name. - if c == 0: - if gbl.midiAvail[self.channel]: - gbl.midiAvail[self.channel] -= 1 - s="%s channel disabled." % self.name - if gbl.midiAvail[self.channel]: - s+=" Other tracks are still using channel %s." % self.channel - else: - s+=" Channel %s available." % self.channel - warning(s) - self.channel = 0 - self.disable = 1 - return + This is stacked and only gets output if track generates MIDI. + It is a handy way to override MMA's track naming. + """ + self.midiPending.append(('TNAME', 0, n )) + if gbl.debug: + print "Set %s track name for MIDI to %s" % (self.name, n) - if c != 10: - for a, tr in gbl.tnames.items(): - if a == self.name: # okay to reassign same number - continue + def setPan(self, ln): + """ Set MIDI Pan for this track. """ - if tr.channel == c: - error("Channel %s is assigned to %s." % (c, tr.name ) ) + v = stoi(ln[0], "Expecting integer value 0..127") - self.channel = c - if not self.name in gbl.midiAssigns[c]: - gbl.midiAssigns[c].append(self.name) + if v<0 or v>127: + error("PAN value must be 0..127") - gbl.midiAvail[c]+=1 + self.midiPending.append( ("PAN", gbl.tickOffset, v)) - if not c in gbl.mtrks: - gbl.mtrks[c]=MMA.midi.Mtrk(c) - offset=0 - if gbl.debug: - print "MIDI channel %s buffer created." % c - else: - offset = gbl.tickOffset + if gbl.debug: + print "Set %s MIDIPan to %s" % (self.name, v) - if c != 10: - f=0 - for a, i in enumerate(self.midiPending): - if i[0]=='TNAME': - f=1 - if not f: - self.midiPending.append(('TNAME', 0, self.name.title() )) - if gbl.debug: - print "MIDI Channel %s assigned to %s." % (self.channel, self.name) + def setGlis(self, ln): + """ Set MIDI Glis for this track. """ - def setChShare(self, ln): - """ Share midi-channel setting. """ + v = stoi(ln, "Expecting integer for Portamento") - if self.channel: # If channel already assigned, ignore - warning("Channel for %s has previously been assigned " - "(can't ChShare)." % self.name) - return + if v<0 or v>127: + error("Value for Portamento must be 0..127") - """ Get name of track to share with and make sure it exists. - If not, trackAlloc() will create the track. Do some - sanity checks and ensure that the shared track has - a channel assigned. - """ + self.midiPending.append( ("GLIS", gbl.tickOffset, v)) - sc = ln.upper() + if gbl.debug: + print "Set %s MIDIPortamento to %s" % (self.name, v) - MMA.alloc.trackAlloc(sc, 1) - if not sc in gbl.tnames: - error("Channel '%s' does not exist. No such name." % sc) - if sc == self.name: - error("%s can't share MIDI channel with itself." % sc) + def setStrum(self, ln): + """ Set Strum time. CHORD only option. """ + warning("Strum has no effect in %s tracks" % self.name) - if not gbl.tnames[sc].channel: - gbl.tnames[sc].setChannel() - schannel = gbl.tnames[sc].channel + def setTone(self, ln): + """ Set Tone. Error trap, only drum tracks have tone. """ - if not schannel: - error("CHShare attempted to assign MIDI channel for %s, but " - "none avaiable." % self.name) + error("Tone command not supported for %s track" % self.name) - """ Actually do the assignment. Also copy voice/octave from - base track to this one ... it's going to use that voice anyway? - """ + def setOn(self): + """ Turn ON track. """ - self.channel = schannel + self.disable = 0 + self.ssvoice = -1 - self.voice = gbl.tnames[sc].voice[:] - self.octave = gbl.tnames[sc].octave[:] + if gbl.debug: + print "%s Enabled" % self.name - # Update the avail. lists + def setOff(self): + """ Turn OFF track. """ - gbl.midiAssigns[self.channel].append(self.name) - gbl.midiAvail[self.channel]+=1 + self.disable = 1 + if gbl.debug: + print "%s Disabled" % self.name - def setChannelVolume(self, v): - """ LowLevel MIDI command. Set Channel Voice. """ - self.midiPending.append(( "CVOLUME", gbl.tickOffset, v) ) - if gbl.debug: - print "Set %s MIDIChannelVolume to %s" % (self.name, v) + def setRVolume(self, ln): + """ Set the volume randomizer for a track. """ - def setTname(self, n): - """ Set the track name. + ln = self.lnExpand(ln, 'RVolume') + tmp = [] - This is stacked and only gets output if track generates MIDI. - It is a handy way to override MMA's track naming. - """ + for n in ln: - self.midiPending.append(('TNAME', 0, n )) - if gbl.debug: - print "Set %s track name for MIDI to %s" % (self.name, n) + n = stoi(n, "Argument for %s RVolume must be a value" % self.name) - def setPan(self, ln): - """ Set MIDI Pan for this track. """ + if n < 0 or n > 100: + error("RVolume %s out-of-range; must be 0..100" % n) - v = stoi(ln[0], "Expecting integer value 0..127") + if n > 30: + warning("%s is a large RVolume value!" % n) - if v<0 or v>127: - error("PAN value must be 0..127") + tmp.append( n/100. ) - self.midiPending.append( ("PAN", gbl.tickOffset, v)) + self.rVolume = seqBump(tmp) - if gbl.debug: - print "Set %s MIDIPan to %s" % (self.name, v) + if gbl.debug: + print "Set %s Rvolume to:" % self.name, + for n in self.rVolume: + print int(n * 100), + print + def setRSkip(self, ln): + """ Set the note random skip factor for a track. """ - def setGlis(self, ln): - """ Set MIDI Glis for this track. """ + ln = self.lnExpand(ln, 'RSkip') + tmp = [] - v = stoi(ln, "Expecting integer for Portamento") + for n in ln: + n = stoi(n, "Expecting integer after in RSkip") - if v<0 or v>127: - error("Value for Portamento must be 0..127") + if n < 0 or n > 99: + error("RSkip arg must be 0..99") - self.midiPending.append( ("GLIS", gbl.tickOffset, v)) + tmp.append(n/100.) - if gbl.debug: - print "Set %s MIDIPortamento to %s" % (self.name, v) + self.rSkip = seqBump(tmp) + if gbl.debug: + print "Set %s RSkip to:" % self.name, + for n in self.rSkip: + print int(n * 100), + print - def setStrum(self, ln): - """ Set Strum time. """ + def setRTime(self, ln): + """ Set the timing randomizer for a track. """ - # Strum is only valid for CHORD tracks. + ln=self.lnExpand(ln, 'RTime') + tmp = [] - if self.vtype != "CHORD": - error( "Strum is only valid in Chord tracks, you tried to " - "set it in a %s track." % self.name) + for n in ln: + n=stoi(n, "Expecting an integer for Rtime") + if n < 0 or n > 100: + error("RTime %s out-of-range; must be 0..100" % n) - ln=self.lnExpand(ln, 'Strum') - tmp = [] + tmp.append(n) - for n in ln: - n = stoi(n, "Argument for %s Strum must be an integer" % self.name) + self.rTime = seqBump(tmp) - if n < 0 or n > 100: - error("Strum %s out-of-range; must be 0..100." % n) + if gbl.debug: + print "Set %s RTime to:" % self.name, + printList(self.rTime) - tmp.append(n) - self.strum = seqBump(tmp) + def setRnd(self, arg): + """ Enable random pattern selection from sequence.""" - if gbl.debug: - print "Set %s Strum to %s" % (self.name, self.strum) + if arg in ("ON", "1"): + self.seqRnd = 1 + elif arg in ("OFF", "0"): + self.seqRnd = 0 - def setTone(self, ln): - """ Set Tone. Error trap, only drum tracks have tone. """ + else: + error("SeqRnd: '%s' is not a valid option" % arg) - error("Tone command not supported for %s track." % self.name) + if gbl.debug: + if self.seqRnd: + a="On" + else: + a="Off" + print "%s SeqRnd: %s" % (self.name, a) - def setOn(self): - """ Turn ON track. """ + def setRndWeight(self, ln): + """ Set weighting factors for seqrnd. """ - self.disable = 0 - self.ssvoice = -1 + ln = self.lnExpand(ln, "SeqRndWeight") + tmp = [] - if gbl.debug: - print "%s Enabled" % self.name + for n in ln: + n = stoi(n) + if n < 0: error("SeqRndWeight: Values must be 0 or greater") + tmp.append(n) + self.seqRndWeight = seqBump(tmp) - def setOff(self): - """ Turn OFF track. """ + if gbl.debug: + print "%s SeqRndWeight:" % self.name, + printList(self.seqRndWeight) - self.disable = 1 - if gbl.debug: - print "%s Disabled" % self.name + def setDirection(self, ln): + """ Set scale direction. """ + ln = self.lnExpand(ln, "Direction") + tmp = [] + for n in ln: + n = n.upper() + if not n in ('UP', 'DOWN', 'BOTH', 'RANDOM'): + error("Unknown %s Direction '%s'" % (self.name, n) ) + tmp.append(n) - def setRVolume(self, ln): - """ Set the volume randomizer for a track. """ + self.direction = seqBump(tmp) - ln = self.lnExpand(ln, 'RVolume') - tmp = [] + if self.vtype == 'SCALE': + self.lastChord = None + self.lastNote = -1 - for n in ln: - n = stoi(n, "Argument for %s RVolume must be a value." % self.name) + if gbl.debug: + print "Set %s Direction to:" % self.name, + printList(self.direction) - if n < 0 or n > 100: - error("RVolume %s out-of-range; must be 0..100." % n) - if n > 30: - warning("%s is a large RVolume value!" % n) + def setScaletype(self, ln): + """ Set scale type. - tmp.append( n/100. ) + This is a error stub. The real code is in the permitted track code. + """ - self.rVolume = seqBump(tmp) + warning("ScaleType has no effect in %s tracks") % self.vtype - if gbl.debug: - print "Set %s Rvolume to " % self.name, - for n in self.rVolume: - print int(n * 100), - print + def setInvert(self, ln): + """ Set inversion for track. - def setRSkip(self, ln): - """ Set the note random skip factor for a track. """ + This can be applied to any track, + but has no effect in drum tracks. It inverts the chord + by one rotation for each value. + """ - ln = self.lnExpand(ln, 'RSkip') - tmp = [] + ln=self.lnExpand(ln, "Invert") - for n in ln: - n = stoi(n, "Expecting integer after in RSkip") + vwarn = 0 + tmp = [] - if n < 0 or n > 99: - error("RSkip arg must be 0..99") + for n in ln: + n = stoi(n, "Argument for %s Invert must be an integer" % self.name) - tmp.append(n/100.) + if n and self.vtype=='CHORD' and self.voicing.mode: + vwarn = 1 - self.rSkip = seqBump(tmp) + tmp.append(n) - if gbl.debug: - print "Set %s RSkip to " % self.name, - for n in self.rSkip: - print int(n * 100), - print + self.invert = seqBump(tmp) + if self.vtype not in ("CHORD", "ARPEGGIO"): + warning ("Invert is ignored in %s tracks" % self.vtype) - def setRTime(self, ln): - """ Set the timing randomizer for a track. """ + if vwarn: + warning("Setting both Voicing Mode and Invert is not a good idea") - ln=self.lnExpand(ln, 'RTime') - tmp = [] + if gbl.debug: + print "Set %s Invert to:" % self.name, + printList(self.invert) - for n in ln: - n=stoi(n, "Expecting an integer for Rtime") - if n < 0 or n > 100: - error("RTime %s out-of-range; must be 0..100." % n) - tmp.append(n) + def setOctave(self, ln): + """ Set the octave for a track. """ - self.rTime = seqBump(tmp) + ln=self.lnExpand(ln, 'Octave') + tmp = [] - if gbl.debug: - print "Set %s RTime to " % self.name, - printList(ln) + for n in ln: + n = stoi(n, "Argument for %s Octave must be an integer" % self.name) + if n < 0 or n > 10: + error("Octave %s out-of-range; must be 0..10" % n) + tmp.append( n * 12 ) - def setRnd(self, arg): - """ Enable random pattern selection from sequence.""" + self.octave = seqBump(tmp) - if arg in ("ON", "1"): - self.seqRnd = 1 + if gbl.debug: + print "Set %s Octave to:" % self.name, + for i in self.octave: + print i/12, + print - elif arg in ("OFF", "0"): - self.seqRnd = 0 - else: - error("SeqRnd: '%s' is not a valid option." % arg) + def setSpan(self, start, end): + """ Set span. - if gbl.debug: - if self.seqRnd: - a="On" - else: - a="Off" - print "%s SeqRnd: %s" % (self.name, a) + Note: The start/end parm has been verified in parser. + """ - def setRndWeight(self, ln): - """ Set weighting factors for seqrnd. """ + if self.vtype == 'DRUM': + warning("Span has no effect in Drum tracks") - ln = self.lnExpand(ln, "SeqRndWeight") - tmp = [] + self.spanStart = start + self.spanEnd = end - for n in ln: - n = stoi(n) - if n < 0: error("SeqRndWeight: Values must be 0 or greater.") - tmp.append(n) + if gbl.debug: + print "Set %s Span to %s...%s" % (self.name, self.spanStart, self.spanEnd) - self.seqRndWeight = seqBump(tmp) - if gbl.debug: - print "%s SeqRndWeight: " % self.name, - printList(self.seqRndWeight) + def setHarmony(self, ln): + """ Set the harmony. """ + ln=self.lnExpand(ln, 'Harmony') + tmp = [] - def setDirection(self, ln): - """ Set scale direction. """ + for n in ln: + n = n.upper() + if n in ( '-', '-0', 'NONE'): + n = None - ln = self.lnExpand(ln, "Direction") - tmp = [] + tmp.append(n) - for n in ln: - n = n.upper() - if not n in ('UP', 'DOWN', 'BOTH', 'RANDOM'): - error("Unknown %s Direction '%s'." % (self.name, n) ) - tmp.append(n) + self.harmony = seqBump(tmp) - self.direction = seqBump(tmp) + if self.vtype in ( 'CHORD', 'DRUM' ): + warning("Harmony setting for %s track ignored" % self.vtype) - if self.vtype == 'SCALE': - self.lastChord = None - self.lastNote = -1 + if gbl.debug: + print "Set %s Harmony to:" % self.name, + printList(self.harmony) - if gbl.debug: - print "Set %s Direction to " % self.name, - printList(ln) + def setHarmonyOnly(self, ln): + """ Set the harmony only. """ - def setScaletype(self, ln): - """ Set scale type. """ + ln=self.lnExpand(ln, 'HarmonyOnly') + tmp = [] - if self.vtype != 'SCALE': - error("ScaleType only valid in Scale tracks.") + for n in ln: + n = n.upper() + if n in ('-', '0'): + n = None - ln = self.lnExpand(ln, "ScaleType") - tmp = [] + tmp.append(n) - for n in ln: - n = n.upper() - if not n in ( 'CHROMATIC', 'AUTO'): - error("Unknown %s ScaleType. Only Chromatic and Auto are valid." % self.name) - tmp.append(n) + self.harmony = seqBump(tmp) + self.harmonyOnly = seqBump(tmp) - self.scaleType = seqBump(tmp) + if self.vtype in ( 'CHORD', 'DRUM'): + warning("HarmonyOnly setting for %s track ignored" % self.vtype) - if gbl.debug: - print "Set %s ScaleType to " % self.name, - printList(ln) + if gbl.debug: + print "Set %s HarmonyOnly to:" % self.name, + printList(self.harmonyOnly) + def setHarmonyVolume(self, ln): + """ Set harmony volume adjustment. """ - def setInvert(self, ln): - """ Set inversion for track. + ln=self.lnExpand(ln, 'HarmonyOnly') + tmp = [] - This can be applied to any track, - but has no effect in drum tracks. It inverts the chord - by one rotation for each value. - """ + for n in ln: + v=stoi(n) - ln=self.lnExpand(ln, "Invert") - vwarn = 0 - tmp = [] + if v<0: + error("HarmonyVolume adjustment must be positive integer") + tmp.append(v/100.) - for n in ln: - n = stoi(n, "Argument for %s Invert must be an integer" % self.name) + self.harmonyVolume = seqBump(tmp) - if n and self.vtype=='CHORD' and self.voicing.mode: - vwarn = 1 + if self.vtype in ( 'CHORD', 'DRUM' ): + warning("HarmonyVolume adjustment for %s track ignored" % self.vtype) - tmp.append(n) + if gbl.debug: + print "Set %s HarmonyVolume to:" % self.name, + printList(self.harmonyVolume) - self.invert = seqBump(tmp) - if self.vtype not in ("CHORD", "ARPEGGIO"): - warning ("Invert is ignored in %s tracks." % self.vtype) + def setSeqSize(self): + """ Expand existing pattern list. """ - if vwarn: - warning("Setting both Voicing Mode and Invert is not a good idea") + self.sequence = seqBump(self.sequence) + if self.midiVoice: + self.midiVoice = seqBump(self.midiVoice) + if self.midiSeq: + self.midiSeq = seqBump(self.midiSeq) + self.invert = seqBump(self.invert) + self.artic = seqBump(self.artic) + self.volume = seqBump(self.volume) + self.voice = seqBump(self.voice) + self.rVolume = seqBump(self.rVolume) + self.rSkip = seqBump(self.rSkip) + self.rTime = seqBump(self.rTime) + self.seqRndWeight = seqBump(self.seqRndWeight) + self.strum = seqBump(self.strum) + self.octave = seqBump(self.octave) + self.harmony = seqBump(self.harmony) + self.harmonyOnly = seqBump(self.harmonyOnly) + self.harmonyVolume = seqBump(self.harmonyVolume) + self.direction = seqBump(self.direction) + self.scaleType = seqBump(self.scaleType) + self.compress = seqBump(self.compress) + self.chordRange = seqBump(self.chordRange) + self.dupRoot = seqBump(self.dupRoot) + self.unify = seqBump(self.unify) + self.accent = seqBump(self.accent) - if gbl.debug: - print "Set %s Invert to " % self.name, - printList(ln) + if self.vtype == "DRUM": + self.toneList = seqBump(self.toneList) - def setOctave(self, ln): - """ Set the octave for a track. """ + def setVoice(self, ln): + """ Set the voice for a track. - ln=self.lnExpand(ln, 'Octave') - tmp = [] + Note, this just sets flags, the voice is set in bar(). + ln[] is not nesc. set to the correct length. + """ - for n in ln: - n = stoi(n, "Argument for %s Octave must be an integer" % self.name) - if n < 0 or n > 10: - error("Octave %s out-of-range; must be 0..10." % n) + ln=self.lnExpand(ln, 'Voice') + tmp = [] - tmp.append( n * 12 ) + for n in ln: + n = MMA.translate.vtable.get(n) + a=MMA.midiC.instToValue(n) - self.octave = seqBump(tmp) + if a < 0: + a=stoi(n, "Expecting a valid voice name or value, " + "not '%s'" % n) + if a <0 or a > 127: + error("Voice must be 0..127") + tmp.append( a ) - if gbl.debug: - print "Set %s Octave to" % self.name, - for i in self.octave: - print i/12, - print + self.voice = seqBump(tmp) - def setSpan(self, start, end): - """ Set span. + if self.channel and len(gbl.midiAssigns[self.channel])>1: + a='' + for n in gbl.midiAssigns[self.channel]: + if n != self.name: + a += ' %s' % n + warning("Track %s is shared with %s,\n" + " changing voice may create conflict" % (a,self.name)) - Note: The start/end parm has been verified in parser. - """ + if gbl.debug: + print "Set %s Voice to:" % self.name, + for a in self.voice: + print MMA.midiC.valueToInst(a), + print - if self.vtype == "DRUM": - error("Span not supported in Drum tracks.") - self.spanStart = start - self.spanEnd = end + def setMidiClear(self, ln): + """ Set MIDIclear sequences. """ - if gbl.debug: - print "Set %s Span to %s...%s." % (self.name, self.spanStart, self.spanEnd) + if ln[0] in 'zZ-': + self.midiClear = None + else: + self.midiClear = MMA.mdefine.mdef.get(ln[0]) - def setHarmony(self, ln): - """ Set the harmony. """ + if gbl.debug: + print "%s MIDIClear: %s" % (self.name, self.midiSeqFmt(self.midiClear)) - ln=self.lnExpand(ln, 'Harmony') - tmp = [] + def doMidiClear(self): + """ Reset MIDI settings. """ - for n in ln: - n = n.upper() - if n in ( '-', '-0', 'NONE'): - n = None + if self.midiSent: + if not self.midiClear: + warning("%s: Midi data has been inserted with MIDIVoice/Seq " + "but no MIDIClear data is present" % self.name) - tmp.append(n) + else: + for i in self.midiClear: + gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) - self.harmony = seqBump(tmp) + self.midiSent = 0 - if self.vtype in ( 'CHORD', 'DRUM' ): - warning("Harmony setting for %s track ignored" % self.vtype) - if gbl.debug: - print "Set %s Harmony to" % self.name, - printList(self.harmony) + def setMidiSeq(self, ln): + """ Set a midi sequence for a track. + This is sent for every bar. Syntax is: + hh .. ; ... - def setHarmonyOnly(self, ln): - """ Set the harmony only. """ + or a single '-' to disable. + """ + """ lnExpand() works here! The midi data has been converted to + pseudo-macros already in the parser. """ - ln=self.lnExpand(ln, 'HarmonyOnly') - tmp = [] + ln=self.lnExpand(ln, "MidiSeq") - for n in ln: - n = n.upper() - if n in ('-', '0'): - n = None + seq = [] + for a in ln: + if a in 'zZ-': + seq.append(None) + else: + seq.append(MMA.mdefine.mdef.get(a.upper())) - tmp.append(n) + if seq.count(None) == len(seq): + self.midiSeq = [] + else: + self.midiSeq = seqBump( seq ) - self.harmony = seqBump(tmp) - self.harmonyOnly = seqBump(tmp) + if gbl.debug: + print "%s MIDISeq:" % self.name, + for l in seq: + print '{ %s }' % self.midiSeqFmt(l), - if self.vtype in ( 'CHORD', 'DRUM'): - warning("HarmonyOnly setting for %s track ignored" % self.vtype) - if gbl.debug: - print "Set %s HarmonyOnly to" % self.name, - printList(self.harmonyOnly) + def setMidiVoice(self, ln): + """ Set a MIDI sequence for a track. - def setHarmonyVolume(self, ln): - """ Set harmony volume adjustment. """ + This is sent whenever we send a VOICE. Syntax is: + hh .. ; ... - ln=self.lnExpand(ln, 'HarmonyOnly') - tmp = [] + or a single '-' to disable. + """ - for n in ln: - v=stoi(n) + """ lnExpand() works here! The midi data has been converted to + pseudo-macros already in the parser. """ - if v<0: - error("HarmonyVolume adjustment must be positive integer") - tmp.append(v/100.) + ln = self.lnExpand(ln, 'MIDIVoice') - self.harmonyVolume = seqBump(tmp) + seq = [] + for a in ln: + if a in 'zZ': + seq.append(None) + else: + seq.append(MMA.mdefine.mdef.get(a.upper())) - if self.vtype in ( 'CHORD', 'DRUM' ): - warning("HarmonyVolume adjustment for %s track ignored" % self.vtype) + if seq.count(None) == len(seq): + self.midiVoice = [] + else: + self.midiVoice = seqBump( seq ) - if gbl.debug: - print "Set %s HarmonyVolume to" % self.name, - printList(self.harmonyVolume) + if gbl.debug: + print "%s MIDIVoice:" % self.name, + for l in seq: + print '{ %s }' % self.midiSeqFmt(l), + print - def setSeqSize(self): - """ Expand existing pattern list. """ - self.sequence = seqBump(self.sequence) - if self.midiVoice: - self.midiVoice = seqBump(self.midiVoice) - if self.midiSeq: - self.midiSeq = seqBump(self.midiSeq) - self.invert = seqBump(self.invert) - self.artic = seqBump(self.artic) - self.volume = seqBump(self.volume) - self.voice = seqBump(self.voice) - self.rVolume = seqBump(self.rVolume) - self.rSkip = seqBump(self.rSkip) - self.rTime = seqBump(self.rTime) - self.seqRndWeight = seqBump(self.seqRndWeight) - self.strum = seqBump(self.strum) - self.octave = seqBump(self.octave) - self.harmony = seqBump(self.harmony) - self.harmonyOnly = seqBump(self.harmonyOnly) - self.harmonyVolume = seqBump(self.harmonyVolume) - self.direction = seqBump(self.direction) - self.scaleType = seqBump(self.scaleType) - self.compress = seqBump(self.compress) - self.chordRange = seqBump(self.chordRange) - self.dupRoot = seqBump(self.dupRoot) - self.unify = seqBump(self.unify) - self.accent = seqBump(self.accent) + def midiSeqFmt(self, lst): + """ Used by setMidiVoice/Clear/Seq for debugging format. """ - if self.vtype == "DRUM": - self.toneList = seqBump(self.toneList) + if lst == None: + return '' + ret='' + for i in lst: + ret += "%s %s 0x%02x ; " % (i[0], + MMA.midiC.valueToCtrl(ord(i[1][0])), + ord(i[1][1])) + return ret.rstrip("; ") - def setVoice(self, ln): - """ Set the voice for a track. + def setVolume(self, ln): + """ Set the volume for a pattern. + ln - list of volume names (pp, mf, etc) + ln[] not nesc. correct length + """ - Note, this just sets flags, the voice is set in bar(). - ln[] is not nesc. set to the correct length. - """ + ln=self.lnExpand(ln, 'Volume') + tmp = [None] * len(ln) - ln=self.lnExpand(ln, 'Voice') - tmp = [] + for i,n in enumerate(ln): + a = MMA.volume.calcVolume(n, self.volume[i]) - for n in ln: - n = MMA.translate.vtable.get(n) - a=MMA.midiC.instToValue(n) + if self.vtype == 'DRUM': + a=MMA.translate.drumVolTable.get(self.toneList[i], a) + else: + a=MMA.translate.voiceVolTable.get(self.voice[i], a) + tmp[i] = a - if a < 0: - a=stoi(n, "Expecting a valid voice name or value, " - "not '%s'" % n) - if a <0 or a > 127: - error("Voice must be 0..127.") - tmp.append( a ) + self.volume = seqBump(tmp) - self.voice = seqBump(tmp) + if gbl.debug: + print "Set %s Volume to:" % self.name, + for a in self.volume: + print int(a * 100), + print - if self.channel and len(gbl.midiAssigns[self.channel])>1: - a='' - for n in gbl.midiAssigns[self.channel]: - if n != self.name: - a += ' %s' % n - warning("Track %s is shared with %s.\n" - " Changing voice may create conflict." % (a,self.name)) + def setCresc(self, dir, ln): + """ Set Crescendo for a track. """ + if len(ln) == 3: + self.setVolume([ln[0]]) + ln=ln[1:] - if gbl.debug: - print "Set %s Voice to: " % self.name, - for a in self.voice: - print MMA.midiC.valueToInst(a), - print + vol = self.volume[0] + if self.volume.count(vol) != len(self.volume): + warning("(De)Crescendo being used with track with variable sequence volumes") - def setMidiClear(self, ln): - """ Set MIDIclear sequences. """ + self.futureVols = MMA.volume.fvolume(dir, vol, ln) - if ln[0] in 'zZ-': - self.midiClear = None - else: - self.midiClear = MMA.mdefine.mdef.get(ln[0]) + def setMallet(self, ln): + """ Mallet (repeat) settngs. """ - if gbl.debug: - print "%s MIDIClear: %s" % (self.name, self.midiSeqFmt(self.midiClear)) + for l in ln: + try: + mode, val = l.upper().split('=') + except: + error("Each Mallet option must contain a '=', not '%s'" % l) + if mode == 'RATE': + self.mallet = getNoteLen(val) - def doMidiClear(self): - """ Reset MIDI settings. """ + elif mode == 'DECAY': + val = stof(val, "Mallet Decay must be a value, not '%s'" % val) - if self.midiSent: - if not self.midiClear: - warning("%s: Midi data has been inserted with MIDIVoice/Seq " - "but no MIDIClear data is present." % self.name) + if val < -50 or val > 50: + error("Mallet Decay rate must be -50..+50") - else: - for i in self.midiClear: - gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) + self.malletDecay = val/100 - self.midiSent = 0 + if gbl.debug: + print "%s Mallet Rate:%s Decay:%s" % \ + (self.name, self.mallet, self.malletDecay) - def setMidiSeq(self, ln): - """ Set a midi sequence for a track. + def setAccent(self, ln): + """ Set the accent values. This is a list of lists, a list for each seq. """ - This is sent for every bar. Syntax is: - hh .. ; ... + tmp = [] - or a single '-' to disable. - """ - """ lnExpand() works here! The midi data has been converted to - pseudo-macros already in the parser. """ + """ We can do "Track Accent 1 20 3 -10" or "Track Accent {1 20 3 -10}" + or even something like "Track Accent {1 20} / {/} {3 20}" + Note that the "/" can or not have {}s. + """ - ln=self.lnExpand(ln, "MidiSeq") + ln = ' '.join(ln) + if not ln.startswith('{'): + ln='{' + ln +"}" - seq = [] - for a in ln: - if a in 'zZ-': - seq.append(None) - else: - seq.append(MMA.mdefine.mdef.get(a.upper())) + # Convert string to list. One entry per seq. - if seq.count(None) == len(seq): - self.midiSeq = [] - else: - self.midiSeq = seqBump( seq ) + l=[] + while ln: + if not ln.startswith("{"): + if ln[0]=='/': + l.append('/') + ln=ln[1:].strip() + else: + error("Unknown value in %s Accent: %s" % (self.name, ln[0])) + else: + a,b = pextract(ln, "{", "}", 1) + ln=a.strip() + if len(b)==1 and b[0]=='/': + l.append('/') + else: + l.append(b[0].split()) - if gbl.debug: - print "%s MIDISeq:" % self.name, - for l in seq: - print '{ %s }' % self.midiSeqFmt(l), + ln=self.lnExpand(l, 'Accent') - def setMidiVoice(self, ln): - """ Set a MIDI sequence for a track. + for l in ln: + tt=[] + if len(l)/2*2 != len(l): + error("Use: %s Accent Beat Percentage [...]" % self.name) - This is sent whenever we send a VOICE. Syntax is: - hh .. ; ... + for b, v in zip(l[::2], l[1::2]): + b=self.setBarOffset( b ) + v=stoi(v, "Bbeat offset must be a value, not '%s'" % v) + if v < -100 or v > 100: + error("Velocity adjustment (as percentage) must " + "be -100..100, not '%s'" % v) - or a single '-' to disable. - """ + tt.append( (b, v/100. ) ) + tmp.append(tt) - """ lnExpand() works here! The midi data has been converted to - pseudo-macros already in the parser. """ + self.accent = seqBump( tmp ) - ln = self.lnExpand(ln, 'MIDIVoice') + if gbl.debug: + print "%s Accent:" % self.name, + for s in self.accent: + print "{", + for b,v in s: + print '%s %s' % (1+(b/float(gbl.BperQ)), int(v*100)), + print "}", + print - seq = [] - for a in ln: - if a in 'zZ': - seq.append(None) - else: - seq.append(MMA.mdefine.mdef.get(a.upper())) - if seq.count(None) == len(seq): - self.midiVoice = [] - else: - self.midiVoice = seqBump( seq ) + def setArtic(self, ln): + """ Set the note articuation value. """ + ln=self.lnExpand(ln, 'Articulate') + tmp = [] - if gbl.debug: - print "%s MIDIVoice:" % self.name, - for l in seq: - print '{ %s }' % self.midiSeqFmt(l), - print + for n in ln: + a = stoi(n, "Expecting value in articulation setting") + if a < 1 or a > 200: + error("Articulation setting must be 1..200, not %s" % a) + if a>150: + warning("Large Articulate value: %s" % a) - def midiSeqFmt(self, lst): - """ Used by setMidiVoice/Clear/Seq for debugging format. """ + tmp.append(a) - if lst == None: - return '' - ret='' - for i in lst: - ret += "%s %s 0x%02x ; " % (i[0], - MMA.midiC.valueToCtrl(ord(i[1][0])), - ord(i[1][1])) - return ret.rstrip("; ") + self.artic = seqBump(tmp) + if gbl.debug: + print "Set %s Articulate to:" % self.name, + printList(self.artic) - def setVolume(self, ln): - """ Set the volume for a pattern. - ln - list of volume names (pp, mf, etc) - ln[] not nesc. correct length - """ - ln=self.lnExpand(ln, 'Volume') - tmp = [None] * len(ln) + def setUnify(self, ln): + """ Set unify. """ - for i,n in enumerate(ln): - a = MMA.volume.calcVolume(n, self.volume[i]) + ln = self.lnExpand(ln, "Unify") + tmp = [] - if self.vtype == 'DRUM': - a=MMA.translate.drumVolTable.get(self.toneList[i], a) - else: - a=MMA.translate.voiceVolTable.get(self.voice[i], a) - tmp[i] = a + for n in ln: + n=n.upper() + if n in ( 'ON', '1'): + tmp.append(1) + elif n in( 'OFF', '0'): + tmp.append(0) + else: + error("Unify accepts ON | OFF | 0 | 1") - self.volume = seqBump(tmp) + self.unify = seqBump(tmp) - if gbl.debug: - print "Set %s Volume to " % self.name, - for a in self.volume: - print int(a * 100), - print + if gbl.debug: + print "Set %s Unify to:" % self.name, + printList(self.unify) - def setCresc(self, dir, ln): - """ Set Crescendo for a track. """ - if len(ln) == 3: - self.setVolume([ln[0]]) - ln=ln[1:] + def lnExpand(self, ln, cmd): + """ Validate and expand a list passed to a set command. """ - vol = self.volume[0] + if len(ln) > gbl.seqSize: + warning("%s list truncated to %s patterns" % (self.name, gbl.seqSize) ) + ln = ln[:gbl.seqSize] + + last = None - if self.volume.count(vol) != len(self.volume): - warning("(De)Crescendo being used with track with variable sequence volumes.") + for i,n in enumerate(ln): + if n == '/': + if not last: + error ("You cannot use a '/' as the first item " + "in a %s list" % cmd) + else: + ln[i] = last + else: + last = n - self.futureVols = MMA.volume.fvolume(dir, vol, ln) + return ln + def copySettings(self, cp): + """ Copy the voicing from a 2nd voice to the current one. """ + if not cp in gbl.tnames: + error("CopySettings does not know track '%s'" % cp) - def setMallet(self, ln): - """ Mallet (repeat) settngs. """ + cp=gbl.tnames[cp] - for l in ln: - try: - mode, val = l.upper().split('=') - except: - error("Each Mallet option must contain a '=', not '%s'" % l) + if cp.vtype != self.vtype: + error("Tracks must be of same type for copy ... " + "%s and %s aren't" % (self.name, cp.name)) + + self.volume = cp.volume[:] + self.rVolume = cp.rVolume[:] + self.accent = cp.accent[:] + self.rSkip = cp.rSkip[:] + self.rTime = cp.rTime[:] + self.strum = cp.strum[:] + self.octave = cp.octave[:] + self.harmony = cp.harmony[:] + self.harmonyOnly = cp.harmonyOnly[:] + self.harmonyVolume = cp.harmonyVolume[:] + self.direction = cp.direction[:] + self.scaleType = cp.scaleType[:] + self.voice = cp.voice[:] + self.invert = cp.invert[:] + self.artic = cp.artic[:] + self.compress = cp.compress[:] + + self.riff = cp.riff[:] + + if self.vtype == 'DRUM': + self.toneList = cp.toneList[:] + + + if gbl.debug: + print "Settings from %s copied to %s" % (cp.name, self.name) + + + + ################################################## + ## Save/restore grooves + + def saveGroove(self, gname): + """ Define a groove. + + Called by the 'DefGroove Name'. This is called for + + each track. + + If 'gname' is already defined it is overwritten. + + Note aux. function which may be defined for each track type. + """ + + self.grooves[gname] = { + 'ACCENT': self.accent[:], + 'ARTIC': self.artic[:], + 'COMPRESS': self.compress[:], + 'DIR': self.direction[:], + 'DUPROOT': self.dupRoot[:], + 'HARMONY': self.harmony[:], + 'HARMONYO': self.harmonyOnly[:], + 'HARMONYV': self.harmonyVolume[:], + 'INVERT': self.invert[:], + 'LIMIT': self.chordLimit, + 'RANGE': self.chordRange[:], + 'OCTAVE': self.octave[:], + 'RSKIP': self.rSkip[:], + 'RTIME': self.rTime[:], + 'RVOLUME': self.rVolume[:], + 'SCALE': self.scaleType[:], + 'SEQ': self.sequence[:], + 'SEQRND': self.seqRnd, + 'SEQRNDWT': self.seqRndWeight[:], + 'STRUM': self.strum[:], + 'VOICE': self.voice[:], + 'VOLUME': self.volume[:], + 'UNIFY': self.unify[:], + 'MIDISEQ': self.midiSeq[:], + 'MIDIVOICE':self.midiVoice[:], + 'MIDICLEAR':self.midiClear[:], + 'SPAN': (self.spanStart, self.spanEnd), + 'MALLET': (self.mallet, self.malletDecay), + } + + + if self.vtype == 'CHORD': + self.grooves[gname]['VMODE'] = copy.deepcopy(self.voicing) + + if self.vtype == 'DRUM': + self.grooves[gname]['TONES'] = self.toneList[:] - if mode == 'RATE': - self.mallet = getNoteLen(val) - elif mode == 'DECAY': - val = stof(val, "Mallet Decay must be a value, not '%s'." % val) + def restoreGroove(self, gname): + """ Restore a defined groove. """ + + self.doMidiClear() + + g = self.grooves[gname] + + self.sequence = g['SEQ'] + self.volume = g['VOLUME'] + self.accent = g['ACCENT'] + self.rTime = g['RTIME'] + self.rVolume = g['RVOLUME'] + self.rSkip = g['RSKIP'] + self.strum = g['STRUM'] + self.octave = g['OCTAVE'] + self.voice = g['VOICE'] + self.harmonyOnly= g['HARMONYO'] + self.harmony = g['HARMONY'] + self.harmonyVolume = g['HARMONYV'] + self.direction = g['DIR'] + self.scaleType = g['SCALE'] + self.invert = g['INVERT'] + self.artic = g['ARTIC'] + self.seqRnd = g['SEQRND' ] + self.seqRndWeight = g['SEQRNDWT'] + self.compress = g['COMPRESS'] + self.chordRange = g['RANGE'] + self.dupRoot = g['DUPROOT'] + self.chordLimit = g['LIMIT'] + self.unify = g['UNIFY'] + self.midiClear = g['MIDICLEAR'] + self.midiSeq = g['MIDISEQ'] + self.midiVoice = g['MIDIVOICE'] + self.spanStart, self.spanEnd = g['SPAN'] + self.mallet, self.malletDecay = g['MALLET'] + + if self.vtype == 'CHORD': + self.voicing = g['VMODE'] + + if self.vtype == 'DRUM': + self.toneList = g['TONES'] + + + """ It's quite possible that the track was created after + the groove was saved. This means that the data restored + was just the default stuff inserted when the track + was created ... which is fine, but the sequence size + isn't necs. right. We can probably test any list, and octave[] + is as good as any. + """ + + if len(self.octave) != gbl.seqSize: + self.setSeqSize() + + #################################### + ## Sequence functions + + def setSequence(self, ln): + """ Set the sequence for a track. + + The ln passed from the parser should be a list of existing + patterns, plus the special 'patterns' Z, z, -, and *. Remember + that the parser has already converted {} patterns to a special + pattern line _1. + + First we expand ln to the proper length. lnExpand() also + duplicates '/' to the previous pattern. + + Then we step though ln: + + - convert 'z', 'Z' and '-' to empty patterns. + + - duplicate the existing pattern for '*' + + - copy the defined pattern for everything else. + There's a bit of Python reference trickery here. + Eg, if we have the line: + + Bass Sequence B1 B2 + + the sequence is set with pointers to the existing + patterns defined for B1 and B2. Now, if we later change + the definitions for B1 or B2, the stored pointer DOEN'T + change. So, changing pattern definitions has NO EFFECT. + + """ + + + ln=self.lnExpand(ln, 'Sequence') + tmp = [None] * len(ln) + + for i, n in enumerate(ln): + n=n.upper() + + if n in ('Z', '-'): + tmp[i] = None + + elif n == '*': + tmp[i] = self.sequence[i] + + else: + p= (self.vtype, n) + if not p in pats: + error("Track %s does not have pattern '%s'" % p ) + tmp[i] = pats[p] + + self.sequence = seqBump(tmp) + + if gbl.seqshow: + print "%s sequence set:" % self.name, + for a in ln: + if a in "Zz-": + print "-", + else: + print a, + print - if val < -50 or val > 50: - error("Mallet Decay rate must be -50..+50") - self.malletDecay = val/100 + def clearSequence(self): + """ Clear sequence for track. - if gbl.debug: - print "%s Mallet Rate:%s Decay:%s " % \ - (self.name, self.mallet, self.malletDecay) + This is also called from __init__() to set the initial defaults for each track. + """ - def setAccent(self, ln): - """ Set the accent values. This is a list of lists, a list for each seq. """ + if self.vtype != 'SOLO' or not self.inited: + self.artic = [90] + self.sequence = [None] + self.seqRnd = 0 + self.seqRndWeight = [1] + if self.vtype == 'ARIA': + self.scaleType = ['CHORD'] + else: + self.scaleType = ['AUTO'] + self.rVolume = [0] + self.rSkip = [0] + self.rTime = [0] + self.octave = [4 * 12] + self.voice = [0] + self.chordRange = [1] + self.harmony = [None] + self.harmonyOnly = [None] + self.harmonyVolume = [.8] + self.strum = [0] + self.volume = [MMA.volume.vols['M'] ] + self.compress = [0] + self.dupRoot = [0] + self.chordLimit = 0 + self.invert = [0] + self.lastChord = [] + self.accent = [ [] ] + self.unify = [0] + self.midiClear = [] + self.midiSeq = [] + self.midiVoice = [] + self.spanStart = 0 + self.spanEnd = 127 + self.mallet = 0 + self.malletDecay = 0 + self.futureVols = [] - tmp = [] + if self.riff: + if len(self.riff) > 1: + warning("%s sequence clear deleting %s riffs" % (self.name, len(self.riff))) + else: + warning("%s sequence clear deleting unused riff" % self.name ) - """ We can do "Track Accent 1 20 3 -10" or "Track Accent {1 20 3 -10}" - or even something like "Track Accent {1 20} / {/} {3 20}" - Note that the "/" can or not have {}s. - """ + self.riff = [] - ln = ' '.join(ln) - if not ln.startswith('{'): - ln='{' + ln +"}" - # Convert string to list. One entry per seq. + if self.vtype == 'CHORD': + self.voicing = Voicing() + self.direction = ['UP'] + else: + self.direction = ['BOTH'] - l=[] - while ln: - if not ln.startswith("{"): - if ln[0]=='/': - l.append('/') - ln=ln[1:].strip() - else: - error("Unknown value in %s Accent: %s" % (self.name, ln[0])) - else: - a,b = pextract(ln, "{", "}", 1) - ln=a.strip() - if len(b)==1 and b[0]=='/': - l.append('/') - else: - l.append(b[0].split()) + self.setSeqSize() - ln=self.lnExpand(l, 'Accent') + ############################ + ### Pattern functions + ############################ - for l in ln: - tt=[] - if len(l)/2*2 != len(l): - error("Use: %s Accent Beat Percentage [...]" % self.name) + def definePattern(self, name, ln): + """ Define a Pattern. - for b, v in zip(l[::2], l[1::2]): - b=self.setBarOffset( b ) - v=stoi(v, "Bbeat offset must be a value, not '%s'." % v) - if v < -100 or v > 100: - error("Velocity adjustment (as percentage) must " - "be -100..100, not '%s'." % v) + All patterns are stored in pats{}. The keys for this + are tuples -- (track type, pattern name). - tt.append( (b, v/100. ) ) - tmp.append(tt) + """ - self.accent = seqBump( tmp ) + name = name.upper() + slot = (self.vtype,name) - if gbl.debug: - print "%s Accent: " % self.name, - for s in self.accent: - print "{", - for b,v in s: - print '%s %s' % (1+(b/float(gbl.BperQ)), int(v*100)), - print "}", - print + # This is just for the debug code + if name.startswith('_'): + redef = "dynamic define" + elif slot in pats: + redef = name + ' redefined' + else: + redef = name + ' created' - def setArtic(self, ln): - """ Set the note articuation value. """ + ln = ln.rstrip('; ') # Delete optional trailing ';' & WS + pats[slot] = self.defPatRiff(ln) - ln=self.lnExpand(ln, 'Articulate') - tmp = [] + if gbl.pshow: + print "%s pattern %s:" % (self.name.title(), redef ) + self.printPattern(pats[slot]) - for n in ln: - a = stoi(n, "Expecting value in articulation setting.") - if a < 1 or a > 200: - error("Articulation setting must be 1..200, not %s." % a) - if a>150: - warning("Large Articulate value: %s" % a) + def setRiff(self, ln): + """ Define and set a Riff. """ - tmp.append(a) + solo = self.vtype in ("MELODY", "SOLO") - self.artic = seqBump(tmp) + if solo: + self.riff.append(ln) + else: + ln = ln.rstrip('; ') + if len(ln) == 1 and (ln[0] in ('Z','z','-')): + self.riff.append([]) + else: + self.riff.append(self.defPatRiff(ln)) - if gbl.debug: - print "Set %s Articulation to " % self.name, - printList(ln) + if gbl.pshow: + print "%s Riff:" % self.name, + if solo: + print self.riff[-1] + else: + self.printPattern(self.riff[-1]) - def setUnify(self, ln): - """ Set unify. """ + def defPatRiff(self, ln): + """ Worker function to define pattern. Shared by definePattern() + and setRiff(). + """ - ln = self.lnExpand(ln, "Unify") - tmp = [] + def mulPatRiff(oldpat, fact): + """ Multiply a pattern. """ - for n in ln: - n=n.upper() - if n in ( 'ON', '1'): - tmp.append(1) - elif n in( 'OFF', '0'): - tmp.append(0) - else: - error("Unify accepts ON | OFF | 0 | 1") + fact = stoi(fact, "The multiplier arg must be an integer not '%s'" % fact) - self.unify = seqBump(tmp) + if fact<1 or fact >100: + error("The multiplier arg must be in the range 2 to 100") - if gbl.debug: - print "Set %s Unify to " % self.name, - printList(self.unify) + """ Make N copies of pattern, adjusted so that the new copy has + all note lengths and start times adjusted. + eg: [[1, 2, 66], [3, 2, 88]] * 2 + becomes [[1,4,66], [2,4,88], [3,4,66], [4,4,88]]. + """ + new = [] + add = 0 + step = (gbl.BperQ * gbl.QperBar)/fact - def lnExpand(self, ln, cmd): - """ Validate and expand a list passed to a set command. """ - - if len(ln) > gbl.seqSize: - warning("%s list truncated to %s patterns." % (self.name, gbl.seqSize) ) - ln = ln[:gbl.seqSize] + for n in range(fact): + orig = copy.deepcopy(oldpat) + for z in orig: + z.offset = (z.offset / fact) + add + z.duration /= fact + if z.duration < 1: + z.duration = 1 - last = None - - for i,n in enumerate(ln): - if n == '/': - if not last: - error ("You cannot use a '/' as the first item " - "in a %s list." % cmd) - else: - ln[i] = last - else: - last = n + new.append(z) + add += step - return ln + return tuple( new ) - def copySettings(self, cp): - """ Copy the voicing from a 2nd voice to the current one. """ + def shiftPatRiff(oldpat, fact): - if not cp in gbl.tnames: - error("CopySettings does not know track '%s'." % cp) + fact = stof(fact, "The shift arg must be a value, not '%s'" % fact) - cp=gbl.tnames[cp] + # Adjust all the beat offsets - if cp.vtype != self.vtype: - error("Tracks must be of same type for copy ... " - "%s and %s aren't." % (self.name, cp.name)) + new = copy.deepcopy(oldpat) + max = gbl.BperQ * (gbl.QperBar) + for n in new: + n.offset += fact * gbl.BperQ + if n.offset < 0 or n.offset > max: + error("Pattern shift with factor %f has resulted in an " + "illegal offset" % fact ) - self.volume = cp.volume[:] - self.rVolume = cp.rVolume[:] - self.accent = cp.accent[:] - self.rSkip = cp.rSkip[:] - self.rTime = cp.rTime[:] - self.strum = cp.strum[:] - self.octave = cp.octave[:] - self.harmony = cp.harmony[:] - self.harmonyOnly = cp.harmonyOnly[:] - self.harmonyVolume = cp.harmonyVolume[:] - self.direction = cp.direction[:] - self.scaleType = cp.scaleType[:] - self.voice = cp.voice[:] - self.invert = cp.invert[:] - self.artic = cp.artic[:] - self.compress = cp.compress[:] - - self.riff = cp.riff[:] - - if self.vtype == 'DRUM': - self.toneList = cp.toneList[:] - - - if gbl.debug: - print "Settings from %s copied to %s." % (cp.name, self.name) - - - - ################################################## - ## Save/restore grooves - - def saveGroove(self, gname): - """ Define a groove. - - Called by the 'DefGroove Name'. This is called for - each track. - - If 'gname' is already defined it is overwritten. - - Note aux. function which may be defined for each track type. - """ - - self.grooves[gname] = { - 'ACCENT': self.accent[:], - 'ARTIC': self.artic[:], - 'COMPRESS': self.compress[:], - 'DIR': self.direction[:], - 'DUPROOT': self.dupRoot[:], - 'HARMONY': self.harmony[:], - 'HARMONYO': self.harmonyOnly[:], - 'HARMONYV': self.harmonyVolume[:], - 'INVERT': self.invert[:], - 'LIMIT': self.chordLimit, - 'RANGE': self.chordRange[:], - 'OCTAVE': self.octave[:], - 'RSKIP': self.rSkip[:], - 'RTIME': self.rTime[:], - 'RVOLUME': self.rVolume[:], - 'SCALE': self.scaleType[:], - 'SEQ': self.sequence[:], - 'SEQRND': self.seqRnd, - 'SEQRNDWT': self.seqRndWeight[:], - 'STRUM': self.strum[:], - 'VOICE': self.voice[:], - 'VOLUME': self.volume[:], - 'UNIFY': self.unify[:], - 'MIDISEQ': self.midiSeq[:], - 'MIDIVOICE':self.midiVoice[:], - 'MIDICLEAR':self.midiClear[:], - 'SPAN': (self.spanStart, self.spanEnd), - 'MALLET': (self.mallet, self.malletDecay) } - - - if self.vtype == 'CHORD': - self.grooves[gname]['VMODE'] = copy.deepcopy(self.voicing) - - if self.vtype == 'DRUM': - self.grooves[gname]['TONES'] = self.toneList[:] - - - def restoreGroove(self, gname): - """ Restore a defined groove. """ - - self.doMidiClear() - - g = self.grooves[gname] - - self.sequence = g['SEQ'] - self.volume = g['VOLUME'] - self.accent = g['ACCENT'] - self.rTime = g['RTIME'] - self.rVolume = g['RVOLUME'] - self.rSkip = g['RSKIP'] - self.strum = g['STRUM'] - self.octave = g['OCTAVE'] - self.voice = g['VOICE'] - self.harmonyOnly= g['HARMONYO'] - self.harmony = g['HARMONY'] - self.harmonyVolume = g['HARMONYV'] - self.direction = g['DIR'] - self.scaleType = g['SCALE'] - self.invert = g['INVERT'] - self.artic = g['ARTIC'] - self.seqRnd = g['SEQRND' ] - self.seqRndWeight = g['SEQRNDWT'] - self.compress = g['COMPRESS'] - self.chordRange = g['RANGE'] - self.dupRoot = g['DUPROOT'] - self.chordLimit = g['LIMIT'] - self.unify = g['UNIFY'] - self.midiClear = g['MIDICLEAR'] - self.midiSeq = g['MIDISEQ'] - self.midiVoice = g['MIDIVOICE'] - self.spanStart, self.spanEnd = g['SPAN'] - self.mallet, self.malletDecay = g['MALLET'] - - if self.vtype == 'CHORD': - self.voicing = g['VMODE'] - - if self.vtype == 'DRUM': - self.toneList = g['TONES'] - - - """ It's quite possible that the track was created after - the groove was saved. This means that the data restored - was just the default stuff inserted when the track - was created ... which is fine, but the sequence size - isn't necs. right. We can probably test any list, and octave[] - is as good as any. - """ - - if len(self.octave) != gbl.seqSize: - self.setSeqSize() - - #################################### - ## Sequence functions - - def setSequence(self, ln): - """ Set the sequence for a track. - - The ln passed from the parser should be a list of existing - patterns, plus the special 'patterns' Z, z, -, and *. Remember - that the parser has already converted {} patterns to a special - pattern line _1. - - First we expand ln to the proper length. lnExpand() also - duplicates '/' to the previous pattern. - - Then we step though ln: - - - convert 'z', 'Z' and '-' to empty patterns. - - - duplicate the existing pattern for '*' - - - copy the defined pattern for everything else. - There's a bit of Python reference trickery here. - Eg, if we have the line: - - Bass Sequence B1 B2 - - the sequence is set with pointers to the existing - patterns defined for B1 and B2. Now, if we later change - the definitions for B1 or B2, the stored pointer DOEN'T - change. So, changing pattern definitions has NO EFFECT. - - """ - - ln=self.lnExpand(ln, 'Sequence') - tmp = [None] * len(ln) - - for i, n in enumerate(ln): - n=n.upper() - - if n in ('Z', '-'): - tmp[i] = None - - elif n == '*': - tmp[i] = self.sequence[i] - - else: - p= (self.vtype, n) - if not p in pats: - error("Track %s does not have pattern '%s'." % p ) - tmp[i] = pats[p] - - self.sequence = seqBump(tmp) - - if gbl.seqshow: - print "%s sequence set:" % self.name, - for a in ln: - if a in "Zz-": print "-", - else: print a, - print - - - def clearSequence(self): - """ Clear sequence for track. - - This is also called from __init__() to set the initial defaults for each track. - - """ - - if self.vtype != 'SOLO' or not self.inited: - self.artic = [90] - self.sequence = [None] - self.seqRnd = 0 - self.seqRndWeight = [1] - self.scaleType = ['AUTO'] - self.rVolume = [0] - self.rSkip = [0] - self.rTime = [0] - self.octave = [4 * 12] - self.voice = [0] - self.chordRange = [1] - self.harmony = [None] - self.harmonyOnly = [None] - self.harmonyVolume = [.8] - self.strum = [0] - self.volume = [MMA.volume.vols['M'] ] - self.compress = [0] - self.dupRoot = [0] - self.chordLimit = 0 - self.invert = [0] - self.lastChord = [] - self.accent = [ [] ] - self.unify = [0] - self.midiClear = [] - self.midiSeq = [] - self.midiVoice = [] - self.spanStart = 0 - self.spanEnd = 127 - self.mallet = 0 - self.malletDecay = 0 - self.futureVols = [] + return tuple( new ) + def patsort(c1, c2): + """ Sort a pattern tuple. """ - if self.riff: - if len(self.riff) > 1: - warning("%s sequence clear deleting %s riffs." % (self.name, len(self.riff))) - else: - warning("%s sequence clear deleting unused riff" % self.name ) + if c1.offset < c2.offset: return -1 + if c1.offset == c2.offset: return 0 + else: return 1 - self.riff = [] - if self.vtype == 'CHORD': - self.voicing = Voicing() - self.direction = ['UP'] - else: - self.direction = ['BOTH'] + ### Start of main function... - self.setSeqSize() + # Convert the string to list... + # "1 2 3; 4 5 6" ---> [ [1,2,3], [4,5,6] ] + p = [] + ln = ln.upper().split(';') + for l in ln: + p.append(l.split()) - ############################ - ### Pattern functions - ############################ + plist=[] - def definePattern(self, name, ln): - """ Define a Pattern. + for ev in p: + more=[] + for i,e in enumerate(ev): + if e.upper() in ('SHIFT', '*'): + if i == 0: + error("Pattern definition can't start with SHIFT or *") + more = ev[i:] + ev=ev[:i] + break - All patterns are stored in pats{}. The keys for this - are tuples -- (track type, pattern name). + if len(ev) == 1: + nm = (self.vtype, ev[0]) - """ + if nm in pats: + if nm[0].startswith('_'): + error("You can't use a pattern name beginning with an underscore") + pt = pats[nm] - name = name.upper() - slot = (self.vtype,name) + else: + error("%s is not an existing %s pattern" % (nm[1], nm[0].title()) ) - # This is just for the debug code + else: + pt = [self.getPgroup(ev)] - if name.startswith('_'): - redef = "dynamic define" - elif slot in pats: - redef = name + ' redefined' - else: - redef = name + ' created' + while more: + cmd = more.pop(0) + if cmd not in ('SHIFT', '*'): + error("Expecting SHIFT or *, not '%s'" % cmd) - ln = ln.rstrip('; ') # Delete optional trailing ';' & WS - pats[slot] = self.defPatRiff(ln) + if not more: + error("Expecting factor after %s" % cmd) + if cmd == 'SHIFT': + pt = shiftPatRiff(pt, more.pop(0)) + elif cmd == '*': + pt = mulPatRiff(pt, more.pop(0)) - if gbl.pshow: - print "%s pattern %s:" % (self.name.title(), redef ) - self.printPattern(pats[slot]) + plist.extend(pt) - def setRiff(self, ln): - """ Define and set a Riff. """ + plist.sort(patsort) - solo = self.vtype in ("MELODY", "SOLO") + if gbl.swingMode: + len8 = getNoteLen('8') + len81 = getNoteLen('81') + len82 = getNoteLen('82') - if solo: - self.riff.append(ln) - else: - ln = ln.rstrip('; ') - if len(ln) == 1 and (ln[0] in ('Z','z','-')): - self.riff.append([]) - else: - self.riff.append(self.defPatRiff(ln)) + onBeats = [ x * gbl.BperQ for x in range(gbl.QperBar)] + offBeats = [ (x * gbl.BperQ + len8) for x in range(gbl.QperBar)] - if gbl.pshow: - print "%s Riff:" % self.name, - if solo: - print self.riff[-1] - else: - self.printPattern(self.riff[-1]) + for p in plist: + if p.duration == len8 or self.vtype=="DRUM" and p.duration==1: + if p.offset in onBeats: + if p.duration == len8: + p.duration = len81 + elif p.offset in offBeats: + if p.duration == len8: + p.duration = len82 + i=offBeats.index(p.offset) + p.offset = onBeats[i] + len81 + return plist - def defPatRiff(self, ln): - """ Worker function to define pattern. Shared by definePattern() - and setRiff(). - """ - def mulPatRiff(oldpat, fact): - """ Multiply a pattern. """ + def printPattern(self, pat): + """ Print a pattern. Used by debugging code.""" - fact = stoi(fact, "The multiplier arg must be an integer not '%s'." % fact) + s=[] + for p in pat: + s.append(" %2.2f %2.0f" % (1+(p.offset/float(gbl.BperQ)), + p.duration)) - if fact<1 or fact >100: - error("The multiplier arg must be in the range 2 to 100.") + if self.vtype == 'CHORD': + for a in p.vol: + s.append( " %2.0f" % a) + elif self.vtype == 'BASS': + f=str(p.noteoffset+1) - """ Make N copies of pattern, adjusted so that the new copy has - all note lengths and start times adjusted. - eg: [[1, 2, 66], [3, 2, 88]] * 2 - becomes [[1,4,66], [2,4,88], [3,4,66], [4,4,88]]. - """ + if p.accidental == 1: + f+="#" + elif p.accidental == -1: + f+="b" - new = [] - add = 0 - step = (gbl.BperQ * gbl.QperBar)/fact + if p.addoctave > 0: + f+="+" * (p.addoctave/12) + elif p.addoctave < 0: + f+="-" * (p.addoctave/-12) - for n in range(fact): - orig = copy.deepcopy(oldpat) - for z in orig: - z.offset = (z.offset / fact) + add - z.duration /= fact - if z.duration < 1: - z.duration = 1 + s.append( " %s %2.0f" % (f, p.vol ) ) - new.append(z) - add += step + elif self.vtype == 'ARPEGGIO': + s.append( " %2.0f " % p.vol ) - return tuple( new ) + elif self.vtype == 'DRUM': + s.append(" %2.0f" % p.vol) + elif self.vtype == 'WALK': + s.append(" %2.0f" % p.vol ) - def shiftPatRiff(oldpat, fact): + s.append(' ;') + s.append('\n') + s[-2]=' ' + print "".join(s) - fact = stof(fact, "The shift arg must be a value, not '%s'." % fact) - # Adjust all the beat offsets + def insertVoice(self): + """ Called from bar() and setForceOut(). Adds voice stuff to track.""" - new = copy.deepcopy(oldpat) - max = gbl.BperQ * (gbl.QperBar) - for n in new: - n.offset += fact * gbl.BperQ - if n.offset < 0 or n.offset > max: - error("Pattern shift with factor %f has resulted in an " - "illegal offset." % fact ) + sc = gbl.seqCount - return tuple( new ) + """ 1st pass for MIDIVOICE. There's a separate slot for + each bar in the sequence, plus the data can be sent + before or after 'voice' commands. This first loop + sends MIDIVOICE data with an offset of 0. Note, we + don't set the value for 'self.smidiVoice' until we + do this again, later. All this is needed since some + MIDIVOICE commands NEED to be sent BEFORE voice selection, + and others AFTER. + """ - def patsort(c1, c2): - """ Sort a pattern tuple. """ + if self.midiVoice: + v = self.midiVoice[sc] + if v and v != self.smidiVoice: + for i in v: + if not i[0]: + gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) - if c1.offset < c2.offset: return -1 - if c1.offset == c2.offset: return 0 - else: return 1 + # Set the voice in the midi track if not previously done. + v=self.voice[sc] + if v != self.ssvoice: + gbl.mtrks[self.channel].addProgChange( gbl.tickOffset, v) + self.ssvoice = v - ### Start of main function... + # Mark ssvoice also in shared tracks - # Convert the string to list... - # "1 2 3; 4 5 6" ---> [ [1,2,3], [4,5,6] ] + for a in gbl.midiAssigns[self.channel]: + if gbl.tnames.has_key(a): + gbl.tnames[a].ssvoice = v - p = [] - ln = ln.upper().split(';') - for l in ln: - p.append(l.split()) + if gbl.debug: + print "Track %s Voice %s inserted" \ + % (self.name, MMA.midiC.valueToInst(v) ) - plist=[] + """ Our 2nd stab at MIDIVOICE. This time any sequences + with offsets >0 are sent. AND the smidiVoice and midiSent + variables are set. + """ + if self.midiVoice: + v = self.midiVoice[sc] + if v and v != self.smidiVoice: + for i in v: + if i[0]: + gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) + self.smidiVoice = v + self.midiSent = 1 # used by MIDICLEAR - for ev in p: - more=[] - for i,e in enumerate(ev): - if e.upper() in ('SHIFT', '*'): - if i == 0: - error("Pattern definition can't start with" - "SHIFT or *") - more = ev[i:] - ev=ev[:i] - break - if len(ev) == 1: - nm = (self.vtype, ev[0]) + ######################### + ## Music processing + ######################### - if nm in pats: - if nm[0].startswith('_'): - error("You can't use a pattern name beginning" - " with an underscore.") - pt = pats[nm] - else: - error("%s is not an existing %s pattern." % (nm[1], nm[0].title()) ) + def bar(self, ctable): + """ Process a bar of music for this track. """ - else: - pt = [self.getPgroup(ev)] - while more: - cmd = more.pop(0) - if cmd not in ('SHIFT', '*'): - error("Expecting SHIFT or *, not '%s'." % cmd) + # Future vol == de(cresc). Done if track is on or off! - if not more: - error("Expecting factor after %s" % cmd) - if cmd == 'SHIFT': - pt = shiftPatRiff(pt, more.pop(0)) - elif cmd == '*': - pt = mulPatRiff(pt, more.pop(0)) + if self.futureVols: + self.volume = seqBump([self.futureVols.pop(0)]) - plist.extend(pt) + # If track is off don't do anything else. + if self.disable: + if self.riff: + self.riff.pop(0) + return - plist.sort(patsort) - if gbl.swingMode: - len8 = getNoteLen('8') - len81 = getNoteLen('81') - len82 = getNoteLen('82') + """ Decide which seq to use. This is either the current + seqCount, or if SeqRnd has been set for the track + it is a random pattern in the sequence. - onBeats = [ x * gbl.BperQ for x in range(gbl.QperBar)] - offBeats = [ (x * gbl.BperQ + len8) for x in range(gbl.QperBar)] + The class variable self.seq is set to the sequence to use. + """ - for p in plist: - if p.duration == len8 or self.vtype=="DRUM" and p.duration==1: - if p.offset in onBeats: - if p.duration == len8: - p.duration = len81 - elif p.offset in offBeats: - if p.duration == len8: - p.duration = len82 - i=offBeats.index(p.offset) - p.offset = onBeats[i] + len81 + if self.seqRnd: + tmp = [] + for x, i in enumerate(self.seqRndWeight): + tmp.extend([x] * i) + if not len(tmp): + error("SeqRndWeight has generated an empty list") + self.seq = random.choice(tmp) + else: + self.seq = gbl.seqCount - return plist + sc = self.seq + """ Get pattern for this sequence. Either a Riff or a Pattern. """ - def printPattern(self, pat): - """ Print a pattern. Used by debugging code.""" + if self.riff: + pattern = self.riff.pop(0) - s=[] - for p in pat: - s.append(" %2.2f %2.0f" % (1+(p.offset/float(gbl.BperQ)), - p.duration)) + else: + pattern = self.sequence[sc] - if self.vtype == 'CHORD': - for a in p.vol: - s.append( " %2.0f" % a) + if not pattern: + return - elif self.vtype == 'BASS': - f=str(p.noteoffset+1) + """ MIDI Channel assignment. If no channel is assigned try + to find an unused number and assign that. + """ - if p.accidental == 1: - f+="#" - elif p.accidental == -1: - f+="b" + if not self.channel: + self.setChannel() - if p.addoctave > 0: - f+="+" * (p.addoctave/12) - elif p.addoctave < 0: - f+="-" * (p.addoctave/-12) + # We are ready to create musical data. 1st do pending midi commands. - s.append( " %s %2.0f" % (f, p.vol ) ) + self.clearPending() - elif self.vtype == 'ARPEGGIO': - s.append( " %2.0f " % p.vol ) + self.insertVoice() - elif self.vtype == 'DRUM': - s.append(" %2.0f" % p.vol) + # Do MIDISeq for this voice - elif self.vtype == 'WALK': - s.append(" %2.0f" % p.vol ) + if self.midiSeq: + l = self.midiSeq[sc] + if l: + for i in l: + gbl.mtrks[self.channel].addCtl( getOffset(i[0]), i[1] ) + self.midiSent = 1 - s.append(' ;') - s.append('\n') - s[-2]=' ' - print "".join(s) + self.trackBar(pattern, ctable) - def insertVoice(self): - """ Called from bar() and setForceOut(). Adds voice stuff to track.""" - sc = gbl.seqCount + def clearPending(self): - """ 1st pass for MIDIVOICE. There's a separate slot for - each bar in the sequence, plus the data can be sent - before or after 'voice' commands. This first loop - sends MIDIVOICE data with an offset of 0. Note, we - don't set the value for 'self.smidiVoice' until we - do this again, later. All this is needed since some - MIDIVOICE commands NEED to be sent BEFORE voice selection, - and others AFTER. - """ + while self.midiPending: + c, off, v = self.midiPending.pop(0) + if c == 'TNAME': + gbl.mtrks[self.channel].addTrkName(off, v) + if gbl.debug: + print "%s Track name inserted at offset %s" % \ + (self.name, off) - if self.midiVoice: - v = self.midiVoice[sc] - if v and v != self.smidiVoice: - for i in v: - if not i[0]: - gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) + elif c == 'GLIS': + gbl.mtrks[self.channel].addGlis(off, v) + if gbl.debug: + print "%s Glis at offset %s set to %s" % \ + (self.name, off, ord(chr(v))) - # Set the voice in the midi track if not previously done. + elif c == 'PAN': + gbl.mtrks[self.channel].addPan(off, v) + if gbl.debug: + print "%s Pan at offset %s set to %s" % \ + (self.name, off, v) - v=self.voice[sc] - if v != self.ssvoice: - gbl.mtrks[self.channel].addProgChange( gbl.tickOffset, v) - self.ssvoice = v + elif c == 'CVOLUME': + gbl.mtrks[self.channel].addChannelVol(off, v) + if gbl.debug: + print "%s ChannelVolume at offset %s set to %s" % \ + (self.name, off, v) - # Mark ssvoice also in shared tracks + else: + error("Unknown midi command pending. Call Bob") - for a in gbl.midiAssigns[self.channel]: - if gbl.tnames.has_key(a): - gbl.tnames[a].ssvoice = v - if gbl.debug: - print "Track %s Voice %s inserted." \ - % (self.name, MMA.midiC.valueToInst(v) ) - """ Our 2nd stab at MIDIVOICE. This time any sequences - with offsets >0 are sent. AND the smidiVoice and midiSent - variables are set. - """ + def getChordInPos( self, offset, ctable): + """ Compare an offset to a list of ctables and return + the table entry active for the given beat. - if self.midiVoice: - v = self.midiVoice[sc] - if v and v != self.smidiVoice: - for i in v: - if i[0]: - gbl.mtrks[self.channel].addCtl(gbl.tickOffset, i[1]) - self.smidiVoice = v - self.midiSent = 1 # used by MIDICLEAR + We assume that the first offset in 'ctable' is 0! + We assme that 'offset' is >= 0! + Returns a ctable. + """ - ######################### - ## Music processing - ######################### + for i in range(len(ctable)-1, -1, -1): # reverse order + if offset >= ctable[i].offset: + break + return ctable[i] - def bar(self, ctable): - """ Process a bar of music for this track. """ + def adjustVolume(self, v, beat): + """ Adjust a note volume based on the track and global volume + setting. + """ - # Future vol == de(cresc). Done if track is on or off! + if not v: + return 0 - if self.futureVols: - self.volume = seqBump([self.futureVols.pop(0)]) + sc = self.seq - # If track is off don't do anything else. + if self.rSkip[sc] and random.random() < self.rSkip[sc]: + return 0 - if self.disable: - if self.riff: - self.riff.pop(0) - return + a1 = self.volume[sc] + if not a1: + return 0 + a1 *= MMA.volume.vTRatio + a2 = MMA.volume.volume + if not a2: + return 0 + a2 *= MMA.volume.vMRatio - """ Decide which seq to use. This is either the current - seqCount, or if SeqRnd has been set for the track - it is a random pattern in the sequence. + v *= ( a1 + a2 ) - The class variable self.seq is set to the sequence to use. - """ + for b,a in self.accent[sc]: + if b==beat: + v += (v * a) - if self.seqRnd: - tmp = [] - for x, i in enumerate(self.seqRndWeight): - tmp.extend([x] * i) - if not len(tmp): - error("SeqRndWeight has generated an empty list.") - self.seq = random.choice(tmp) - else: - self.seq = gbl.seqCount + # take .rVolume % of current volume, add/sub result to current - sc = self.seq - #print self.name, sc - """ Get pattern for this sequence. Either a Riff or a Pattern. """ + if self.rVolume[sc]: + a = int(v * self.rVolume[sc]) + if a: + v += random.randrange(-a, a) - if self.riff: - pattern = self.riff.pop(0) + if v > 127: + v = 127 + elif v < 1: + v = 1 - else: - pattern = self.sequence[sc] + return int(v) - if not pattern: - return - """ MIDI Channel assignment. If no channel is assigned try - to find an unused number and assign that. - """ + def adjustNote(self, n): + """ Adjust a note for a given octave/transposition. + Ensure that the note is in range. + """ - if not self.channel: - self.setChannel() + n += self.octave[self.seq] + gbl.transpose - # We are ready to create musical data. 1st do pending midi commands. + while n < 0: + n += 12 + while n > 127: + n -= 12 - self.clearPending() + while n < self.spanStart: + n += 12 + while n > self.spanEnd: + n -= 12 - self.insertVoice() + return n - # Do MIDISeq for this voice - if self.midiSeq: - l = self.midiSeq[sc] - if l: - for i in l: - gbl.mtrks[self.channel].addCtl( getOffset(i[0]), i[1] ) - self.midiSent = 1 + def setBarOffset(self, v): + """ Convert a string into a valid bar offset in midi ticks. """ - self.trackBar(pattern, ctable) + m=v.find('-') + p=v.find('+') + if m>-1 and p>-1: + if m>p: + sp = p + sign = 1 + else: + sp = m + sign = -1 + elif m >- 1: + sp = m + sign = -1 - def clearPending(self): + elif p >- 1: + sp = p + sign = 1 - while self.midiPending: - c, off, v = self.midiPending.pop(0) - if c == 'TNAME': - gbl.mtrks[self.channel].addTrkName(off, v) - if gbl.debug: - print "%s Track name inserted at offset %s." % \ - (self.name, off) + else: + sp = None - elif c == 'GLIS': - gbl.mtrks[self.channel].addGlis(off, v) - if gbl.debug: - print "%s Glis at offset %s set to %s." % \ - (self.name, off, ord(chr(v))) + if sp: + note = v[sp+1:] + v = v[:sp] + else: + note = None - elif c == 'PAN': - gbl.mtrks[self.channel].addPan(off, v) - if gbl.debug: - print "%s Pan at offset %s set to %s." % \ - (self.name, off, v) - elif c == 'CVOLUME': - gbl.mtrks[self.channel].addChannelVol(off, v) - if gbl.debug: - print "%s ChannelVolume at offset %s set to %s" % \ - (self.name, off, v) + v=stof(v, "Value for %s bar offset must be integer/float" % self.name) + v = (v-1) * gbl.BperQ - else: - error("Unknown midi command pending. Call Bob.") + if note: + v += getNoteLen(note) * sign + if v < 0: + if v<-gbl.BperQ: + error("Defining %s Pattern, bar offset must be 0 or greater" % + self.name) + else: + warning("Offset in '%s' is '%s ticks' before bar start!" % (self.name, -v)) + if v >= gbl.QperBar * gbl.BperQ: + error("Defining %s Pattern, bar offset must be less than %s" % + (self.name, gbl.QperBar + 1)) - def getChordInPos( self, offset, ctable): - """ Compare an offset to a list of ctables and return - the table entry active for the given beat. - We assume that the first offset in 'ctable' is 0! - We assme that 'offset' is >= 0! + return int(v) - Returns a ctable. - """ - for i in range(len(ctable)-1, -1, -1): # reverse order - if offset >= ctable[i].offset: - break - return ctable[i] + def getDur(self, d): + """ Return the adjusted duration for a note. + The adjustment makes notes more staccato. Valid + adjustments are 1 to 100. 100 is not recommended. + """ + d = (d * self.artic[self.seq]) / 100 + if not d: + d = 1 - def adjustVolume(self, v, beat): - """ Adjust a note volume based on the track and global volume - setting. - """ + return d - if not v: - return 0 - sc = self.seq + def sendNote( self, offset, duration, note, velocity): + """ Send a note to the MIDI machine. This is called from all + track classes and handles niceties like mallet-repeat. + """ - if self.rSkip[sc] and random.random() < self.rSkip[sc]: - return 0 + if not velocity: + return - a1 = self.volume[sc] - if not a1: - return 0 - a1 *= MMA.volume.vTRatio + sc = self.seq - a2 = MMA.volume.volume - if not a2: - return 0 - a2 *= MMA.volume.vMRatio + rptr = self.mallet - v *= ( a1 + a2 ) + if rptr and duration > rptr: + ll = self.getDur(rptr) + offs = 0 + vel = velocity + count =0 - for b,a in self.accent[sc]: - if b==beat: - v += (v * a) + for q in range(duration/rptr): + gbl.mtrks[self.channel].addPairToTrack( + offset + offs, + self.rTime[sc], + ll, + note, + vel, + None ) - # take .rVolume % of current volume, add/sub result to current + offs += rptr + if self.malletDecay: + vel = int( vel + (vel * self.malletDecay) ) + if vel < 1: + vel = 1 + if vel > 255: + vel=255 + count+=1 - if self.rVolume[sc]: - a = int(v * self.rVolume[sc]) - if a: - v += random.randrange(-a, a) - - if v > 127: - v = 127 - elif v < 1: - v = 1 - - return int(v) - - - def adjustNote(self, n): - """ Adjust a note for a given octave/transposition. - Ensure that the note is in range. - """ - - n += self.octave[self.seq] + gbl.transpose - - while n < 0: - n += 12 - while n > 127: - n -= 12 - - while n < self.spanStart: - n += 12 - while n > self.spanEnd: - n -= 12 - - return n - - - def setBarOffset(self, v): - """ Convert a string into a valid bar offset in midi ticks. """ - - m=v.find('-') - p=v.find('+') - - if m>-1 and p>-1: - if m>p: - sp = p - sign = 1 - else: - sp = m - sign = -1 - - elif m >- 1: - sp = m - sign = -1 - - elif p >- 1: - sp = p - sign = 1 - - else: - sp = None - - if sp: - note = v[sp+1:] - v = v[:sp] - else: - note = None - - - v=stof(v, "Value for %s bar offset must be integer/float" % self.name) - v = (v-1) * gbl.BperQ - - if note: - v += getNoteLen(note) * sign - - if v < 0: - if v<-gbl.BperQ: - error("Defining %s Pattern, bar offset must be 0 or greater." % - self.name) - else: - warning("Offset in '%s' is '%s ticks' before bar start!" % (self.name, -v)) - - if v >= gbl.QperBar * gbl.BperQ: - error("Defining %s Pattern, bar offset must be less than %s." % - (self.name, gbl.QperBar + 1)) - - - return int(v) - - - def getDur(self, d): - """ Return the adjusted duration for a note. - - The adjustment makes notes more staccato. Valid - adjustments are 1 to 100. 100 is not recommended. - """ - - d = (d * self.artic[self.seq]) / 100 - if not d: - d = 1 - - return d - - - def sendNote( self, offset, duration, note, velocity): - """ Send a note to the MIDI machine. This is called from all - track classes and handles niceties like mallet-repeat. - """ - - if not velocity: - return - - sc = self.seq - - rptr = self.mallet - - if rptr and duration > rptr: - ll = self.getDur(rptr) - offs = 0 - vel = velocity - count =0 - - for q in range(duration/rptr): - gbl.mtrks[self.channel].addPairToTrack( - offset + offs, - self.rTime[sc], - ll, - note, - vel, - None ) - - offs += rptr - if self.malletDecay: - vel = int( vel + (vel * self.malletDecay) ) - if vel < 1: - vel = 1 - if vel > 255: - vel=255 - count+=1 - - else: - gbl.mtrks[self.channel].addPairToTrack( - offset, - self.rTime[sc], - duration, - note, - velocity, - self.unify[sc] ) + else: + gbl.mtrks[self.channel].addPairToTrack( + offset, + self.rTime[sc], + duration, + note, + velocity, + self.unify[sc] ) diff --git a/mma/MMA/patAria.py b/mma/MMA/patAria.py new file mode 100644 index 0000000..13aaedb --- /dev/null +++ b/mma/MMA/patAria.py @@ -0,0 +1,228 @@ + +# patAria.py + +""" +This module is an integeral part of the program +MMA - Musical Midi Accompaniment. + +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, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Bob van der Poel + +""" + + + +import gbl +from MMA.notelen import getNoteLen +from MMA.common import * +from MMA.harmony import harmonize +from MMA.pat import PC, seqBump + +import random + +class Aria(PC): + """ Pattern class for an aria (auto-melody) track. """ + + vtype = 'ARIA' + notes = [] + selectDir = [1] + noteptr = 0 + dirptr = 0 + lastChord = None + lastStype = None + lastRange = None + + + + def restoreGroove(self, gname): + """ Grooves are not saved/restored for aria tracks. But, seqsize is honored! """ + self.setSeqSize() + + def saveGroove(self, gname): + """ No save done for grooves. """ + pass + + + def getPgroup(self, ev): + """ Get group for aria pattern. + + Fields - start, length, velocity + + """ + + if len(ev) != 3: + error("There must be n groups of 3 in a pattern definition, " + "not <%s>" % ' '.join(ev) ) + + a = struct() + + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen( ev[1] ) + a.vol = stoi(ev[2], "Note volume in Aria definition not int") + + return a + + + def setScaletype(self, ln): + """ Set scale type. """ + + ln = self.lnExpand(ln, "ScaleType") + tmp = [] + + for n in ln: + n = n.upper() + if not n in ( 'CHROMATIC', 'AUTO', 'CHORD'): + error("Unknown %s ScaleType. Only Chromatic, Scale and Chord are valid" % self.name) + tmp.append(n) + + self.scaleType = seqBump(tmp) + + if gbl.debug: + print "Set %s ScaleType: " % self.name, + printList(self.scaleType) + + + def setDirection(self, ln): + """ Set direction for melody creation. + + This function replaces the pattern function of the same name ... + the command name is shared, the function is different. Note we + need to use a different storage name as well since + self.direction is managed in the PC class. + """ + + if not len(ln): + error("There must be at least one value for %s Direction." % self.name) + + self.selectDir = [] + for a in ln: + if a.upper() == 'R': + self.selectDir.append(a.upper()) + else: + a=stoi(a, "Expecting integer value or 'r'.") + if a < -4 or a > 4: + error("Aria direction must be 'r' or -4 to 4, not '%s'" % a) + self.selectDir.append(a) + + if gbl.debug: + print "Set %s Direction:" % self.name, + printList(self.selectDir) + + def restart(self): + self.ssvoice = -1 + + + def trackBar(self, pattern, ctable): + """ Do the aria bar. + + Called from self.bar() + + """ + + sc = self.seq + unify = self.unify[sc] + + for p in pattern: + ct = self.getChordInPos(p.offset, ctable) + + if ct.ariaZ: + continue + + thisChord = ct.chord.tonic + ct.chord.chordType + stype = self.scaleType[sc] + range = self.chordRange[sc] + + ### Generate notelist if nesc. + + if self.lastChord != thisChord or self.lastStype != stype or \ + self.lastRange != range: + + self.lastChord = thisChord + self.lastStype = stype + self.lastRange = range + + if stype == 'CHORD': + notelist = ct.chord.noteList + elif stype == 'CHROMATIC': + notelist = [ ct.chord.rootNote + x for x in range(0,12)] + else: + notelist = list(ct.chord.scaleList) + + o=0 + self.notes=[] + + while range >= 1: + for a in notelist: + self.notes.append(a+o) + o+=12 + range-=1 + + if range>0 and range<1: # for fractional scale lengths + range = int(len(notelist) * range) + if range < 2: # important, must be at least 2 notes in a scale + range=2 + for a in notelist[:range]: + self.notes.append(a+o) + + # grab a note from the list + + if self.dirptr >= len(self.selectDir): + self.dirptr=0 + + a = self.selectDir[self.dirptr] + if a == 'R': + a = random.choice( (-1, 0, 1) ) + self.noteptr += a + + if self.noteptr >= len(self.notes): + if a > 0: + self.noteptr = 0 + else: + self.noteptr = len(self.notes)-1 + elif self.noteptr < 0: + if a < 0: + self.noteptr = len(self.notes)-1 + else: + self.noteptr = 0 + + note = self.notes[self.noteptr] + + self.dirptr += 1 + + # output + + if not self.harmonyOnly[sc]: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume(p.vol, p.offset)) + + + if self.harmony[sc]: + h = harmonize(self.harmony[sc], note, ct.chord.noteList) + for n in h: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(n), + self.adjustVolume(p.vol * self.harmonyVolume[sc], -1)) + + + + + + diff --git a/mma/MMA/patArpeggio.py b/mma/MMA/patArpeggio.py index 97c023f..4ca1a81 100644 --- a/mma/MMA/patArpeggio.py +++ b/mma/MMA/patArpeggio.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -34,128 +34,128 @@ from MMA.pat import PC class Arpeggio(PC): - """ Pattern class for an arpeggio track. """ + """ Pattern class for an arpeggio track. """ - vtype = 'ARPEGGIO' - arpOffset = -1 - arpDirection = 1 + vtype = 'ARPEGGIO' + arpOffset = -1 + arpDirection = 1 - def getPgroup(self, ev): - """ Get group for apreggio pattern. + def getPgroup(self, ev): + """ Get group for apreggio pattern. - Fields - start, length, volume - """ + Fields - start, length, volume + """ - a = struct() - if len(ev) != 3: - error("There must be exactly 3 items in each group " - "for apreggio define, not <%s>." % ' '.join(ev) ) + a = struct() + if len(ev) != 3: + error("There must be exactly 3 items in each group " + "for apreggio define, not '%s'" % ' '.join(ev) ) - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen(ev[1]) - a.vol = stoi(ev[2], "Type error in Arpeggio definition.") + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen(ev[1]) + a.vol = stoi(ev[2], "Type error in Arpeggio definition") - return a + return a - def restart(self): - self.ssvoice = -1 - self.arpOffset=-1 - self.arpDirection=1 + def restart(self): + self.ssvoice = -1 + self.arpOffset=-1 + self.arpDirection=1 - def trackBar(self, pattern, ctable): - """ Do a arpeggio bar. + def trackBar(self, pattern, ctable): + """ Do a arpeggio bar. - Called from self.bar() + Called from self.bar() - """ + """ - sc = self.seq - direct = self.direction[sc] + sc = self.seq + direct = self.direction[sc] - for p in pattern: - tb = self.getChordInPos(p.offset, ctable) + for p in pattern: + tb = self.getChordInPos(p.offset, ctable) - if tb.arpeggioZ: - continue + if tb.arpeggioZ: + continue - if direct == 'DOWN': - self.arpDirection = -1 + if direct == 'DOWN': + self.arpDirection = -1 - if self.chordLimit: - tb.chord.limit(self.chordLimit) + if self.chordLimit: + tb.chord.limit(self.chordLimit) - if self.compress[sc]: - tb.chord.compress() + if self.compress[sc]: + tb.chord.compress() - if self.invert[sc]: - tb.chord.invert(self.invert[sc]) + if self.invert[sc]: + tb.chord.invert(self.invert[sc]) - # This should be optimized, it recreates the chord for every pattern. - # Problem is that one would need to check all the LIMIT, COMPRESS, etc - # settings each for each bar as well, so it's probably just as easy to - # leave it as is. Besides, this works. + # This should be optimized, it recreates the chord for every pattern. + # Problem is that one would need to check all the LIMIT, COMPRESS, etc + # settings each for each bar as well, so it's probably just as easy to + # leave it as is. Besides, this works. - ln = self.chordRange[sc] - o = 0 - ourChord = [] - while ln >= 1: - for a in tb.chord.noteList: - ourChord.append(a+o) - ln -= 1 - o += 12 + ln = self.chordRange[sc] + o = 0 + ourChord = [] + while ln >= 1: + for a in tb.chord.noteList: + ourChord.append(a+o) + ln -= 1 + o += 12 - if ln > 0 and ln < 1: # for fractional lengths - ln = int(tb.chord.noteListLen * ln) - if ln < 2: # important, min of 2 notes in arp. - ln=2 - for a in tb.chord.noteList[:ln]: - ourChord.append(a+o) + if ln > 0 and ln < 1: # for fractional lengths + ln = int(tb.chord.noteListLen * ln) + if ln < 2: # important, min of 2 notes in arp. + ln=2 + for a in tb.chord.noteList[:ln]: + ourChord.append(a+o) - if direct == 'BOTH': - if self.arpOffset < 0: - self.arpOffset = 1 - self.arpDirection = 1 - elif self.arpOffset >= len(ourChord): - self.arpOffset = len(ourChord)-2 - self.arpDirection = -1 + if direct == 'BOTH': + if self.arpOffset < 0: + self.arpOffset = 1 + self.arpDirection = 1 + elif self.arpOffset >= len(ourChord): + self.arpOffset = len(ourChord)-2 + self.arpDirection = -1 - elif direct == 'UP': - if self.arpOffset >= len(ourChord) or self.arpOffset < 0: - self.arpOffset = 0 - self.arpDirection = 1 + elif direct == 'UP': + if self.arpOffset >= len(ourChord) or self.arpOffset < 0: + self.arpOffset = 0 + self.arpDirection = 1 - elif direct == 'DOWN': - if self.arpOffset < 0 or self.arpOffset >= len(ourChord): - self.arpOffset = len(ourChord)-1 - self.arpDirection = -1 + elif direct == 'DOWN': + if self.arpOffset < 0 or self.arpOffset >= len(ourChord): + self.arpOffset = len(ourChord)-1 + self.arpDirection = -1 - if direct == 'RANDOM': - note = random.choice(ourChord) - else: - note = ourChord[self.arpOffset] + if direct == 'RANDOM': + note = random.choice(ourChord) + else: + note = ourChord[self.arpOffset] - self.arpOffset += self.arpDirection + self.arpOffset += self.arpDirection - if not self.harmonyOnly[sc]: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(note), - self.adjustVolume(p.vol, p.offset) ) + if not self.harmonyOnly[sc]: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume(p.vol, p.offset) ) - if self.harmony[sc]: - h = harmonize(self.harmony[sc], note, ourChord) - for n in h: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(n), - self.adjustVolume(p.vol * self.harmonyVolume[sc], -1) ) + if self.harmony[sc]: + h = harmonize(self.harmony[sc], note, ourChord) + for n in h: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(n), + self.adjustVolume(p.vol * self.harmonyVolume[sc], -1) ) - tb.chord.reset() # important, other tracks chord object + tb.chord.reset() # important, other tracks chord object diff --git a/mma/MMA/patBass.py b/mma/MMA/patBass.py index bf95c02..df8f253 100644 --- a/mma/MMA/patBass.py +++ b/mma/MMA/patBass.py @@ -1,8 +1,8 @@ -# patBass.py +# patBass.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ - + import gbl @@ -33,102 +33,102 @@ from MMA.pat import PC class Bass(PC): - """ Pattern class for a bass track. """ + """ Pattern class for a bass track. """ - vtype = 'BASS' - - def getPgroup(self, ev): - """ Get group for bass pattern. - - Fields - start, length, note, volume - - """ - - if len(ev) != 4: - error("There must be n groups of 4 in a pattern definition, " - "not <%s>." % ' '.join(ev) ) + vtype = 'BASS' - a = struct() + def getPgroup(self, ev): + """ Get group for bass pattern. - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen( ev[1] ) + Fields - start, length, note, volume - offset = ev[2] - n=offset[0] - if n in "1234567": - a.noteoffset = int(n)-1 - else: - error("Note offset in Bass must be '1'...'7', not '%s'" % n ) - - n = offset[1:2] - if n == "#": - a.accidental = 1 - ptr = 2 - elif n == 'b' or n == 'b' or n == '&': - a.accidental = -1 - ptr = 2 - else: - a.accidental = 0 - ptr = 1 - - a.addoctave = 0 + """ - for n in ev[2][ptr:]: - if n == '+': - a.addoctave += 12 - elif n == '-': - a.addoctave -= 12 - - else: - error("Only '- + # b &' are permitted after a noteoffset, not '%s'" % n) - - a.vol = stoi(ev[3], "Note volume in Bass definition not int.") - - return a + if len(ev) != 4: + error("There must be n groups of 4 in a pattern definition, " + "not <%s>" % ' '.join(ev) ) - def restart(self): - self.ssvoice = -1 - + a = struct() - def trackBar(self, pattern, ctable): - """ Do the bass bar. - - Called from self.bar() - - """ - - sc = self.seq - unify = self.unify[sc] + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen( ev[1] ) + + offset = ev[2] + n=offset[0] + if n in "1234567": + a.noteoffset = int(n)-1 + else: + error("Note offset in Bass must be '1'...'7', not '%s'" % n ) + + n = offset[1:2] + if n == "#": + a.accidental = 1 + ptr = 2 + elif n == 'b' or n == 'b' or n == '&': + a.accidental = -1 + ptr = 2 + else: + a.accidental = 0 + ptr = 1 + + a.addoctave = 0 + + for n in ev[2][ptr:]: + if n == '+': + a.addoctave += 12 + elif n == '-': + a.addoctave -= 12 + + else: + error("Only '- + # b &' are permitted after a noteoffset, not '%s'" % n) + + a.vol = stoi(ev[3], "Note volume in Bass definition not int") + + return a + + def restart(self): + self.ssvoice = -1 + + + def trackBar(self, pattern, ctable): + """ Do the bass bar. + + Called from self.bar() + + """ + + sc = self.seq + unify = self.unify[sc] + + for p in pattern: + ct = self.getChordInPos(p.offset, ctable) + + if ct.bassZ: + continue + + + note = ct.chord.scaleList[p.noteoffset] + p.addoctave + p.accidental + + + if not self.harmonyOnly[sc]: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume(p.vol, p.offset)) + + + if self.harmony[sc]: + h = harmonize(self.harmony[sc], note, ct.chord.noteList) + for n in h: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(n), + self.adjustVolume(p.vol * self.harmonyVolume[sc], -1)) - for p in pattern: - ct = self.getChordInPos(p.offset, ctable) - if ct.bassZ: - continue - - note = ct.chord.scaleList[p.noteoffset] + p.addoctave + p.accidental - - if not self.harmonyOnly[sc]: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(note), - self.adjustVolume(p.vol, p.offset)) - - - if self.harmony[sc]: - h = harmonize(self.harmony[sc], note, ct.chord.noteList) - for n in h: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(n), - self.adjustVolume(p.vol * self.harmonyVolume[sc], -1)) - - - - diff --git a/mma/MMA/patChord.py b/mma/MMA/patChord.py index fab7c0f..4bec74f 100644 --- a/mma/MMA/patChord.py +++ b/mma/MMA/patChord.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -29,240 +29,376 @@ import random import gbl from MMA.notelen import getNoteLen from MMA.common import * -from MMA.pat import PC +from MMA.pat import PC, seqBump + class Chord(PC): - """ Pattern class for a chord track. """ + """ Pattern class for a chord track. """ - vtype = 'CHORD' + vtype = 'CHORD' - def getPgroup(self, ev): - """ Get group for chord pattern. + def setVoicing(self, ln): + """ set the Voicing Mode options. Only valid for CHORDS. """ - Tuples: [start, length, volume (,volume ...) ] - """ + for l in ln: + try: + mode, val = l.upper().split('=') + except: + error("Each Voicing option must contain a '=', not '%s'" % l) - if len(ev) < 3: - error("There must be at least 3 items in each group " - "of a chord pattern definition, not <%s>." % ' '.join(ev)) - a = struct() + if mode == 'MODE': + valid= ("-", "OPTIMAL", "NONE", "ROOT", "COMPRESSED", "INVERT") - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen(ev[1]) + if not val in valid: + error("Valid Voicing Modes are: %s" % " ".join(valid)) - vv = ev[2:] - if len(vv)>8: - error("Only 8 volumes are permitted in Chord definition, not %s." % len(vv)) + if val in ('-', 'NONE',"ROOT"): + val = None - a.vol = [0] * 8 - for i,v in enumerate(vv): - v=stoi(v, "Expecting integer in volume list for Chord definition.") - a.vol[i]=v - for i in range(i+1,8): # force remaining volumes - a.vol[i]=v + if val and (max(self.invert) + max(self.compress)): + warning("Setting both VoicingMode and Invert/Compress is not a good idea") - return a + """ When we set voicing mode we always reset this. This forces + the voicingmode code to restart its rotations. + """ - def restart(self): - self.ssvoice = -1 - self.lastChord = None + self.lastChord = [] + self.voicing.mode = val - def chordVoicing(self, chord, vMove): - """ Voicing algorithm by Alain Brenzikofer. """ + elif mode == 'RANGE': + val = stoi(val, "Argument for %s Voicing Range " + "must be a value" % self.name) - sc = self.seq - vmode=self.voicing.mode + if val < 1 or val > 30: + error("Voicing Range '%s' out-of-range; " + "must be 1 to 30" % val) - if vmode == "OPTIMAL": + self.voicing.range = val - # Initialize with a voicing around centerNote - chord.center1(self.lastChord) + elif mode == 'CENTER': + val = stoi(val, "Argument for %s Voicing Center " + "must be a value" % self.name) - # Adjust range and center + if val < 1 or val > 12: + error("Voicing Center %s out-of-range; " + "must be 1 to 12" % val) - if not (self.voicing.bcount or self.voicing.random): - chord.center2(self.voicing.center, self.voicing.range/2) + self.voicing.center = val + elif mode == 'RMOVE': + val = stoi(val, "Argument for %s Voicing Random " + "must be a value" % self.name) - # Move voicing + if val < 0 or val > 100: + error("Voicing Random value must be 0 to 100 " + "not %s" % val) - elif self.lastChord: - if (self.lastChord != chord.noteList ) and vMove: - chord.center2(self.voicing.center,self.voicing.range/2) - vMove = 0 + self.voicing.random = val + self.voicing.bcount = 0 - # Update voicingCenter + elif mode == 'MOVE': + val = stoi(val, "Argument for %s Voicing Move " + "must be a value" % self.name) - sum=0 - for n in chord.noteList: - sum += n - c=sum/chord.noteListLen + if val < 0 : + error("Voicing Move (bar count) must >= 0, not %s" % val) + if val > 20: + warning("Voicing Move (bar count) %s is quite large" % val) - """ If using random voicing move it it's possible to - get way off the selected octave. This check ensures - that the centerpoint stays in a tight range. - Note that if using voicingMove manually (not random) - it is quite possible to move the chord centers to very - low or high keyboard positions! - """ + self.voicing.bcount = val + self.voicing.random = 0 - if self.voicing.random: - if c < -4: c=0 - elif c >4: c=4 - self.voicing.center=c + elif mode == 'DIR': + val = stoi(val, "Argument for %s Voicing Dir (move direction) " + "must be a value" % self.name) + if not val in (1,0,-1): + error("Voicing Move Dir -1, 0 or 1, not %s" % val) - elif vmode == "COMPRESSED": - chord.compress() + self.voicing.dir = val - elif vmode == "INVERT": - if chord.rootNote < -2: - chord.invert(1) - elif chord.rootNote > 2: - chord.invert(-1) - chord.compress() + if gbl.debug: + v=self.voicing + print "Set %s Voicing MODE=%s" % (self.name, v.mode), + print "RANGE=%s CENTER=%s" % (v.range, v.center), + print "RMOVE=%s MOVE=%s DIR=%s" % (v.random, v.bcount, v.dir) - self.lastChord = chord.noteList[:] - return vMove + def setDupRoot(self, ln): + """ set/unset root duplication. Only for CHORDs """ - def trackBar(self, pattern, ctable): - """ Do a chord bar. Called from self.bar() """ + ln=self.lnExpand(ln, 'DupRoot') + tmp = [] - sc = self.seq - unify = self.unify[sc] + for n in ln: + n = stoi(n, "Argument for %s DupRoot must be a value" % self.name) - """ Set voicing move ONCE at the top of each bar. - The voicing code resets vmove to 0 the first - time it's used. That way only one movement is - done in a bar. - """ + if n < -9 or n > 9: + error("DupRoot %s out-of-range; must be -9 to 9" % n) - vmove = 0 + tmp.append( n * 12 ) - if self.voicing.random: - if random.randrange(100) <= self.voicing.random: - vmove = random.choice((-1,1)) - elif self.voicing.bcount and self.voicing.dir: - vmove = self.voicing.dir + self.dupRoot = seqBump(tmp) + if gbl.debug: + print "Set %s DupRoot to " % self.name, + printList(ln) - for p in pattern: - tb = self.getChordInPos(p.offset, ctable) - if tb.chordZ: - continue + def setStrum(self, ln): + """ Set Strum time. """ - self.crDupRoot = self.dupRoot[sc] + ln=self.lnExpand(ln, 'Strum') + tmp = [] - vmode = self.voicing.mode - vols = p.vol[0:tb.chord.noteListLen] + for n in ln: + n = stoi(n, "Argument for %s Strum must be an integer" % self.name) - # Limit the chord notes. This works even if THERE IS A VOICINGMODE! + if n < 0 or n > 100: + error("Strum %s out-of-range; must be 0..100" % n) - if self.chordLimit: - tb.chord.limit(self.chordLimit) + tmp.append(n) - """ Compress chord into single octave if 'compress' is set - We do it here, before octave, transpose and invert! - Ignored if we have a VOICINGMODE. - """ + self.strum = seqBump(tmp) - if self.compress[sc] and not vmode: - tb.chord.compress() + if gbl.debug: + print "Set %s Strum to %s" % (self.name, self.strum) - # Do the voicing stuff. - if vmode: - vmove=self.chordVoicing(tb.chord, vmove) + def getPgroup(self, ev): + """ Get group for chord pattern. - # Invert. + Tuples: [start, length, volume (,volume ...) ] + """ - if self.invert[sc]: - tb.chord.invert(self.invert[sc]) + if len(ev) < 3: + error("There must be at least 3 items in each group " + "of a chord pattern definition, not <%s>" % ' '.join(ev)) - # Set STRUM flags + a = struct() - strumAdjust = self.strum[sc] - strumOffset = 0 - sd = self.direction[sc] - if sd=='BOTH': - sd = 'BOTHDOWN' - if sd == 'BOTHDOWN': - sd = 'BOTHUP' - elif sd == 'BOTHUP': - sd = 'BOTHDOWN' + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen(ev[1]) - if strumAdjust and sd in ('DOWN', 'BOTHDOWN'): - strumOffset += strumAdjust * tb.chord.noteListLen - strumAdjust = -strumAdjust + vv = ev[2:] + if len(vv)>8: + error("Only 8 volumes are permitted in Chord definition, not %s" % len(vv)) + a.vol = [0] * 8 + for i,v in enumerate(vv): + v=stoi(v, "Expecting integer in volume list for Chord definition") + a.vol[i]=v - """ Voicing adjustment for 'jazz' or altered chords. If a chord (most - likely something like a M7 or flat-9 ends up with any 2 adjacent - notes separated by a single tone an unconfortable dissonance results. - This little check compares all notes in the chord and will cut the - volume of one note to reduce the disonance. Usually this will be - the root note volume being decreased. - """ + for i in range(i+1,8): # force remaining volumes + a.vol[i]=v - nl=tb.chord.noteList - l=len(nl) - for j in range(l-1): - r = nl[j] - for i in range(j+1, l): - if nl[i] in (r-1, r+1, r-13, r+13) and vols[i] >= vols[0]: - vols[j] = vols[i]/2 - break + return a - loo = zip(nl, vols) # this is a note/volume array of tuples + def restart(self): + self.ssvoice = -1 + self.lastChord = None - """ Duplicate the root. This can be set from a DupRoot command - or by chordVoicing(). Notes: - - The volume for the added root will be the average of the chord - notes (ignoring OFF notes) divided by 2. - - If the new note (after transpose and octave adjustments - is out of MIDI range it will be ignored. - """ + def chordVoicing(self, chord, vMove): + """ Voicing algorithm by Alain Brenzikofer. """ - if self.crDupRoot: - root = tb.chord.rootNote + self.crDupRoot - t = root + self.octave[sc] + gbl.transpose - if t >=0 and t < 128: - v=0 - c=0 - for vv in vols: - if vv: - v += vv - c += 2 - v /= c - loo.append( (tb.chord.rootNote + self.crDupRoot, v)) - for note, v in sorted(loo): # sorting low-to-high notes. Mainly for STRUM. - self.sendNote( - p.offset+strumOffset, - self.getDur(p.duration), - self.adjustNote(note), - self.adjustVolume( v, p.offset) ) + sc = self.seq + vmode=self.voicing.mode - strumOffset += strumAdjust + if vmode == "OPTIMAL": - tb.chord.reset() # important, other tracks chord object + # Initialize with a voicing around centerNote - # Adjust the voicingMove counter at the end of the bar + chord.center1(self.lastChord) - if self.voicing.bcount: - self.voicing.bcount -= 1 + # Adjust range and center + + if not (self.voicing.bcount or self.voicing.random): + chord.center2(self.voicing.center, self.voicing.range/2) + + + # Move voicing + + elif self.lastChord: + if (self.lastChord != chord.noteList ) and vMove: + chord.center2(self.voicing.center,self.voicing.range/2) + vMove = 0 + + # Update voicingCenter + + sum=0 + for n in chord.noteList: + sum += n + c=sum/chord.noteListLen + + """ If using random voicing move it it's possible to + get way off the selected octave. This check ensures + that the centerpoint stays in a tight range. + Note that if using voicingMove manually (not random) + it is quite possible to move the chord centers to very + low or high keyboard positions! + """ + + if self.voicing.random: + if c < -4: c=0 + elif c >4: c=4 + self.voicing.center=c + + + elif vmode == "COMPRESSED": + chord.compress() + + elif vmode == "INVERT": + if chord.rootNote < -2: + chord.invert(1) + + elif chord.rootNote > 2: + chord.invert(-1) + chord.compress() + + self.lastChord = chord.noteList[:] + + return vMove + + + def trackBar(self, pattern, ctable): + """ Do a chord bar. Called from self.bar() """ + + sc = self.seq + unify = self.unify[sc] + + """ Set voicing move ONCE at the top of each bar. + The voicing code resets vmove to 0 the first + time it's used. That way only one movement is + done in a bar. + """ + + vmove = 0 + + if self.voicing.random: + if random.randrange(100) <= self.voicing.random: + vmove = random.choice((-1,1)) + elif self.voicing.bcount and self.voicing.dir: + vmove = self.voicing.dir + + + for p in pattern: + tb = self.getChordInPos(p.offset, ctable) + + if tb.chordZ: + continue + + self.crDupRoot = self.dupRoot[sc] + + vmode = self.voicing.mode + vols = p.vol[0:tb.chord.noteListLen] + + # Limit the chord notes. This works even if THERE IS A VOICINGMODE! + + if self.chordLimit: + tb.chord.limit(self.chordLimit) + + """ Compress chord into single octave if 'compress' is set + We do it here, before octave, transpose and invert! + Ignored if we have a VOICINGMODE. + """ + + if self.compress[sc] and not vmode: + tb.chord.compress() + + # Do the voicing stuff. + + if vmode: + vmove=self.chordVoicing(tb.chord, vmove) + + # Invert. + + if self.invert[sc]: + tb.chord.invert(self.invert[sc]) + + # Set STRUM flags + + strumAdjust = self.strum[sc] + strumOffset = 0 + sd = self.direction[sc] + if sd=='BOTH': + sd = 'BOTHDOWN' + if sd == 'BOTHDOWN': + sd = 'BOTHUP' + elif sd == 'BOTHUP': + sd = 'BOTHDOWN' + + if strumAdjust and sd in ('DOWN', 'BOTHDOWN'): + strumOffset += strumAdjust * tb.chord.noteListLen + strumAdjust = -strumAdjust + + + """ Voicing adjustment for 'jazz' or altered chords. If a chord (most + likely something like a M7 or flat-9 ends up with any 2 adjacent + notes separated by a single tone an unconfortable dissonance results. + This little check compares all notes in the chord and will cut the + volume of one note to reduce the disonance. Usually this will be + the root note volume being decreased. + """ + + nl=tb.chord.noteList + l=len(nl) + for j in range(l-1): + r = nl[j] + for i in range(j+1, l): + if nl[i] in (r-1, r+1, r-13, r+13) and vols[i] >= vols[0]: + vols[j] = vols[i]/2 + break + + loo = zip(nl, vols) # this is a note/volume array of tuples + + + """ Duplicate the root. This can be set from a DupRoot command + or by chordVoicing(). Notes: + - The volume for the added root will be the average of the chord + notes (ignoring OFF notes) divided by 2. + - If the new note (after transpose and octave adjustments + is out of MIDI range it will be ignored. + """ + + if self.crDupRoot: + root = tb.chord.rootNote + self.crDupRoot + t = root + self.octave[sc] + gbl.transpose + if t >=0 and t < 128: + v=0 + c=0 + for vv in vols: + if vv: + v += vv + c += 2 + v /= c + loo.append( (tb.chord.rootNote + self.crDupRoot, v)) + + for note, v in sorted(loo): # sorting low-to-high notes. Mainly for STRUM. + self.sendNote( + p.offset+strumOffset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume( v, p.offset) ) + + strumOffset += strumAdjust + + tb.chord.reset() # important, other tracks chord object + + # Adjust the voicingMove counter at the end of the bar + + if self.voicing.bcount: + self.voicing.bcount -= 1 diff --git a/mma/MMA/patDrum.py b/mma/MMA/patDrum.py index 20f293f..dd272ab 100644 --- a/mma/MMA/patDrum.py +++ b/mma/MMA/patDrum.py @@ -2,7 +2,7 @@ # patDrum.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ import gbl @@ -31,73 +31,84 @@ from MMA.pat import PC, seqBump class Drum(PC): - """ Pattern class for a drum track. """ + """ Pattern class for a drum track. """ - vtype = 'DRUM' - toneList = [38] + vtype = 'DRUM' + toneList = [38] - def setTone(self, ln): - """ Set a tone list. Only valid for DRUMs. - ln[] is not nesc. the right length. - """ - - ln=self.lnExpand(ln, 'Tone') - tmp = [] - - for n in ln: - tmp.append(MMA.translate.dtable.get(n)) + def __init__(self, ln): + """ init for drum track. """ - self.toneList = seqBump( tmp ) + PC.__init__(self, ln) + + self.setChannel('10') + if not gbl.mtrks[self.channel].trackname: + gbl.mtrks[self.channel].addTrkName(0, 'Drum') - def restart(self): - self.ssvoice = -1 - - - def getPgroup(self, ev): - """ Get group for a drum pattern. - - Fields - start, length, volume - """ + + def setTone(self, ln): + """ Set a tone list. Only valid for DRUMs. + ln[] is not nesc. the right length. + """ - if len(ev) != 3: - error("There must be at exactly 3 items in each " - "group of a drum define, not <%s>." % ' '.join(ev) ) + ln=self.lnExpand(ln, 'Tone') + tmp = [] + + for n in ln: + tmp.append(MMA.translate.dtable.get(n)) + + self.toneList = seqBump( tmp ) + + + def restart(self): + self.ssvoice = -1 + + + def getPgroup(self, ev): + """ Get group for a drum pattern. + + Fields - start, length, volume + """ + + if len(ev) != 3: + error("There must be at exactly 3 items in each " + "group of a drum define, not <%s>" % ' '.join(ev) ) + + a = struct() + + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen(ev[1]) + a.vol = stoi(ev[2], "Type error in Drum volume") + + return a + + + + def trackBar(self, pattern, ctable): + """ Do a drum bar. + + Called from self.bar() + + """ + + sc = self.seq + + for p in pattern: + tb = self.getChordInPos(p.offset, ctable) + + if tb.drumZ: + continue + + self.sendNote( + p.offset, + self.getDur(p.duration), + self.toneList[sc], + self.adjustVolume(p.vol, p.offset) ) - a = struct() - - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen(ev[1]) - a.vol = stoi(ev[2], "Type error in Drum volume.") - return a - - - def trackBar(self, pattern, ctable): - """ Do a drum bar. - - Called from self.bar() - - """ - - sc = self.seq - - for p in pattern: - tb = self.getChordInPos(p.offset, ctable) - - if tb.drumZ: - continue - self.sendNote( - p.offset, - self.getDur(p.duration), - self.toneList[sc], - self.adjustVolume(p.vol, p.offset) ) - - - - diff --git a/mma/MMA/patScale.py b/mma/MMA/patScale.py index dd76b50..21e7701 100644 --- a/mma/MMA/patScale.py +++ b/mma/MMA/patScale.py @@ -19,197 +19,213 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ - - - import random from MMA.harmony import harmonize from MMA.notelen import getNoteLen import gbl from MMA.common import * -from MMA.pat import PC +from MMA.pat import PC, seqBump class Scale(PC): - """ Pattern class for a Scale track. """ + """ Pattern class for a Scale track. """ - vtype = 'SCALE' + vtype = 'SCALE' - lastNote = -1 - lastChord = None - lastStype = None - lastDirect = 1 - lastRange = 0 - sOffset = 0 - notes = None - dirfact = 1 + lastNote = -1 + lastChord = None + lastStype = None + lastDirect = 1 + lastRange = 0 + sOffset = 0 + notes = None + dirfact = 1 - def getPgroup(self, ev): - """ Get group for scale patterns. + def getPgroup(self, ev): + """ Get group for scale patterns. - Fields - start, length, volume - """ + Fields - start, length, volume + """ - if len(ev) != 3: - error("There must be at exactly 3 items in each group " - "in a Scale definition, not <%s>." % ' '.join(ev)) + if len(ev) != 3: + error("There must be at exactly 3 items in each group " + "in a Scale definition, not <%s>." % ' '.join(ev)) - a = struct() + a = struct() - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen(ev[1]) - a.vol = stoi(ev[2], "Type error in Scale definition") + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen(ev[1]) + a.vol = stoi(ev[2], "Type error in Scale definition") - return a + return a - def restart(self): - self.ssvoice = -1 - self.lastNote = -1 - self.lastChord = None - self.lastStype = None - self.lastDirect = 1 - self.lastRange = 0 - self.sOffset = 0 - self.notes = None - self.dirfact = 1 + def setScaletype(self, ln): + """ Set scale type. """ - def trackBar(self, pattern, ctable): - """ Do a scale bar. + ln = self.lnExpand(ln, "ScaleType") + tmp = [] - Called from self.bar() - """ + for n in ln: + n = n.upper() + if not n in ( 'CHROMATIC', 'AUTO'): + error("Unknown %s ScaleType. Only Chromatic and Auto are valid" % self.name) + tmp.append(n) - sc = self.seq - direct = self.direction[sc] - unify = self.unify[sc] + self.scaleType = seqBump(tmp) - # If the range or direction has changed, we just start - # with a new scale. + if gbl.debug: + print "Set %s ScaleType to " % self.name, + printList(ln) - t = self.chordRange[sc] - if t != self.lastRange: - self.lastRange = t - self.lastChord = None + def restart(self): + self.ssvoice = -1 + self.lastNote = -1 + self.lastChord = None + self.lastStype = None + self.lastDirect = 1 + self.lastRange = 0 + self.sOffset = 0 + self.notes = None + self.dirfact = 1 - if self.lastDirect != direct: - self.lastDirect = direct - self.lastChord = None + def trackBar(self, pattern, ctable): + """ Do a scale bar. - for p in pattern: + Called from self.bar() + """ - tb = self.getChordInPos(p.offset, ctable) + sc = self.seq + direct = self.direction[sc] + unify = self.unify[sc] - if tb.scaleZ: - continue + # If the range or direction has changed, we just start + # with a new scale. - thisChord = tb.chord.tonic + tb.chord.chordType - stype = self.scaleType[sc] + t = self.chordRange[sc] + if t != self.lastRange: + self.lastRange = t + self.lastChord = None - if thisChord != self.lastChord or stype != self.lastStype: - self.lastChord = thisChord - self.lastStype = stype + if self.lastDirect != direct: + self.lastDirect = direct + self.lastChord = None - if stype == 'CHROMATIC': - notelist = [ tb.chord.rootNote + x for x in range(0,12)] + for p in pattern: - else: - notelist = list(tb.chord.scaleList) + tb = self.getChordInPos(p.offset, ctable) - """ Get the current scale and append enuf copies - together for RANGE setting. If Range happens - to be 0 or 1 we end up with a single copy. - """ - - ln=self.chordRange[sc] # RANGE 1...x (def. == 1) - - o=0 - self.notes = [] - - while ln >= 1: - for a in notelist: - self.notes.append(a+o) - o+=12 - ln-=1 - - if ln>0 and ln<1: # for fractional scale lengths - ln = int(len(notelist) * ln) - if ln < 2: # important, must be at least 2 notes in a scale - ln=2 - for a in notelist[:ln]: - self.notes.append(a+o) - - if direct == 'DOWN': - self.dirfact = -1 - if self.lastNote == -1: - self.sOffset = len(self.notes)-1 - else: - self.sOffset = 0 - - if self.lastNote > -1: - if self.lastNote in self.notes: - self.sOffset = self.notes.index(self.lastNote) - - else: - self.sOffset=len(self.notes)-1 - for i, a in enumerate(self.notes): - if a>self.lastNote: - self.sOffset = i - break + if tb.scaleZ: + continue - # Keep offset into note list in range + thisChord = tb.chord.tonic + tb.chord.chordType + stype = self.scaleType[sc] - # only > end of list if BOTH or UP + if thisChord != self.lastChord or stype != self.lastStype: + self.lastChord = thisChord + self.lastStype = stype - if self.sOffset >= len(self.notes): - if direct == 'BOTH': - self.dirfact = -1 - self.sOffset = len(self.notes)-2 - else: ## UP - self.sOffset = 0 + if stype == 'CHROMATIC': + notelist = [ tb.chord.rootNote + x for x in range(0,12)] + + else: + notelist = list(tb.chord.scaleList) - # only < start of list if DOWN or BOTH + """ Get the current scale and append enuf copies + together for RANGE setting. If Range happens + to be 0 or 1 we end up with a single copy. + """ - elif self.sOffset < 0: - if direct == 'BOTH': - self.dirfact = 1 - self.sOffset = 1 - else: ## DOWN - self.sOffset = len(self.notes)-1 + ln=self.chordRange[sc] # RANGE 1...x (def. == 1) - if direct == 'RANDOM': - note = random.choice(self.notes) - else: - note = self.notes[self.sOffset] - self.sOffset += self.dirfact + o=0 + self.notes = [] - self.lastNote = note + while ln >= 1: + for a in notelist: + self.notes.append(a+o) + o+=12 + ln-=1 - if not self.harmonyOnly[sc]: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(note), - self.adjustVolume(p.vol, p.offset)) + if ln>0 and ln<1: # for fractional scale lengths + ln = int(len(notelist) * ln) + if ln < 2: # important, must be at least 2 notes in a scale + ln=2 + for a in notelist[:ln]: + self.notes.append(a+o) + + if direct == 'DOWN': + self.dirfact = -1 + if self.lastNote == -1: + self.sOffset = len(self.notes)-1 + else: + self.sOffset = 0 + + if self.lastNote > -1: + if self.lastNote in self.notes: + self.sOffset = self.notes.index(self.lastNote) + + else: + self.sOffset=len(self.notes)-1 + for i, a in enumerate(self.notes): + if a>self.lastNote: + self.sOffset = i + break - if self.harmony[sc]: - ch = self.getChordInPos(p.offset, ctable).chord.noteList - h = harmonize(self.harmony[sc], note, ch) - for n in h: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(n), - self.adjustVolume(self.harmonyVolume[sc] * p.vol, -1) ) + # Keep offset into note list in range + + # only > end of list if BOTH or UP + + if self.sOffset >= len(self.notes): + if direct == 'BOTH': + self.dirfact = -1 + self.sOffset = len(self.notes)-2 + else: ## UP + self.sOffset = 0 + + # only < start of list if DOWN or BOTH + + elif self.sOffset < 0: + if direct == 'BOTH': + self.dirfact = 1 + self.sOffset = 1 + else: ## DOWN + self.sOffset = len(self.notes)-1 + + if direct == 'RANDOM': + note = random.choice(self.notes) + else: + note = self.notes[self.sOffset] + self.sOffset += self.dirfact + + self.lastNote = note + + if not self.harmonyOnly[sc]: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume(p.vol, p.offset)) + + + if self.harmony[sc]: + ch = self.getChordInPos(p.offset, ctable).chord.noteList + h = harmonize(self.harmony[sc], note, ch) + for n in h: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(n), + self.adjustVolume(self.harmonyVolume[sc] * p.vol, -1) ) diff --git a/mma/MMA/patSolo.py b/mma/MMA/patSolo.py index 4c49996..f3a32c9 100644 --- a/mma/MMA/patSolo.py +++ b/mma/MMA/patSolo.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ @@ -34,500 +34,512 @@ import MMA.volume class NoteList: - def __init__(self, length): - self.dur = length - self.velocity = [] - self.nl = [] + def __init__(self, length): + self.dur = length + self.velocity = [] + self.nl = [] ############################## class Melody(PC): - """ The melody and solo tracks are identical, expect that - the solo tracks DO NOT get saved in grooves and are only - initialized once. - """ + """ The melody and solo tracks are identical, expect that + the solo tracks DO NOT get saved in grooves and are only + initialized once. + """ - vtype = 'MELODY' - drumType = None + vtype = 'MELODY' + drumType = None + + endTilde = [] + drumTone = 38 - endTilde = [] - drumTone = 38 + def setDrumType(self): + """ Set this track to be a drum track. """ - def setDrumType(self): - """ Set this track to be a drum track. """ + if self.channel: + error("You cannot change a track to DRUM once it has been used") - if self.channel: - error("You cannot change a track to DRUM once it has been used.") + self.drumType = 1 + self.setChannel('10') - self.drumType = 1 - self.setChannel('10') + def definePattern(self, name, ln): + error("Melody/solo patterns cannot be defined") - def definePattern(self, name, ln): - error("Melody/solo patterns cannot be defined.") + def restart(self): + self.ssvoice = -1 - def restart(self): - self.ssvoice = -1 + def setTone(self, ln): + """ A solo track can have a tone, if it is DRUMTYPE.""" - def setTone(self, ln): - """ A solo track can have a tone, if it is DRUMTYPE.""" + if not self.drumType: + error("You must set a Solo track to DrumType before setting Tone") - if not self.drumType: - error("You must set a Solo track to DrumType before setting Tone.") + if len(ln) > 1: + error("Only 1 value permitted for Drum Tone in Solo tracks") - if len(ln) > 1: - error("Only 1 value permitted for Drum Tone in Solo tracks.") + self.drumTone = MMA.translate.dtable.get(ln[0]) - self.drumTone = MMA.translate.dtable.get(ln[0]) + def getLine(self, pat, ctable): + """ Extract a melodyline for solo/melody tracks. + This is only called from trackbar(), but it's nicer + to isolate it here. - def getLine(self, pat, ctable): - """ Extract a melodyline for solo/melody tracks. - This is only called from trackbar(), but it's nicer - to isolate it here. - """ + RETURNS: notes structure. This is a dictionary. Each key represents + an offset in MIDI ticks in the current bar. The data for + each entry is an array of notes, a duration and velocity: - sc = self.seq - barEnd = gbl.BperQ*gbl.QperBar + notes[offset].dur - duration in ticks + notes[offset].velocity[] - velocity for notes + notes[offset].defaultVel - default velocity for this offset + notes[offset].nl[] - list of notes (if the only note value + is None this is a rest placeholder) - acc=keySig.getAcc() + """ - # list of notename to midivalues + sc = self.seq + barEnd = gbl.BperQ*gbl.QperBar - midiNotes = {'c':0, 'd':2, 'e':4, 'f':5, 'g':7, 'a':9, 'b':11, 'r':None } + acc=keySig.getAcc() - """ The initial string is in the format "1ab;4c;;4r;". The trailing - ';' is important and needed. If we don't have this requirement - we can't tell if the last note is a repeat of the previous. For - example, if we have coded "2a;2a;" as "2a;;" and we didn't - have the 'must end with ;' rule, we end up with "2a;" and - then we make this into 2 notes...or do we? Easiest just to - insist that all bars end with a ";". - """ + # list of notename to midivalues - if not pat.endswith(';'): - error("All Solo strings must end with a ';'") + midiNotes = {'c':0, 'd':2, 'e':4, 'f':5, 'g':7, 'a':9, 'b':11, 'r':None } - """ Take our list of note/value pairs and decode into - a list of midi values. Quite ugly. - """ + """ The initial string is in the format "1ab;4c;;4r;". The trailing + ';' is important and needed. If we don't have this requirement + we can't tell if the last note is a repeat of the previous. For + example, if we have coded "2a;2a;" as "2a;;" and we didn't + have the 'must end with ;' rule, we end up with "2a;" and + then we make this into 2 notes...or do we? Easiest just to + insist that all bars end with a ";". + """ - if gbl.swingMode: - len8 = getNoteLen('8') - len81 = getNoteLen('81') - len82 = getNoteLen('82') - onBeats = [ x * gbl.BperQ for x in range(gbl.QperBar)] - offBeats = [ (x * gbl.BperQ + len8) for x in range(gbl.QperBar)] + if not pat.endswith(';'): + error("All Solo strings must end with a ';'") + """ Take our list of note/value pairs and decode into + a list of midi values. Quite ugly. + """ - length = getNoteLen('4') # default note length - lastc = '' # last parsed note - velocity = 90 # intial/default velocity for solo notes - harmony = self.harmony[sc] - harmOnly = self.harmonyOnly[sc] + if gbl.swingMode: + len8 = getNoteLen('8') + len81 = getNoteLen('81') + len82 = getNoteLen('82') + onBeats = [ x * gbl.BperQ for x in range(gbl.QperBar)] + offBeats = [ (x * gbl.BperQ + len8) for x in range(gbl.QperBar)] - notes={} # A dict of NoteList, keys == offset - if self.drumType: - isdrum = 1 - lastc = str(self.drumTone) - else: - isdrum = None + length = getNoteLen('4') # default note length + lastc = '' # last parsed note + velocity = 90 # intial/default velocity for solo notes - pat = pat.replace(' ', '').split(';')[:-1] + notes={} # A dict of NoteList, keys == offset - # set initial offset into bar + if self.drumType: + isdrum = 1 + lastc = str(self.drumTone) + else: + isdrum = None - if pat[0].startswith("~"): - pat[0]=pat[0][1:] - if not self.endTilde or self.endTilde[1] != gbl.tickOffset: - error("Previous line did not end with '~'.") - else: - offset = self.endTilde[0] - else: - offset = 0 - lastOffset = None + pat = pat.replace(' ', '').split(';')[:-1] - # Strip off trailing ~ + # set initial offset into bar - if pat[-1].endswith("~"): - self.endTilde = [1, gbl.tickOffset + (gbl.BperQ * gbl.QperBar) ] - pat[-1]=pat[-1][:-1] - else: - self.endTilde = [] + if pat[0].startswith("~"): + pat[0]=pat[0][1:] + if not self.endTilde or self.endTilde[1] != gbl.tickOffset: + error("Previous line did not end with '~'") + else: + offset = self.endTilde[0] + else: + offset = 0 + lastOffset = None + # Strip off trailing ~ - # Begin parse loop + if pat[-1].endswith("~"): + self.endTilde = [1, gbl.tickOffset + (gbl.BperQ * gbl.QperBar) ] + pat[-1]=pat[-1][:-1] + else: + self.endTilde = [] - for a in pat: - if a == '<>': - continue - if offset >= barEnd: - error("Attempt to start Solo note '%s' after end of bar." % a) + # Begin parse loop - # strip out all '' setting and adjust velocity + for a in pat: + if a == '<>': + continue - a, vls = pextract(a, "<", ">") - if vls: - if len(vls) > 1: - error("Only 1 volume string is permitted per note-set") + if offset >= barEnd: + error("Attempt to start Solo note '%s' after end of bar" % a) - vls = vls[0].upper().strip() - if not vls in MMA.volume.vols: - error("%s string Expecting a valid volume, not '%s'" % \ - (self.name, vls)) - velocity *= MMA.volume.vols[vls] + # strip out all '' setting and adjust velocity + a, vls = pextract(a, "<", ">") + if vls: + if len(vls) > 1: + error("Only 1 volume string is permitted per note-set") - """ Split the chord chunk into a note length and notes. Each - part of this is optional and defaults to the previously - parsed value. - """ + vls = vls[0].upper().strip() + if not vls in MMA.volume.vols: + error("%s string Expecting a valid volume, not '%s'" % \ + (self.name, vls)) + velocity *= MMA.volume.vols[vls] - i = 0 - while i < len(a): - if not a[i] in '1234568.+': - break - else: - i+=1 - if i: - l=getNoteLen(a[0:i]) - c=a[i:] - else: - l=length - c=a + """ Split the chord chunk into a note length and notes. Each + part of this is optional and defaults to the previously + parsed value. + """ - if not c: - c=lastc - if not c: - error("You must specify the first note in a solo line") + i = 0 + while i < len(a): + if not a[i] in '1234568.+': + break + else: + i+=1 - length = l # set defaults for next loop - lastc = c + if i: + l=getNoteLen(a[0:i]) + c=a[i:] + else: + l=length + c=a + if not c: + c=lastc + if not c: + error("You must specify the first note in a solo line") - """ Convert the note part into a series of midi values - Notes can be a single note, or a series of notes. And - each note can be a letter a-g (or r), a '#,&,n' plus - a series of '+'s or '-'s. Drum solos must have each - note separated by ','s: "Snare1,Kick1,44". - """ + length = l # set defaults for next loop + lastc = c - if isdrum: - c=c.split(',') - else: - c=list(c) - while c: + """ Convert the note part into a series of midi values + Notes can be a single note, or a series of notes. And + each note can be a letter a-g (or r), a '#,&,n' plus + a series of '+'s or '-'s. Drum solos must have each + note separated by ','s: "Snare1,Kick1,44". + """ - # Parse off note name or 'r' for a rest + if isdrum: + c=c.split(',') + else: + c=list(c) - name = c.pop(0) + while c: - if name == 'r' and (offset in notes or c): - error("You cannot combine a rest with a note in " - "a chord for solos.") + # Parse off note name or 'r' for a rest + name = c.pop(0) - if not isdrum: - if not name in midiNotes: - error("%s encountered illegal note name '%s'." - % (self.name, name)) + if name == 'r' and (offset in notes or c): + error("You cannot combine a rest with a note in a chord for solos") - v = midiNotes[ name ] - # Parse out a "#', '&' or 'n' accidental. + if not isdrum: + if not name in midiNotes: + error("%s encountered illegal note name '%s'" + % (self.name, name)) - if c and c[0]=='#': - c.pop(0) - acc[name] = 1 + v = midiNotes[ name ] - elif c and c[0]=='&': - c.pop(0) - acc[name] = -1 + # Parse out a "#', '&' or 'n' accidental. - elif c and c[0]=='n': - c.pop(0) - acc[name] = 0 + if c and c[0]=='#': + c.pop(0) + acc[name] = 1 - if v != None: - v += acc[name] + elif c and c[0]=='&': + c.pop(0) + acc[name] = -1 - # Parse out +/- (or series) for octave + elif c and c[0]=='n': + c.pop(0) + acc[name] = 0 - if c and c[0] == '+': - while c and c[0] == '+': - c.pop(0) - v += 12 - elif c and c[0] == '-': - while c and c[0] == '-': - c.pop(0) - v -= 12 + if v != None: + v += acc[name] - else: - if not name: # just for leading '.'s - continue - if name == 'r': - v = midiNotes[ name ] - elif name == '*': - v = self.drumTone - else: - v = MMA.translate.dtable.get(name) + # Parse out +/- (or series) for octave + if c and c[0] == '+': + while c and c[0] == '+': + c.pop(0) + v += 12 + elif c and c[0] == '-': + while c and c[0] == '-': + c.pop(0) + v -= 12 - """ Swingmode -- This tests for successive 8ths on/off beat - If found, the first is converted to 'long' 8th, the 2nd to a 'short' - and the offset for the 2nd is adjusted to comp. for the 'long'. - """ + else: + if not name: # just for leading '.'s + continue + if name == 'r': + v = midiNotes[ name ] + elif name == '*': + v = self.drumTone + else: + v = MMA.translate.dtable.get(name) - if gbl.swingMode and l==len8 and \ - offset in offBeats and \ - lastOffset in onBeats and \ - lastOffset in notes: - if notes[lastOffset].dur == len8: - offset = lastOffset + len81 - notes[lastOffset].dur = len81 - l=len82 + """ Swingmode -- This tests for successive 8ths on/off beat + If found, the first is converted to 'long' 8th, the 2nd to a 'short' + and the offset for the 2nd is adjusted to comp. for the 'long'. + """ - # create a new note[] entry for this offset + if gbl.swingMode and l==len8 and \ + offset in offBeats and \ + lastOffset in onBeats and \ + lastOffset in notes: + if notes[lastOffset].dur == len8: + offset = lastOffset + len81 + notes[lastOffset].dur = len81 + l=len82 - if not offset in notes: - notes[offset] = NoteList(l) - # add note event to note[] array + # create a new note[] entry for this offset - notes[offset].nl.append(v) - notes[offset].velocity.append(self.adjustVolume(velocity, offset)) + if not offset in notes: + notes[offset] = NoteList(l) - """ Do harmony. This is done for each chord as they are - parsed out. So, after parsing out the "16g" from the solo - string "4a;16g;4c;" we add the harmony notes to the 'g' note. + # add note event to note[] array - The chord is not processed if this is a "drum-type", if there is - more than one note in the chord (we assume user harmony), - if the chord for the current beat is a 'z', or if the note - is a 'rest' (note==None). - """ + notes[offset].nl.append(v) + notes[offset].velocity.append(self.adjustVolume(velocity, offset)) - if harmony and offset in notes and not isdrum: - nn=notes[offset] + notes[offset].defaultVel = velocity # needed for addHarmony() - if len(nn.nl) == 1 and nn.nl[0] != None: - tb = self.getChordInPos(offset, ctable) + lastOffset = offset + offset += l - if not tb.chordZ: - h = harmonize(harmony, nn.nl[0], tb.chord.bnoteList) + if offset <= barEnd: + if self.endTilde: + error("Tilde at end of bar has no effect") - """ If harmonyonly set then drop note, substitute harmony, - else append harmony notes to chord. - """ + else: + if self.endTilde: + self.endTilde[0]=offset-barEnd + else: + warning("%s, end of last note overlaps end of bar by %2.3f " + "beat(s)." % (self.name, (offset-barEnd)/float(gbl.BperQ))) - for i in range(len(h)): - nn.velocity.append(self.adjustVolume(velocity * - self.harmonyVolume[sc], offset)) + return notes - if harmOnly: - nn.nl = h - else: - nn.nl.extend(h) - lastOffset = offset - offset += l + def addHarmony(self, notes, ctable): + """ Add harmony to solo notes. """ + sc=self.seq - if offset <= barEnd: - if self.endTilde: - error("Tilde at end of bar has no effect.") + harmony = self.harmony[sc] + harmOnly = self.harmonyOnly[sc] + + + for offset in notes: + nn = notes[offset] + + if len(nn.nl) == 1 and nn.nl[0] != None: + tb = self.getChordInPos(offset, ctable) + + if tb.chordZ: + continue - else: - if self.endTilde: - self.endTilde[0]=offset-barEnd - else: - warning("%s, end of last note overlaps end of bar by %2.3f " - "beat(s)." % (self.name, (offset-barEnd)/float(gbl.BperQ))) + h = harmonize(harmony, nn.nl[0], tb.chord.bnoteList) - return notes + """ If harmonyonly set then drop note, substitute harmony, + else append harmony notes to chord. + """ + + if harmOnly: + nn.nl = h + nn.velocity = [] + off=0 + else: + nn.nl.extend(h) + off=1 + # Create velocites for harmony note(s) - def trackBar(self, pat, ctable): - """ Do the solo/melody line. Called from self.bar() """ + for i in range(off,len(nn.nl)): + nn.velocity.append(self.adjustVolume(nn.defaultVel * + self.harmonyVolume[sc], offset)) - notes = self.getLine(pat, ctable) + return notes - """ The notes structure is a dictionary. Each key represents an offset - in MIDI ticks in the current bar. The data for each entry is an array - of notes, a duration and velocity: - notes[offset].dur - duration in ticks - notes[offset].velocity[] - velocity for notes - notes[offset].nl[] - list of notes (if the only note value is None - this is a rest placeholder) - """ + def trackBar(self, pat, ctable): + """ Do the solo/melody line. Called from self.bar() """ - sc=self.seq - unify = self.unify[sc] + notes = self.getLine(pat, ctable) - rptr = self.mallet + if self.harmony[self.seq] and not self.drumType: + self.addHarmony(notes, ctable) - for offset in sorted(notes.keys()): - nn=notes[offset] + sc=self.seq + unify = self.unify[sc] - for n,v in zip(nn.nl, nn.velocity): - if n == None: # skip rests - continue + rptr = self.mallet - if not self.drumType: # octave, transpose - n = self.adjustNote(n) + for offset in sorted(notes.keys()): + nn=notes[offset] - self.sendNote( offset, self.getDur(nn.dur), n, v) + for n,v in zip(nn.nl, nn.velocity): + if n == None: # skip rests + continue + + if not self.drumType: # octave, transpose + n = self.adjustNote(n) + + self.sendNote( offset, self.getDur(nn.dur), n, v) class Solo(Melody): - """ Pattern class for a solo track. """ + """ Pattern class for a solo track. """ - vtype = 'SOLO' + vtype = 'SOLO' - # Grooves are not saved/restored for solo tracks. + # Grooves are not saved/restored for solo tracks. - def restoreGroove(self, gname): - self.setSeqSize() + def restoreGroove(self, gname): + self.setSeqSize() - def saveGroove(self, gname): - pass + def saveGroove(self, gname): + pass ################################## """ Keysignature. This is only used in the solo/melody tracks so it probably makes sense to have the parse routine here as well. To - contain everything in one location we make a single instance class - of the whole mess. + contain everything in one location we make a single instance class + of the whole mess. """ class KeySig: - def __init__(self): - self.kSig = 0 + def __init__(self): + self.kSig = 0 - majKy = { "C" : 0, "G" : 1, "D" : 2, - "A" : 3, "E" : 4, "B" : 5, - "F#": 6, "C#": 7, "F" : -1, - "Bb": -2, "Eb": -3, "Ab": -4, - "Db": -5, "Gb": -6, "Cb": -7 } + majKy = { "C" : 0, "G" : 1, "D" : 2, + "A" : 3, "E" : 4, "B" : 5, + "F#": 6, "C#": 7, "F" : -1, + "Bb": -2, "Eb": -3, "Ab": -4, + "Db": -5, "Gb": -6, "Cb": -7 } - minKy = { "A" : 0, "E" : 1, "B" : 2, - "F#": 3, "C#": 4, "G#": 5, - "D#": 6, "A#": 7, "D" : -1, - "G" : -2, "C" : -3, "F" : -4, - "Bb": -5, "Eb": -6, "Ab": -7 } + minKy = { "A" : 0, "E" : 1, "B" : 2, + "F#": 3, "C#": 4, "G#": 5, + "D#": 6, "A#": 7, "D" : -1, + "G" : -2, "C" : -3, "F" : -4, + "Bb": -5, "Eb": -6, "Ab": -7 } - def set(self,ln): - """ Set the keysignature. Used by solo tracks.""" + def set(self,ln): + """ Set the keysignature. Used by solo tracks.""" - mi = 0 + mi = 0 - if len(ln) < 1 or len(ln) > 2: - error("KeySig only takes 1 or 2 arguments.") + if len(ln) < 1 or len(ln) > 2: + error("KeySig only takes 1 or 2 arguments") - if len(ln) == 2: - l=ln[1][0:3].upper() - if l == 'MIN': - mi=1 - elif l == 'MAJ': - mi=0 - else: - error("KeySig 2nd arg must be 'Major' or 'Minor', not '%s'" % ln[1]) + if len(ln) == 2: + l=ln[1][0:3].upper() + if l == 'MIN': + mi=1 + elif l == 'MAJ': + mi=0 + else: + error("KeySig 2nd arg must be 'Major' or 'Minor', not '%s'" % ln[1]) - l=ln[0] + l=ln[0] - t=l[0].upper() + l[1:] + t=l[0].upper() + l[1:] - if mi and t in self.minKy: - self.kSig = self.minKy[t] - elif not mi and t in self.majKy: - self.kSig = self.majKy[t] - elif l[0] in "ABCDEFG": - error("There is no key signature name: '%s'" % l) + if mi and t in self.minKy: + self.kSig = self.minKy[t] + elif not mi and t in self.majKy: + self.kSig = self.majKy[t] + elif l[0] in "ABCDEFG": + error("There is no key signature name: '%s'" % l) - else: - c=l[0] - f=l[1].upper() + else: + c=l[0] + f=l[1].upper() - if not f in ("B", "&", "#"): - error("2nd char in KeySig must be 'b' or '#', not '%s'" % f) + if not f in ("B", "&", "#"): + error("2nd char in KeySig must be 'b' or '#', not '%s'" % f) - if not c in "01234567": - error("1st char in KeySig must be digit 0..7, not '%s'" % c) + if not c in "01234567": + error("1st char in KeySig must be digit 0..7, not '%s'" % c) - self.kSig = int(c) + self.kSig = int(c) - if f in ('B', '&'): - self.kSig = -self.kSig + if f in ('B', '&'): + self.kSig = -self.kSig - if not c in "01234567": - error("1st char in KeySig must be digit 0..7, not '%s'" % c) + if not c in "01234567": + error("1st char in KeySig must be digit 0..7, not '%s'" % c) - # Set the midi meta track with the keysig. This doen't do anything - # in the playback, but other programs may use it. + # Set the midi meta track with the keysig. This doen't do anything + # in the playback, but other programs may use it. - n = self.kSig - if n < 0: - n = 256 + n + n = self.kSig + if n < 0: + n = 256 + n - gbl.mtrks[0].addKeySig(gbl.tickOffset, n, mi) + gbl.mtrks[0].addKeySig(gbl.tickOffset, n, mi) - if gbl.debug: - n = self.kSig - if n >= 0: - f = "Sharps" - else: - f = "Flats" + if gbl.debug: + n = self.kSig + if n >= 0: + f = "Sharps" + else: + f = "Flats" - print "KeySig set to %s %s" % (abs(n), f) + print "KeySig set to %s %s" % (abs(n), f) - def getAcc(self): - """ The solo parser needs to know which notes are accidentals. - This is simple with a keysig table. There is an entry for each note, - either -1,0,1 corresponding to flat,natural,sharp. We populate - the table for each bar from the keysig value. As we process - the bar data we update the table. There is one flaw here---in - real music an accidental for a note in a give octave does not - effect the following same-named notes in different octaves. - In this routine IT DOES. + def getAcc(self): + """ The solo parser needs to know which notes are accidentals. + This is simple with a keysig table. There is an entry for each note, + either -1,0,1 corresponding to flat,natural,sharp. We populate + the table for each bar from the keysig value. As we process + the bar data we update the table. There is one flaw here---in + real music an accidental for a note in a give octave does not + effect the following same-named notes in different octaves. + In this routine IT DOES. - NOTE: This is recreated for each bar of music for each solo/melody track. - """ + NOTE: This is recreated for each bar of music for each solo/melody track. + """ - acc = {'a':0, 'b':0, 'c':0, 'd':0, 'e':0, 'f':0, 'g':0 } - ks=self.kSig + acc = {'a':0, 'b':0, 'c':0, 'd':0, 'e':0, 'f':0, 'g':0 } + ks=self.kSig - if ks < 0: - for a in range( abs(ks) ): - acc[ ['b','e','a','d','g','c','f'][a] ] = -1 + if ks < 0: + for a in range( abs(ks) ): + acc[ ['b','e','a','d','g','c','f'][a] ] = -1 - else: - for a in range(ks): - acc[ ['f','c','g','d','a','e','b'][a] ] = 1 + else: + for a in range(ks): + acc[ ['f','c','g','d','a','e','b'][a] ] = 1 - return acc + return acc keySig=KeySig() # single instance + ####################### """ When solos are included in a chord/data line they are @@ -539,83 +551,83 @@ autoSoloTracks = [ 'SOLO', 'SOLO-1', 'SOLO-2', 'SOLO-3' ] def setAutoSolo(ln): - """ Set the order and names of tracks to use when assigning - automatic solos (specified on chord lines in {}s). - """ + """ Set the order and names of tracks to use when assigning + automatic solos (specified on chord lines in {}s). + """ - global autoSoloTracks + global autoSoloTracks - if not len(ln): - error("You must specify at least one track for autosolos.") + if not len(ln): + error("You must specify at least one track for autosolos") - autoSoloTracks = [] - for n in ln: - n=n.upper() - MMA.alloc.trackAlloc(n, 1) - if gbl.tnames[n].vtype not in ('MELODY', 'SOLO'): - error("All autotracks must be Melody or Solo tracks, " - "not %s." % gbl.tnames[n].vtype) + autoSoloTracks = [] + for n in ln: + n=n.upper() + MMA.alloc.trackAlloc(n, 1) + if gbl.tnames[n].vtype not in ('MELODY', 'SOLO'): + error("All autotracks must be Melody or Solo tracks, not %s" % gbl.tnames[n].vtype) - autoSoloTracks.append(n) + autoSoloTracks.append(n) - if gbl.debug: - print "AutoSolo track names:", - for a in autoSoloTracks: - print a, - print + if gbl.debug: + print "AutoSolo track names:", + for a in autoSoloTracks: + print a, + print ############### + def extractSolo(ln, rptcount): - """ Parser calls this to extract solo strings. """ + """ Parser calls this to extract solo strings. """ - a = ln.count('{') - b = ln.count('}') + a = ln.count('{') + b = ln.count('}') - if a != b: - error("Mismatched {}s for solo found in chord line.") + if a != b: + error("Mismatched {}s for solo found in chord line") - if a: - if rptcount > 1: - error("Bars with both repeat count and solos are not permitted.") + if a: + if rptcount > 1: + error("Bars with both repeat count and solos are not permitted") - ln, solo = pextract(ln, '{', '}') + ln, solo = pextract(ln, '{', '}') - if len(solo) > len(autoSoloTracks): - error("Too many melody/solo riffs in chord line. %s used, " - "only %s defined." % (len(solo), len(autoSoloTracks)) ) + if len(solo) > len(autoSoloTracks): + error("Too many melody/solo riffs in chord line. %s used, " + "only %s defined" % (len(solo), len(autoSoloTracks)) ) - firstSolo = solo[0][:] # save for autoharmony tracks + firstSolo = solo[0][:] # save for autoharmony tracks - """ We have the solo information. Now we loop though each "solo" and: - 1. Ensure or Create a MMA track for the solo - 2. Push the solo data into a Riff for the given track. - """ - - for s, trk in zip(solo, autoSoloTracks): - MMA.alloc.trackAlloc(trk, 1) - gbl.tnames[trk].setRiff( s.strip() ) - - - """ After all the solo data is interpreted and sent to the - correct track, we check any leftover tracks. If any of these - tracks are empty of data AND are harmonyonly the note - data from the first track is interpeted again for that - track. Tricky: the max() is needed since harmonyonly can - have different setting for each bar...this way - the copy is done if ANY bar in the seq has harmonyonly set. + """ We have the solo information. Now we loop though each "solo" and: + 1. Ensure or Create a MMA track for the solo + 2. Push the solo data into a Riff for the given track. """ - for t in autoSoloTracks[1:]: - if gbl.tnames.has_key(t) and gbl.tnames[t].riff == [] \ - and max(gbl.tnames[t].harmonyOnly): - gbl.tnames[t].setRiff( firstSolo[:] ) + for s, trk in zip(solo, autoSoloTracks): + MMA.alloc.trackAlloc(trk, 1) + gbl.tnames[trk].setRiff( s.strip() ) - if gbl.debug: - print "%s duplicated to %s for HarmonyOnly." % (trk, t) - return ln + """ After all the solo data is interpreted and sent to the + correct track, we check any leftover tracks. If any of these + tracks are empty of data AND are harmonyonly the note + data from the first track is interpeted again for that + track. Tricky: the max() is needed since harmonyonly can + have different setting for each bar...this way + the copy is done if ANY bar in the seq has harmonyonly set. + """ + + for t in autoSoloTracks[1:]: + if gbl.tnames.has_key(t) and gbl.tnames[t].riff == [] \ + and max(gbl.tnames[t].harmonyOnly): + gbl.tnames[t].setRiff( firstSolo[:] ) + + if gbl.debug: + print "%s duplicated to %s for HarmonyOnly." % (trk, t) + + return ln diff --git a/mma/MMA/patWalk.py b/mma/MMA/patWalk.py index d026930..63fe4dc 100644 --- a/mma/MMA/patWalk.py +++ b/mma/MMA/patWalk.py @@ -2,7 +2,7 @@ # patWalk.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ @@ -34,131 +34,131 @@ from MMA.pat import PC class Walk(PC): - """ Pattern class for a walking bass track. """ + """ Pattern class for a walking bass track. """ - vtype = 'WALK' - walkChoice = 0 - - def getPgroup(self, ev): - """ Get group for walking bass pattern. - - Fields - start, length, volume - """ + vtype = 'WALK' + walkChoice = 0 - if len(ev) != 3: - error("There must be at exactly 3 items in each group in " - "a Walking Bass definition, not <%s>." % ' '.join(ev)) + def getPgroup(self, ev): + """ Get group for walking bass pattern. - a = struct() - - a.offset = self.setBarOffset(ev[0]) - a.duration = getNoteLen(ev[1]) - a.vol = stoi(ev[2], "Type error in Walking Bass definition") + Fields - start, length, volume + """ - return a - + if len(ev) != 3: + error("There must be at exactly 3 items in each group in " + "a Walking Bass definition, not <%s>" % ' '.join(ev)) - def restart(self): - self.ssvoice = -1 - self.walkChoice = 0 - - - def trackBar(self, pattern, ctable): - """ Do a waling bass bar. - - Called from self.bar() - - """ + a = struct() - sc=self.seq - dir = self.direction[sc] - unify = self.unify[sc] - - for p in pattern: - - tb = self.getChordInPos(p.offset, ctable) - - if tb.walkZ: - continue - - root = tb.chord.rootNote # root note of chord + a.offset = self.setBarOffset(ev[0]) + a.duration = getNoteLen(ev[1]) + a.vol = stoi(ev[2], "Type error in Walking Bass definition") - """ Create a note list from the current scale. We do - this for each beat, but it's pretty fast. The note - list is simply notes 0..6 of the scale PLUS notes - 1..5 reversed. So, a Cmajor chord would result in - the note list (0,2,4,5,7,9,7,5,4,2). - - Note that we deliberately skip the 7th. Too often - the chord is a Major but the melody note will be - the dom. 7th and the M7 will sound off. So, just - err on the side of caution. - - If DIR is UP or DOWN we don't append the 2nd half - of the scale. - - If DIR is DOWN we reverse the order as well. - """ - - wNotes = list(tb.chord.scaleList[0:6]) - if dir not in ('UP', 'DOWN'): - b = list(tb.chord.scaleList[1:5]) - b.reverse() - wNotes += b - - if dir == 'DOWN': - wNotes.reverse() - - - # Ensure that the offset is in range. - - if self.walkChoice >= len(wNotes) or self.walkChoice < 0: - self.walkChoice = 0 - - """ Even with a walking bass it's nice to have the chord root on - beat 1 ... not all the time, but most. This bit of code ensures - that more that 50% of beat ones will have the root. - """ - - - if p.offset == 0 and random.choice((0,1)): - self.walkChoice=0 - - note = wNotes[self.walkChoice] - - """ Adjust offset for NEXT TIME. If the direction is - up/down we just increment the pointer. If we have - direction set to RANDOM then we select either -1, - 0 or 1 with equal change for moving up, down or - not-at-all. With BOTH we have a preference to move up. - """ - - - if dir in ('UP', 'DOWN'): - self.walkChoice += 1 - elif dir == 'RANDOM': - self.walkChoice += random.choice((0,1,-1)) - else: # BOTH - self.walkChoice += random.choice( (-1,0,0,2,2,1,1,1,1,1,1,1)) - - - if not self.harmonyOnly[sc]: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(note), - self.adjustVolume(p.vol, p.offset) ) + return a - if self.harmony[sc]: - ch = self.getChordInPos(p.offset, ctable).chord.noteList - h = harmonize(self.harmony[sc], note, ch) - for n in h: - self.sendNote( - p.offset, - self.getDur(p.duration), - self.adjustNote(n), - self.adjustVolume(p.vol * self.harmonyVolume[sc], -1) ) + def restart(self): + self.ssvoice = -1 + self.walkChoice = 0 + + + def trackBar(self, pattern, ctable): + """ Do a waling bass bar. + + Called from self.bar() + + """ + + sc=self.seq + dir = self.direction[sc] + unify = self.unify[sc] + + for p in pattern: + + tb = self.getChordInPos(p.offset, ctable) + + if tb.walkZ: + continue + + root = tb.chord.rootNote # root note of chord + + """ Create a note list from the current scale. We do + this for each beat, but it's pretty fast. The note + list is simply notes 0..6 of the scale PLUS notes + 1..5 reversed. So, a Cmajor chord would result in + the note list (0,2,4,5,7,9,7,5,4,2). + + Note that we deliberately skip the 7th. Too often + the chord is a Major but the melody note will be + the dom. 7th and the M7 will sound off. So, just + err on the side of caution. + + If DIR is UP or DOWN we don't append the 2nd half + of the scale. + + If DIR is DOWN we reverse the order as well. + """ + + wNotes = list(tb.chord.scaleList[0:6]) + if dir not in ('UP', 'DOWN'): + b = list(tb.chord.scaleList[1:5]) + b.reverse() + wNotes += b + + if dir == 'DOWN': + wNotes.reverse() + + + # Ensure that the offset is in range. + + if self.walkChoice >= len(wNotes) or self.walkChoice < 0: + self.walkChoice = 0 + + """ Even with a walking bass it's nice to have the chord root on + beat 1 ... not all the time, but most. This bit of code ensures + that more that 50% of beat ones will have the root. + """ + + + if p.offset == 0 and random.choice((0,1)): + self.walkChoice=0 + + note = wNotes[self.walkChoice] + + """ Adjust offset for NEXT TIME. If the direction is + up/down we just increment the pointer. If we have + direction set to RANDOM then we select either -1, + 0 or 1 with equal change for moving up, down or + not-at-all. With BOTH we have a preference to move up. + """ + + + if dir in ('UP', 'DOWN'): + self.walkChoice += 1 + elif dir == 'RANDOM': + self.walkChoice += random.choice((0,1,-1)) + else: # BOTH + self.walkChoice += random.choice( (-1,0,0,2,2,1,1,1,1,1,1,1)) + + + if not self.harmonyOnly[sc]: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(note), + self.adjustVolume(p.vol, p.offset) ) + + + if self.harmony[sc]: + ch = self.getChordInPos(p.offset, ctable).chord.noteList + h = harmonize(self.harmony[sc], note, ch) + for n in h: + self.sendNote( + p.offset, + self.getDur(p.duration), + self.adjustNote(n), + self.adjustVolume(p.vol * self.harmonyVolume[sc], -1) ) diff --git a/mma/MMA/translate.py b/mma/MMA/translate.py index e1d3ffc..7f4534a 100644 --- a/mma/MMA/translate.py +++ b/mma/MMA/translate.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel This module handles voice name translations. @@ -32,114 +32,116 @@ from MMA.common import * """ Translation table for VOICE. This is ONLY used when a voice is set -from the VOICE command. If a translation exists the translation is -substituted. """ + from the VOICE command. If a translation exists the translation is + substituted. +""" class Vtable: - def __init__(self): - self.table = {} + def __init__(self): + self.table = {} - def retlist(self): + def retlist(self): - l=[] - for n in sorted(self.table.keys()): - l.append("%s=%s" % (n.title(), self.table[n])) + l=[] + for n in sorted(self.table.keys()): + l.append("%s=%s" % (n.title(), self.table[n])) - return ' '.join(l) + return ' '.join(l) - def set(self, ln): - """ Set a name/alias for voice translation, called from parser. """ + def set(self, ln): + """ Set a name/alias for voice translation, called from parser. """ - if not ln: - self.table = {} - if gbl.debug: - print "Voice Translaion table reset." + if not ln: + self.table = {} + if gbl.debug: + print "Voice Translaion table reset." - return + return - for l in ln: - l=l.upper() - if l.count('=') != 1: - error("Each translation pair must be in the format Voice=Alias") - v,a = l.split('=') - self.table[v] = a + for l in ln: + l=l.upper() + if l.count('=') != 1: + error("Each translation pair must be in the format Voice=Alias") + v,a = l.split('=') + self.table[v] = a - if gbl.debug: - print "Voice Translations: ", - for l in ln: - print l, - print + if gbl.debug: + print "Voice Translations: ", + for l in ln: + print l, + print - def get(self, name): - """ Return a translation or original. """ + def get(self, name): + """ Return a translation or original. """ - name=name.upper() - if self.table.has_key(name): - return self.table[name] + name=name.upper() + if self.table.has_key(name): + return self.table[name] - else: - return name + else: + return name -vtable=Vtable() # Create single class instance. +vtable=Vtable() # Create single class instance. """ This is just like the Vtable, but it is used for DRUM TONES. We use -this translation when a TONE is set for a drum in setTone() and when a -tone is selected in a Solo/Melody DRUM track. """ + this translation when a TONE is set for a drum in setTone() and when a + tone is selected in a Solo/Melody DRUM track. +""" class Dtable: - def __init__(self): - self.table = {} + def __init__(self): + self.table = {} - def retlist(self): + def retlist(self): - l=[] - for n in sorted(self.table.keys()): - l.append("%s=%s" % ( MMA.midiC.valueToDrum(n), - MMA.midiC.valueToDrum(self.table[n]))) + l=[] + for n in sorted(self.table.keys()): + l.append("%s=%s" % ( MMA.midiC.valueToDrum(n), + MMA.midiC.valueToDrum(self.table[n]))) - return ' '.join(l) + return ' '.join(l) - def set(self, ln): - """ Set a name/alias for drum tone translation, called from parser. """ + def set(self, ln): + """ Set a name/alias for drum tone translation, called from parser. """ - if not ln: - self.table = {} - if gbl.debug: - print "DrumTone Translaion table reset." + if not ln: + self.table = {} + if gbl.debug: + print "DrumTone Translaion table reset." - return + return - for l in ln: - l=l.upper() - if l.count('=') != 1: - error("Each translation pair must be in the format Voice=Alias") - v,a = l.split('=') + for l in ln: + l=l.upper() + if l.count('=') != 1: + error("Each translation pair must be in the format Voice=Alias") + v,a = l.split('=') - v=MMA.midiC.drumToValue(v) - a=MMA.midiC.drumToValue(a) + v=MMA.midiC.drumToValue(v) + a=MMA.midiC.drumToValue(a) - self.table[v] = a - if gbl.debug: - print "DrumTone Translation: %s=%s" % \ - (MMA.midiC.valueToDrum(v), MMA.midiC.valueToDrum(a)) + self.table[v] = a + if gbl.debug: + print "DrumTone Translation: %s=%s" % \ + (MMA.midiC.valueToDrum(v), MMA.midiC.valueToDrum(a)) - def get(self, name): - """ Return a translation or original. """ + def get(self, name): + """ Return a translation or original. """ - v=MMA.midiC.drumToValue(name) + v=MMA.midiC.drumToValue(name) - if self.table.has_key(v): - return self.table[v] + if self.table.has_key(v): + return self.table[v] - else: - return v + else: + return v @@ -147,105 +149,106 @@ dtable=Dtable() """ Volume adjustment. Again, similar to voice/tone translations, -but this is for the volume. The table creates a percentage adjustment -for tones/voices specified. When a TRACK VOLUME is set in -MMApat.setVolume() the routine checks here for an adjustment. """ + but this is for the volume. The table creates a percentage adjustment + for tones/voices specified. When a TRACK VOLUME is set in + MMApat.setVolume() the routine checks here for an adjustment. +""" class VoiceVolTable: - def __init__(self): - self.table = {} + def __init__(self): + self.table = {} - def retlist(self): - l=[] - for n in sorted(self.table.keys()): - l.append("%s=%s" % ( MMA.midiC.valueToInst(n), self.table[n])) + def retlist(self): + l=[] + for n in sorted(self.table.keys()): + l.append("%s=%s" % ( MMA.midiC.valueToInst(n), self.table[n])) - return ' '.join(l) + return ' '.join(l) - def set(self, ln): - """ Set a name/alias for voice volume adjustment, called from parser. """ + def set(self, ln): + """ Set a name/alias for voice volume adjustment, called from parser. """ - if not ln: - self.table = {} - if gbl.debug: - print "Voice Volume Adjustment table reset." + if not ln: + self.table = {} + if gbl.debug: + print "Voice Volume Adjustment table reset." - return + return - for l in ln: - l=l.upper() - if l.count('=') != 1: - error("Each translation pair must be in the format Voice=Ajustment") - v,a = l.split('=') + for l in ln: + l=l.upper() + if l.count('=') != 1: + error("Each translation pair must be in the format Voice=Ajustment") + v,a = l.split('=') - v=MMA.midiC.instToValue(v) - a=stoi(a) - if a<1 or a>200: - error("Voice volume adjustments must be in range 1 to 200, not %." % a) - self.table[v] = a/100. - if gbl.debug: - print "Voice Volume Adjustment: %s=%s" % (MMA.midiC.valueToInst(v), a) + v=MMA.midiC.instToValue(v) + a=stoi(a) + if a<1 or a>200: + error("Voice volume adjustments must be in range 1 to 200, not %s" % a) + self.table[v] = a/100. + if gbl.debug: + print "Voice Volume Adjustment: %s=%s" % (MMA.midiC.valueToInst(v), a) - def get(self, v, vol): - """ Return an adjusted value or original. """ + def get(self, v, vol): + """ Return an adjusted value or original. """ - if self.table.has_key(v): - vol = int(vol * self.table[v]) + if self.table.has_key(v): + vol = int(vol * self.table[v]) - return vol + return vol voiceVolTable=VoiceVolTable() class DrumVolTable: - def __init__(self): - self.table = {} + def __init__(self): + self.table = {} - def retlist(self): + def retlist(self): - l=[] - for n in sorted(self.table.keys()): - l.append("%s=%s" % ( MMA.midiC.valueToDrum(n), self.table[n])) + l=[] + for n in sorted(self.table.keys()): + l.append("%s=%s" % ( MMA.midiC.valueToDrum(n), self.table[n])) - return ' '.join(l) + return ' '.join(l) - def set(self, ln): - """ Set a name/alias for voice volume adjustment, called from parser. """ + def set(self, ln): + """ Set a name/alias for voice volume adjustment, called from parser. """ - if not ln: - self.table = {} - if gbl.debug: - print "Drum Volume Adjustment table reset." + if not ln: + self.table = {} + if gbl.debug: + print "Drum Volume Adjustment table reset." - return + return - for l in ln: - l=l.upper() - if l.count('=') != 1: - error("Each translation pair must be in the format Drum=Ajustment") - v,a = l.split('=') + for l in ln: + l=l.upper() + if l.count('=') != 1: + error("Each translation pair must be in the format Drum=Ajustment") + v,a = l.split('=') - v=MMA.midiC.instToValue(v) - a=stoi(a) - if a<1 or a>200: - error("Drum volume adjustments must be in range 1 to 200, not %." % a) - self.table[v] = a/100. - if gbl.debug: - print "Drum Volume Adjustment: %s=%s" % (MMA.midiC.valueToDrum(v), a) + v=MMA.midiC.instToValue(v) + a=stoi(a) + if a<1 or a>200: + error("Drum volume adjustments must be in range 1 to 200, not %s" % a) + self.table[v] = a/100. + if gbl.debug: + print "Drum Volume Adjustment: %s=%s" % (MMA.midiC.valueToDrum(v), a) - def get(self, v, vol): - """ Return an adjusted value or original. """ + def get(self, v, vol): + """ Return an adjusted value or original. """ - if self.table.has_key(v): - vol = int(vol * self.table[v]) + if self.table.has_key(v): + vol = int(vol * self.table[v]) - return vol + return vol drumVolTable=DrumVolTable() diff --git a/mma/MMA/volume.py b/mma/MMA/volume.py index 7a90c8b..3b3dbda 100644 --- a/mma/MMA/volume.py +++ b/mma/MMA/volume.py @@ -2,7 +2,7 @@ # volume.py """ -This module is an integeral part of the program +This module is an integeral part of the program MMA - Musical Midi Accompaniment. This program is free software; you can redistribute it and/or modify @@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel - +Bob van der Poel + """ from MMA.common import * @@ -28,20 +28,20 @@ from MMA.common import * """ Volumes are specified in musical terms, but converted to midi velocities. This table has a list of percentage changes - to apply to the current volume. Used in both track and global - situations. Note that the volume for 'ffff' is 200%--this will - most likely generate velocities outside the midi range of 0..127. - But that's fine since mma will adjust volumes into the valid - range. Using very high percentages will ensure that 'ffff' notes - are (most likely) sounded with a maximum velocity. + to apply to the current volume. Used in both track and global + situations. Note that the volume for 'ffff' is 200%--this will + most likely generate velocities outside the midi range of 0..127. + But that's fine since mma will adjust volumes into the valid + range. Using very high percentages will ensure that 'ffff' notes + are (most likely) sounded with a maximum velocity. """ vols={ 'OFF': 0.00, 'PPPP': 0.05, 'PPP': 0.10, 'PP': 0.25, 'P': 0.40, 'MP': 0.70, - 'M': 1.00, 'MF': 1.10, 'F': 1.30, - 'FF': 1.60, 'FFF': 1.80, 'FFFF': 2.00 } + 'M': 1.00, 'MF': 1.10, 'F': 1.30, + 'FF': 1.60, 'FFF': 1.80, 'FFFF': 2.00 } -volume = vols['M'] # default global volume +volume = vols['M'] # default global volume lastVolume = volume futureVol = [] vTRatio = .6 @@ -49,158 +49,160 @@ vMRatio = 1-vTRatio def adjvolume(ln): - """ Adjust the ratio used in the volume table and track/global ratio. """ + """ Adjust the ratio used in the volume table and track/global ratio. """ - global vols, vTRatio, vMRatio - - if not ln: - error("Use: AdjustVolume DYN=RATIO [..].") + global vols, vTRatio, vMRatio - for l in ln: + if not ln: + error("Use: AdjustVolume DYN=RATIO [..]") - try: - v,r = l.split('=') - except: - error("AdjustVolume expecting DYN=RATIO pair, not '%s'." % l) - - v=v.upper() + for l in ln: - if v == 'RATIO': + try: + v,r = l.split('=') + except: + error("AdjustVolume expecting DYN=RATIO pair, not '%s'" % l) - r=stof(r) + v=v.upper() - if r<0 or r>100: - error("VolumeRatio must be value 0 to 100.") + if v == 'RATIO': - vTRatio = r/100 - vMRatio = 1-vTRatio + r=stof(r) - elif v in vols: - vols[v] = calcVolume(r, vols[v]) - - else: - error("Dynamic '%s' for AdjustVolume is unknown." % v ) - + if r<0 or r>100: + error("VolumeRatio must be value 0 to 100") + + vTRatio = r/100 + vMRatio = 1-vTRatio + + elif v in vols: + vols[v] = calcVolume(r, vols[v]) + + else: + error("Dynamic '%s' for AdjustVolume is unknown" % v ) - if gbl.debug: - print "Volume Ratio: %s%% Track / %s%% Master" % ( vTRatio * 100, vMRatio * 100) - print "Volume table:", - for a in vols: - print "%s=%s" % (a, int(vols[a] * 100)), - print - + if gbl.debug: + print "Volume Ratio: %s%% Track / %s%% Master" % ( vTRatio * 100, vMRatio * 100) + print "Volume table:", + for a in vols: + print "%s=%s" % (a, int(vols[a] * 100)), + print + + def calcVolume(new, old): - """ Calculate a new volume "new" possibly adjusting from "old". """ + """ Calculate a new volume "new" possibly adjusting from "old". """ - if new[0] == '-' or new[0] == '+': - a = stoi(new, "Volume expecting value for %% adjustment, not %s." % new) - v = old + (old * a/100.) + if new[0] == '-' or new[0] == '+': + a = stoi(new, "Volume expecting value for %% adjustment, not %s" % new) + v = old + (old * a/100.) - elif new[0] in "0123456789": - v = stoi(new, "Volume expecting value, not '%s'" % new) / 100. - - else: - new = new.upper() - - adj = None - - if '+' in new: - new,adj = new.split('+') - elif '-' in new: - new,adj = new.split('-') - adj = '-' + adj + elif new[0] in "0123456789": + v = stoi(new, "Volume expecting value, not '%s'" % new) / 100. - if not new in vols: - error("Unknown volume '%s'." % new) + else: + new = new.upper() - v=vols[new] + adj = None - if adj: - a = stoi(adj, "Volume expecting adjustment value, not %s." % adj) - v += (v * (a/100.)) + if '+' in new: + new,adj = new.split('+') + elif '-' in new: + new,adj = new.split('-') + adj = '-' + adj - return v + if not new in vols: + error("Unknown volume '%s'" % new) + + v=vols[new] + + if adj: + a = stoi(adj, "Volume expecting adjustment value, not %s" % adj) + v += (v * (a/100.)) + + return v def setVolume(ln): - """ Set master volume. """ + """ Set master volume. """ - global volume, lastVolume - - lastVolume = volume - - if len(ln) != 1: - error ("Use: Volume DYNAMIC.") + global volume, lastVolume - volume = calcVolume(ln[0], volume) - - if gbl.debug: - print "Volume: %s%%" % volume + lastVolume = volume + + if len(ln) != 1: + error ("Use: Volume DYNAMIC") + + volume = calcVolume(ln[0], volume) + + if gbl.debug: + print "Volume: %s%%" % volume # The next 2 are called from the parser. def setCresc(ln): - setCrescendo(1, ln) + setCrescendo(1, ln) def setDecresc(ln): - setCrescendo(-1, ln) - + setCrescendo(-1, ln) + def setCrescendo(dir, ln): - """ Combined (de)cresc() """ - - global futureVol, volume, lastVolume + """ Combined (de)cresc() """ - lastVolume = volume + global futureVol, volume, lastVolume - if len(ln) == 3: - setVolume([ln[0]]) - ln=ln[1:] + lastVolume = volume - - futureVol = fvolume(dir, volume, ln) + if len(ln) not in (2, 3): + error("Usage: (De)Cresc [start-Dynamic] final-Dynamic bar-count") + + if len(ln) == 3: + setVolume([ln[0]]) + ln=ln[1:] + + futureVol = fvolume(dir, volume, ln) # Used by both the 2 funcs above and from TRACK.setCresc() def fvolume(dir, startvol, ln): - """ Create a list of future vols. Called by (De)Cresc. """ + """ Create a list of future vols. Called by (De)Cresc. """ - # Get destination volume - - destvol = calcVolume(ln[0], startvol) + # Get destination volume - bcount = stoi(ln[1], "Type error in bar count for (De)Cresc, '%s'." % ln[1] ) - - if bcount <= 0: - error("Bar count for (De)Cresc must be postive.") - - if dir > 0 and destvol < startvol: - warning("Cresc volume less than current setting. " ) - - elif dir < 0 and destvol > startvol: - warning("Decresc volume greater than current setting. " ) - - elif destvol == startvol: - warning("(De)Cresc volume equal to current setting. " ) + destvol = calcVolume(ln[0], startvol) - bcount -= 1 - step = ( destvol-startvol ) / bcount + bcount = stoi(ln[1], "Type error in bar count for (De)Cresc, '%s'" % ln[1] ) - volList=[startvol] - - for a in range(bcount-1): - startvol += step - volList.append( startvol) - - volList.append(destvol) + if bcount <= 0: + error("Bar count for (De)Cresc must be postive") + + if dir > 0 and destvol < startvol: + warning("Cresc volume less than current setting" ) + + elif dir < 0 and destvol > startvol: + warning("Decresc volume greater than current setting" ) + + elif destvol == startvol: + warning("(De)Cresc volume equal to current setting" ) + + bcount -= 1 + step = ( destvol-startvol ) / bcount + + volList=[startvol] + + for a in range(bcount-1): + startvol += step + volList.append( startvol) + + volList.append(destvol) + + return volList - return volList - diff --git a/mma/cp-install b/mma/cp-install index 00dac7c..3ef1840 100755 --- a/mma/cp-install +++ b/mma/cp-install @@ -15,15 +15,40 @@ def okay(msg): # Simple python script to install mma from tarball # This should be fixed to be more versatile. Volunteers? -########################################### -####### Banner, get destination +# Before we do anything, make sure we have an up-to-date python. + +pyMaj=2 +pyMin=4 + +if sys.version_info[0] < pyMaj or sys.version_info[1] < pyMin: + print + print "You need a more current version of Python to run MMA and this install script." + print "We're looking for something equal or greater than version %s.%s" % \ + (pyMaj,pyMin) + print "Current Python version is ", sys.version + print + sys.exit(0) + + +# Banner. Check to make sure user has root permissions. print """ This script will install mma, the standard library and the python modules. +""" -YOU WILL NEED TO BE LOGGED IN AS ROOT TO CONTINUE! +try: + u=os.getuid() +except: + u=1 +if u: + okay("""You do not appear to be running this script as 'root' user. +Continuing will probably cause all kinds of strange errors +and a generally unsatisfactory experience. But, we can try... +""") + +print """ We recommend that you install the package with this script in the default locations. This script will create a directory 'mma' in /usr/local/share. If this isn't @@ -48,6 +73,7 @@ bin='/usr/local/bin/mma' if os.path.exists(bin): okay("Existing mma executable '%s' is being overwritten." % bin) + os.remove(bin) print "Copying mma to", bin diff --git a/mma/docs/html/lib/index.html b/mma/docs/html/lib/index.html index c62d1fe..4371f88 100644 --- a/mma/docs/html/lib/index.html +++ b/mma/docs/html/lib/index.html @@ -48,15 +48,17 @@ information from the each library file:
  • The file description from the "Doc Note" directive. +
  • Any user variables documented in "DocVar" directives. +
  • Each groove description: This is the optional text following a DefGroove directive. -
      -
    • The sequence size. This is extracted from the current groove +
        +
      • The sequence size. This is extracted from the current groove information and was set with the SeqSize directive. It is displayed in a small box after the groove description. -
      • A "summary" of the voices used in the groove. Note that a +
      • A "summary" of the voices used in the groove. Note that a different voice or MIDI note is possible for each bar in the sequence size; however, this listing only lists the selection for the first bar. @@ -65,86 +67,99 @@ information from the each library file:

      If you find that you don't have some of the grooves listed below in your distribution - you need to run the program mklibdoc.py to update these docs. Not all style files are - distributed in the default MMA distribution. + you need to run the program mklibdoc.py to update these docs. Not all style files are + distributed in the default MMA distribution.


      Index


      These grooves can be used from a program just by using their name.

      +
    • Kara

    • +
    • Yamaha


    These grooves can be used from a program just by using their name.

    Stdlib

    Use the following grooves with a "use" directive.

    Kara

    + +

    Yamaha

    +

    @@ -153,4 +168,4 @@ information from the each library file:

    It is a part of the MMA distribution and is protected by the same copyrights as MMA (the GNU General Public License). -

    Created: Sun Oct 15 11:26:36 2006 \ No newline at end of file +

    Created: Wed Mar 7 11:50:18 2007 \ No newline at end of file diff --git a/mma/docs/html/lib/kara/K50s_rock.html b/mma/docs/html/lib/kara/K50s_rock.html index f650e68..c6bc689 100644 --- a/mma/docs/html/lib/kara/K50s_rock.html +++ b/mma/docs/html/lib/kara/K50s_rock.html @@ -1,4 +1,4 @@ - +

    K50S_Rock

    @@ -21,7 +21,6 @@
  • 50sFill-In-DD -

    50sMain-A

    @@ -39,7 +38,6 @@
    -

    50sFill-In-AA

    @@ -57,7 +55,6 @@
    -

    50sIntro-A

    @@ -75,7 +72,6 @@
    -

    50sEnding-A

    @@ -96,7 +92,6 @@
    -

    50sMain-B

    @@ -114,7 +109,6 @@
    -

    50sFill-In-BB

    @@ -133,7 +127,6 @@
    -

    50sFill-In-BA

    @@ -152,7 +145,6 @@
    -

    50sIntro-B

    @@ -171,7 +163,6 @@
    -

    50sEnding-B

    @@ -193,7 +184,6 @@
    -

    50sMain-C

    @@ -212,7 +202,6 @@
    -

    50sFill-In-CC

    @@ -232,7 +221,6 @@
    -

    50sIntro-C

    @@ -251,7 +239,6 @@
    -

    50sEnding-C

    @@ -273,7 +260,6 @@
    -

    50sMain-D

    @@ -291,7 +277,6 @@
    -

    50sFill-In-DD

    diff --git a/mma/docs/html/lib/kara/Kfunk1.html b/mma/docs/html/lib/kara/Kfunk1.html index 7901c9f..0892daf 100644 --- a/mma/docs/html/lib/kara/Kfunk1.html +++ b/mma/docs/html/lib/kara/Kfunk1.html @@ -1,4 +1,4 @@ - +

    Kfunk1

    @@ -14,7 +14,6 @@
  • Ending-A -

    Main-A

    @@ -35,7 +34,6 @@
    -

    Fill-In-AA

    @@ -57,7 +55,6 @@
    -

    Fill-In-AB

    @@ -80,7 +77,6 @@
    -

    Main-B

    @@ -104,7 +100,6 @@
    -

    Fill-In-BA

    @@ -130,7 +125,6 @@
    -

    Fill-In-BB

    @@ -155,7 +149,6 @@
    -

    Intro-A

    @@ -179,7 +172,6 @@
    -

    Ending-A

    diff --git a/mma/docs/html/lib/kara/twi.html b/mma/docs/html/lib/kara/twi.html index 12a0ee3..fdf94e3 100644 --- a/mma/docs/html/lib/kara/twi.html +++ b/mma/docs/html/lib/kara/twi.html @@ -1,4 +1,4 @@ - +

    Twi

    @@ -14,7 +14,6 @@
  • Ending-B -

    Main-A

    @@ -32,7 +31,6 @@
    -

    Fill-In-AA

    @@ -51,7 +49,6 @@
    -

    Fill-In-AB

    @@ -73,7 +70,6 @@
    -

    Main-B

    @@ -94,7 +90,6 @@
    -

    Fill-In-BA

    @@ -116,7 +111,6 @@
    -

    Fill-In-BB

    @@ -136,7 +130,6 @@
    -

    Intro-B

    @@ -155,7 +148,6 @@
    -

    Ending-B

    diff --git a/mma/docs/html/lib/stdlib/50srock.html b/mma/docs/html/lib/stdlib/50srock.html index 2ec6157..bcb1bd6 100644 --- a/mma/docs/html/lib/stdlib/50srock.html +++ b/mma/docs/html/lib/stdlib/50srock.html @@ -1,4 +1,4 @@ - +

    50Srock

    @@ -12,7 +12,6 @@
  • 50sRockEnd -

    50sRock

    @@ -32,7 +31,6 @@
    -

    50sRockSus

    @@ -53,7 +51,6 @@
    -

    50sRock1

    @@ -73,7 +70,6 @@
    -

    50sRock1Sus

    @@ -94,7 +90,6 @@
    -

    50sRockIntro

    @@ -114,7 +109,6 @@
    -

    50sRockEnd

    diff --git a/mma/docs/html/lib/stdlib/60srock.html b/mma/docs/html/lib/stdlib/60srock.html index 8f6733e..d214503 100644 --- a/mma/docs/html/lib/stdlib/60srock.html +++ b/mma/docs/html/lib/stdlib/60srock.html @@ -1,4 +1,4 @@ - +

    60Srock

    @@ -11,7 +11,6 @@
  • 60sRockEnd -

    60sRock

    @@ -30,7 +29,6 @@
    -

    60sRock1

    @@ -48,7 +46,6 @@
    -

    60sRockSus

    @@ -68,7 +65,6 @@
    -

    60sRock1Sus

    @@ -87,7 +83,6 @@
    -

    60sRockEnd

    diff --git a/mma/docs/html/lib/stdlib/8beat.html b/mma/docs/html/lib/stdlib/8beat.html index 177c010..b4f1355 100644 --- a/mma/docs/html/lib/stdlib/8beat.html +++ b/mma/docs/html/lib/stdlib/8beat.html @@ -1,4 +1,4 @@ - +

    8Beat

    @@ -8,10 +8,10 @@
  • 8BeatSus
  • 8Beat1
  • 8Beat1Sus +
  • 8BeatIntro
  • 8BeatEnd -

    8Beat

    @@ -30,7 +30,6 @@
    -

    8BeatSus

    @@ -50,7 +49,6 @@
    -

    8Beat1

    @@ -70,7 +68,6 @@
    -

    8Beat1Sus

    @@ -90,8 +87,25 @@

  • + + + + +
    +

    8BeatIntro

    + Straight-ahead four bar introduction. (4) +
    + + + + + + + + +
    Bass FingeredBass
    Chord Honky-TonkPiano
    Chord-Guitar CleanGuitar
    Drum-Chh ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Ohh OpenHiHat
    Drum-Snare SnareDrum1
    +
    -

    8BeatEnd

    diff --git a/mma/docs/html/lib/stdlib/ballad.html b/mma/docs/html/lib/stdlib/ballad.html index 632def5..2fd9ed1 100644 --- a/mma/docs/html/lib/stdlib/ballad.html +++ b/mma/docs/html/lib/stdlib/ballad.html @@ -1,4 +1,4 @@ - +

    Ballad

    @@ -12,9 +12,9 @@
  • BalladIntro1
  • BalladIntro2
  • BalladEnd +
  • Ballad1End -

    Ballad

    @@ -40,7 +40,6 @@
    -

    BalladSus

    @@ -67,7 +66,6 @@
    -

    Ballad1

    @@ -93,7 +91,6 @@
    -

    Ballad1Sus

    @@ -120,7 +117,6 @@
    -

    BalladIntro

    @@ -142,7 +138,6 @@
    -

    BalladIntro1

    @@ -163,7 +158,6 @@
    -

    BalladIntro2

    @@ -185,7 +179,6 @@
    -

    BalladEnd

    @@ -210,5 +203,30 @@

  • + + + + +
    +

    Ballad1End

    + A simpler 4 bar ending. We still have a harp, but it's doing quarter note arpeggios. (4) +
    + + + + + + + + + + + + + + + +
    Arpeggio OrchestralHarp
    Bass FretlessBass
    Chord Atmosphere
    Drum-Bongo LowBongo
    Drum-Cabasa Cabasa
    Drum-Cym RideCymbal1
    Drum-Hh PedalHiHat
    Drum-Hiconga MuteHighConga
    Drum-Kick KickDrum1
    Drum-Loconga LowConga
    Drum-Mutetri MuteTriangle
    Drum-Opentri OpenTriangle
    Drum-Shake Shaker
    Drum-Tamb Tambourine
    +
    diff --git a/mma/docs/html/lib/stdlib/ballad128.html b/mma/docs/html/lib/stdlib/ballad128.html new file mode 100644 index 0000000..be13e34 --- /dev/null +++ b/mma/docs/html/lib/stdlib/ballad128.html @@ -0,0 +1,113 @@ + + + +

    Ballad128

    +

    A 12/8 Ballad. Written for "Memory" This is written in 4/4, so, when figuring tempo use a dotted quarter for the beat count. +

    + + + + +
    +

    Ballad128

    + A very simple, relaxed 12/8 ballad pattern. (4) +
    + + + + + + +
    Bass AcousticBass
    Chord OrchestralHarp
    Drum-Kick SideKick
    Drum-Snare SnareDrum2
    Walk AcousticBass
    +
    + + + + +
    +

    Ballad128Plus

    + Adds arpeggiated . (4) +
    + + + + + + + +
    Arpeggio Piano1
    Bass AcousticBass
    Chord OrchestralHarp
    Drum-Kick SideKick
    Drum-Snare SnareDrum2
    Walk AcousticBass
    +
    + + + + +
    +

    Ballad128Sus

    + Add in sustained TremoloStrings (4) +
    + + + + + + + +
    Bass AcousticBass
    Chord OrchestralHarp
    Chord-Sus TremoloStrings
    Drum-Kick SideKick
    Drum-Snare SnareDrum2
    Walk AcousticBass
    +
    + + + + +
    +

    Ballad128SusPlus

    + Sustained strings and apreggiating piano. (4) +
    + + + + + + + + +
    Arpeggio Piano1
    Bass AcousticBass
    Chord OrchestralHarp
    Chord-Sus TremoloStrings
    Drum-Kick SideKick
    Drum-Snare SnareDrum2
    Walk AcousticBass
    +
    + + + + +
    +

    Ballad128Intro

    + This 4 bar intro plays bass notes and harp arpeggios. It pretty much assumes a 7th chord on the 4th bar. (4) +
    + + + + + +
    Arpeggio OrchestralHarp
    Bass AcousticBass
    Bass-Intro OrchestralHarp
    Walk AcousticBass
    +
    + + + + +
    +

    Ballad128End

    + A 2 bar ending. (2) +
    + + + + + +
    Bass AcousticBass
    Chord OrchestralHarp
    Drum-Kick SideKick
    Drum-Snare SnareDrum2
    +
    + + diff --git a/mma/docs/html/lib/stdlib/basicrock.html b/mma/docs/html/lib/stdlib/basicrock.html index a3bd670..0a918f9 100644 --- a/mma/docs/html/lib/stdlib/basicrock.html +++ b/mma/docs/html/lib/stdlib/basicrock.html @@ -1,4 +1,4 @@ - +

    Basicrock

    @@ -11,7 +11,6 @@
  • BasicRockEnd -

    BasicRock

    @@ -31,7 +30,6 @@
    -

    BasicRockSus

    @@ -52,7 +50,6 @@
    -

    BasicRock4

    @@ -71,7 +68,6 @@
    -

    BasicRock4Sus

    @@ -91,7 +87,6 @@
    -

    BasicRockEnd

    diff --git a/mma/docs/html/lib/stdlib/beguine.html b/mma/docs/html/lib/stdlib/beguine.html index a73bb9e..5f092a1 100644 --- a/mma/docs/html/lib/stdlib/beguine.html +++ b/mma/docs/html/lib/stdlib/beguine.html @@ -1,4 +1,4 @@ - +

    Beguine

    @@ -11,9 +11,9 @@
  • BeguineFill
  • BeguineIntro
  • BeguineEnd +
  • Beguine2End -

    Beguine

    @@ -35,7 +35,6 @@
    -

    BeguineSus

    @@ -58,7 +57,6 @@
    -

    Beguine1

    @@ -81,7 +79,6 @@
    -

    Beguine1Sus

    @@ -105,7 +102,6 @@
    -

    BeguineFill

    @@ -127,7 +123,6 @@
    -

    BeguineIntro

    @@ -149,7 +144,6 @@
    -

    BeguineEnd

    @@ -171,5 +165,25 @@

  • + + + + +
    +

    Beguine2End

    + A more abrupt 2 bar ending. (2) +
    + + + + + + + + + + +
    Bass FretlessBass
    Chord Piano2
    Drum Claves
    Drum-Hconga MuteHighConga
    Drum-Hh ClosedHiHat
    Drum-Lconga LowConga
    Drum-Maraca Maracas
    Drum-Toms1 MidTom1
    Drum-Toms2 MidTom2
    +
    diff --git a/mma/docs/html/lib/stdlib/bigband.html b/mma/docs/html/lib/stdlib/bigband.html index f909e35..fca82af 100644 --- a/mma/docs/html/lib/stdlib/bigband.html +++ b/mma/docs/html/lib/stdlib/bigband.html @@ -1,4 +1,4 @@ - +

    Bigband

    @@ -13,6 +13,7 @@
  • BigBand8
  • BigBand8Sus
  • BigBandFill +
  • BigBand1Fill
  • BigBandIntro
  • BigBandEnd
  • BigBand1End @@ -20,7 +21,6 @@
  • BigBand4End -

    BigBand

    @@ -39,7 +39,6 @@
    -

    BigBandSus

    @@ -58,7 +57,6 @@
    -

    BigBandPlus

    @@ -78,7 +76,6 @@
    -

    BigBandSusPlus

    @@ -98,7 +95,6 @@
    -

    BigBand1

    @@ -118,7 +114,6 @@
    -

    BigBand1Sus

    @@ -139,7 +134,6 @@
    -

    BigBand8

    @@ -159,7 +153,6 @@
    -

    BigBand8Sus

    @@ -180,7 +173,6 @@
    -

    BigBandFill

    @@ -196,8 +188,25 @@

  • + + + + +
    +

    BigBand1Fill

    + Louder, 4 in the bar fill. (1) +
    + + + + + + + + +
    Bass AcousticBass
    Chord Trombone
    Chord-Hits1 MutedTrumpet
    Drum-Hh OpenHiHat
    Drum-Kick KickDrum1
    Drum-Ride RideCymbal1
    Drum-Snare SnareDrum1
    +
    -

    BigBandIntro

    @@ -216,7 +225,6 @@
    -

    BigBandEnd

    @@ -234,7 +242,6 @@
    -

    BigBand1End

    @@ -253,7 +260,6 @@
    -

    BigBand2End

    @@ -272,7 +278,6 @@
    -

    BigBand4End

    diff --git a/mma/docs/html/lib/stdlib/bluegrass.html b/mma/docs/html/lib/stdlib/bluegrass.html index 4c9a2fd..4b66cb2 100644 --- a/mma/docs/html/lib/stdlib/bluegrass.html +++ b/mma/docs/html/lib/stdlib/bluegrass.html @@ -1,4 +1,4 @@ - +

    Bluegrass

    @@ -12,7 +12,6 @@
  • BlueGrassEnd -

    BlueGrass

    @@ -30,7 +29,6 @@
    -

    BlueGrassClap

    @@ -49,7 +47,6 @@
    -

    BlueGrassBottle

    @@ -69,7 +66,6 @@
    -

    BlueGrassBottleClap

    @@ -89,7 +85,6 @@
    -

    BlueGrassSus

    @@ -108,7 +103,6 @@
    -

    BlueGrassEnd

    diff --git a/mma/docs/html/lib/stdlib/blues.html b/mma/docs/html/lib/stdlib/blues.html index 9e2021a..57b13e9 100644 --- a/mma/docs/html/lib/stdlib/blues.html +++ b/mma/docs/html/lib/stdlib/blues.html @@ -1,4 +1,4 @@ - +

    Blues

    @@ -14,7 +14,6 @@
  • BluesEnd -

    Blues

    @@ -32,7 +31,6 @@
    -

    BluesTriple

    @@ -50,7 +48,6 @@
    -

    BluesSus

    @@ -69,7 +66,6 @@
    -

    BluesTripleSus

    @@ -88,7 +84,6 @@
    -

    Blues1

    @@ -107,7 +102,6 @@
    -

    Blues1Sus

    @@ -127,7 +121,6 @@
    -

    BluesIntro

    @@ -145,7 +138,6 @@
    -

    BluesEnd

    diff --git a/mma/docs/html/lib/stdlib/boggiewoggie.html b/mma/docs/html/lib/stdlib/boggiewoggie.html index 92235fe..22867c1 100644 --- a/mma/docs/html/lib/stdlib/boggiewoggie.html +++ b/mma/docs/html/lib/stdlib/boggiewoggie.html @@ -1,4 +1,4 @@ - +

    Boggiewoggie

    @@ -11,7 +11,6 @@
  • BoggieWoggieEnd -

    BoggieWoggie

    @@ -25,7 +24,6 @@
    -

    BoggieWoggie1

    @@ -39,7 +37,6 @@
    -

    BoggieWoggie2

    @@ -53,7 +50,6 @@
    -

    BoggieWoggie3

    @@ -67,7 +63,6 @@
    -

    BoggieWoggieEnd

    diff --git a/mma/docs/html/lib/stdlib/bolero.html b/mma/docs/html/lib/stdlib/bolero.html index cc7cdee..2fa2af5 100644 --- a/mma/docs/html/lib/stdlib/bolero.html +++ b/mma/docs/html/lib/stdlib/bolero.html @@ -1,4 +1,4 @@ - +

    Bolero

    @@ -18,7 +18,6 @@
  • Bolero1End -

    Bolero

    @@ -38,7 +37,6 @@
    -

    BoleroFill

    @@ -59,7 +57,6 @@
    -

    BoleroSus

    @@ -80,7 +77,6 @@
    -

    BoleroSusFill

    @@ -102,7 +98,6 @@
    -

    BoleroIntro

    @@ -122,7 +117,6 @@
    -

    BoleroEnd

    @@ -143,7 +137,6 @@
    -

    Bolero1

    @@ -161,7 +154,6 @@
    -

    Bolero1Fill

    @@ -180,7 +172,6 @@
    -

    Bolero1Sus

    @@ -199,7 +190,6 @@
    -

    Bolero1SusFill

    @@ -219,7 +209,6 @@
    -

    Bolero1Intro

    @@ -237,7 +226,6 @@
    -

    Bolero1End

    diff --git a/mma/docs/html/lib/stdlib/bossanova.html b/mma/docs/html/lib/stdlib/bossanova.html index 6011cb8..389c380 100644 --- a/mma/docs/html/lib/stdlib/bossanova.html +++ b/mma/docs/html/lib/stdlib/bossanova.html @@ -1,4 +1,4 @@ - +

    Bossanova

    @@ -7,6 +7,8 @@
  • BossaNova
  • BossaNovaSus
  • BossaNova1Sus +
  • BossaNova2Sus +
  • BossaNova3Sus
  • BossaNovaFill
  • BossaNovaIntro
  • BossaNovaIntro8 @@ -15,7 +17,6 @@
  • BossaNova2End -

    BossaNova

    @@ -38,7 +39,6 @@
    -

    BossaNovaSus

    @@ -62,7 +62,6 @@
    -

    BossaNova1Sus

    @@ -85,8 +84,54 @@

  • + + + + +
    +

    BossaNova2Sus

    + Basic Bossa with decending string pattern. (4) +
    + + + + + + + + + + + + + +
    Bass JazzGuitar
    Bass-Sus Strings
    Chord JazzGuitar
    Drum Cabasa
    Drum-Chh ClosedHiHat
    Drum-Clave Claves
    Drum-Kick KickDrum2
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Muteconga MuteHighConga
    Drum-Openhiconga OpenHighConga
    Drum-Sidekick SideKick
    +
    + + + + +
    +

    BossaNova3Sus

    + A combination of BossaNova1Sus and BossaNova2Sus. Alternating bars of decending strings with full chords. (4) +
    + + + + + + + + + + + + + + +
    Bass JazzGuitar
    Bass-Sus Strings
    Chord JazzGuitar
    Chord-Sus Strings
    Drum Cabasa
    Drum-Chh ClosedHiHat
    Drum-Clave Claves
    Drum-Kick KickDrum2
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Muteconga MuteHighConga
    Drum-Openhiconga OpenHighConga
    Drum-Sidekick SideKick
    +
    -

    BossaNovaFill

    @@ -110,7 +155,6 @@
    -

    BossaNovaIntro

    @@ -133,7 +177,6 @@
    -

    BossaNovaIntro8

    @@ -156,7 +199,6 @@
    -

    BossaNovaEnd

    @@ -180,7 +222,6 @@
    -

    BossaNova1End

    @@ -205,7 +246,6 @@
    -

    BossaNova2End

    diff --git a/mma/docs/html/lib/stdlib/broadway.html b/mma/docs/html/lib/stdlib/broadway.html index 86581f2..660778e 100644 --- a/mma/docs/html/lib/stdlib/broadway.html +++ b/mma/docs/html/lib/stdlib/broadway.html @@ -1,4 +1,4 @@ - +

    Broadway

    @@ -12,7 +12,6 @@
  • BroadWayEnd -

    Broadway

    @@ -32,7 +31,6 @@
    -

    Broadway1

    @@ -53,7 +51,6 @@
    -

    BroadwaySus

    @@ -74,7 +71,6 @@
    -

    Broadway1Sus

    @@ -96,7 +92,6 @@
    -

    BroadwayIntro

    @@ -116,7 +111,6 @@
    -

    BroadWayEnd

    diff --git a/mma/docs/html/lib/stdlib/calypso.html b/mma/docs/html/lib/stdlib/calypso.html index f5bc691..057db9b 100644 --- a/mma/docs/html/lib/stdlib/calypso.html +++ b/mma/docs/html/lib/stdlib/calypso.html @@ -1,4 +1,4 @@ - +

    Calypso

    @@ -11,7 +11,6 @@
  • CalypsoEnd -

    Calypso

    @@ -28,7 +27,6 @@
    -

    CalypsoSus

    @@ -46,7 +44,6 @@
    -

    Calypso1

    @@ -63,7 +60,6 @@
    -

    Calypso1Sus

    @@ -81,7 +77,6 @@
    -

    CalypsoEnd

    diff --git a/mma/docs/html/lib/stdlib/chacha.html b/mma/docs/html/lib/stdlib/chacha.html index 1b256d1..31a836e 100644 --- a/mma/docs/html/lib/stdlib/chacha.html +++ b/mma/docs/html/lib/stdlib/chacha.html @@ -1,18 +1,41 @@ - +

    Chacha

    -

    A popular, albeit somewhat dated and make trite by Americanized versions, The Cha-Cha-Cha remains a popular rhythm with broad audience appeal. I've used ``Rico Vacilon'' as a demo. This file was mostly developed from the patterns in``Latin Rhythms: Mystery Unraveled'' by Victor Lopez. +

    The Cha-Cha-Cha remains a popular rhythm with broad audience appeal, despite the fact that it is somewhat dated and made trite by Americanized versions. I've used "Rico Vacilon" as a demo. This file was mostly developed from the patterns in "Latin Rhythms: Mystery Unraveled" by Victor Lopez. +

    + + + +
    +

    Variables

    +
    + + + + + + + + + + + + + +
    ArpeggioOctave The Octave setting for the flute arpeggios (default=7)
    ArpeggioVoice Voice for the ChaCha1 Arpeggios (default=Flute)
    ScaleVoice Voice for the accending scale in ChaCha1Fill (default=Flute)
    +

    -

    ChaCha

    @@ -35,7 +58,6 @@
    -

    ChaCha1

    @@ -59,7 +81,6 @@
    -

    ChaChaSus

    @@ -83,7 +104,6 @@
    -

    ChaCha1Sus

    @@ -107,8 +127,52 @@

    + + + + +
    +

    ChaChaFill

    + A one bar fill. (1) +
    + + + + + + + + + + + + +
    Bass JazzGuitar
    Chord Piano1
    Drum-Clave Claves
    Drum-Hconga MuteHighConga
    Drum-Hh RideCymbal1
    Drum-Htom HighTom2
    Drum-Lconga LowConga
    Drum-Lguiro LongGuiro
    Drum-Mtom MidTom2
    Drum-Sguiro ShortGuiro
    Drum-Snare SnareDrum1
    +
    + + + + +
    +

    ChaCha1Fill

    + Fill with accending flute run. Makes a good section introduction. (1) +
    + + + + + + + + + + + + + +
    Bass JazzGuitar
    Chord Piano1
    Drum-Clave Claves
    Drum-Hconga MuteHighConga
    Drum-Hh RideCymbal1
    Drum-Htom HighTom2
    Drum-Lconga LowConga
    Drum-Lguiro LongGuiro
    Drum-Mtom MidTom2
    Drum-Sguiro ShortGuiro
    Drum-Snare SnareDrum1
    Scale Flute
    +
    -

    ChaChaIntro

    @@ -131,7 +195,6 @@
    -

    ChaChaEnd

    diff --git a/mma/docs/html/lib/stdlib/countryblues.html b/mma/docs/html/lib/stdlib/countryblues.html index 67858fe..cc9335a 100644 --- a/mma/docs/html/lib/stdlib/countryblues.html +++ b/mma/docs/html/lib/stdlib/countryblues.html @@ -1,4 +1,4 @@ - +

    Countryblues

    @@ -19,7 +19,6 @@
  • CountryBluesEnd -

    CountryBlues

    @@ -38,7 +37,6 @@
    -

    CountryBluesSus

    @@ -58,7 +56,6 @@
    -

    CountryBluesWalk

    @@ -76,7 +73,6 @@
    -

    CountryBluesWalkSus

    @@ -95,7 +91,6 @@
    -

    CountryBlues1

    @@ -114,7 +109,6 @@
    -

    CountryBlues1Sus

    @@ -134,7 +128,6 @@
    -

    CountryBlues1Walk

    @@ -152,7 +145,6 @@
    -

    CountryBlues1WalkSus

    @@ -171,7 +163,6 @@
    -

    CountryBluesFill

    @@ -191,7 +182,6 @@
    -

    CountryBluesWalkFill

    @@ -210,7 +200,6 @@
    -

    CountryBlues1Fill

    @@ -230,7 +219,6 @@
    -

    CountryBlues1WalkFill

    @@ -249,7 +237,6 @@
    -

    CountryBluesEnd

    diff --git a/mma/docs/html/lib/stdlib/countryswing.html b/mma/docs/html/lib/stdlib/countryswing.html index fef5ee6..d86db61 100644 --- a/mma/docs/html/lib/stdlib/countryswing.html +++ b/mma/docs/html/lib/stdlib/countryswing.html @@ -1,4 +1,4 @@ - +

    Countryswing

    @@ -14,7 +14,6 @@
  • CountrySwingEnd -

    CountrySwing

    @@ -31,7 +30,6 @@
    -

    CountrySwingSus

    @@ -49,7 +47,6 @@
    -

    CountrySwing1

    @@ -67,7 +64,6 @@
    -

    CountrySwing1Sus

    @@ -86,7 +82,6 @@
    -

    CountrySwing2

    @@ -104,7 +99,6 @@
    -

    CountrySwing2Sus

    @@ -123,7 +117,6 @@
    -

    CountrySwingIntro

    @@ -139,7 +132,6 @@
    -

    CountrySwingEnd

    diff --git a/mma/docs/html/lib/stdlib/countrywaltz.html b/mma/docs/html/lib/stdlib/countrywaltz.html index 8d80761..2c25923 100644 --- a/mma/docs/html/lib/stdlib/countrywaltz.html +++ b/mma/docs/html/lib/stdlib/countrywaltz.html @@ -1,4 +1,4 @@ - +

    Countrywaltz

    @@ -19,7 +19,6 @@
  • CountryWaltzEnd -

    CountryWaltz

    @@ -36,7 +35,6 @@
    -

    CountryWaltzSus

    @@ -54,7 +52,6 @@
    -

    CountryWaltz1

    @@ -72,7 +69,6 @@
    -

    CountryWaltz1Sus

    @@ -91,7 +87,6 @@
    -

    CountryWaltz2

    @@ -109,7 +104,6 @@
    -

    CountryWaltz2Sus

    @@ -128,7 +122,6 @@
    -

    CountryWaltzWalk

    @@ -145,7 +138,6 @@
    -

    CountryWaltzWalkSus

    @@ -163,7 +155,6 @@
    -

    CountryWaltz1Walk

    @@ -181,7 +172,6 @@
    -

    Countrywaltz2Walk

    @@ -199,7 +189,6 @@
    -

    CountryWaltz1SusWalk

    @@ -218,7 +207,6 @@
    -

    CountryWaltz2SusWalk

    @@ -237,7 +225,6 @@
    -

    CountryWaltzEnd

    diff --git a/mma/docs/html/lib/stdlib/desert.html b/mma/docs/html/lib/stdlib/desert.html index f2228c3..3711972 100644 --- a/mma/docs/html/lib/stdlib/desert.html +++ b/mma/docs/html/lib/stdlib/desert.html @@ -1,4 +1,4 @@ - +

    Desert

    @@ -10,7 +10,6 @@
  • DesertEnd -

    Desert

    @@ -28,7 +27,6 @@
    -

    DesertSus

    @@ -47,7 +45,6 @@
    -

    DesertFill

    @@ -66,7 +63,6 @@
    -

    DesertEnd

    diff --git a/mma/docs/html/lib/stdlib/dixie.html b/mma/docs/html/lib/stdlib/dixie.html index 42a4416..87c13a9 100644 --- a/mma/docs/html/lib/stdlib/dixie.html +++ b/mma/docs/html/lib/stdlib/dixie.html @@ -1,4 +1,4 @@ - +

    Dixie

    @@ -12,7 +12,6 @@
  • DixieEnd -

    Dixie

    @@ -31,7 +30,6 @@
    -

    Dixie1

    @@ -50,7 +48,6 @@
    -

    Dixie2

    @@ -70,7 +67,6 @@
    -

    Dixie3

    @@ -90,7 +86,6 @@
    -

    DixieStrum

    @@ -109,7 +104,6 @@
    -

    DixieEnd

    diff --git a/mma/docs/html/lib/stdlib/dixiemarch.html b/mma/docs/html/lib/stdlib/dixiemarch.html index 03117a1..6046849 100644 --- a/mma/docs/html/lib/stdlib/dixiemarch.html +++ b/mma/docs/html/lib/stdlib/dixiemarch.html @@ -1,4 +1,4 @@ - +

    Dixiemarch

    @@ -12,7 +12,6 @@
  • DixieMarchEnd -

    DixieMarch

    @@ -29,7 +28,6 @@
    -

    DixieMarchPlus

    @@ -47,7 +45,6 @@
    -

    DixieMarchSus

    @@ -65,7 +62,6 @@
    -

    DixieMarchSusPlus

    @@ -84,7 +80,6 @@
    -

    DixieMarchIntro

    @@ -101,7 +96,6 @@
    -

    DixieMarchEnd

    diff --git a/mma/docs/html/lib/stdlib/easyswing.html b/mma/docs/html/lib/stdlib/easyswing.html index 67133c2..044fa04 100644 --- a/mma/docs/html/lib/stdlib/easyswing.html +++ b/mma/docs/html/lib/stdlib/easyswing.html @@ -1,4 +1,4 @@ - +

    Easyswing

    @@ -29,7 +29,6 @@
  • EasySwingEnd -

    EasySwing

    @@ -46,7 +45,6 @@
    -

    EasySwingSus

    @@ -64,7 +62,6 @@
    -

    EasySwingFill

    @@ -82,7 +79,6 @@
    -

    EasySwingWalk

    @@ -98,7 +94,6 @@
    -

    EasySwingWalkSus

    @@ -115,7 +110,6 @@
    -

    EasySwingWalkFill

    @@ -133,7 +127,6 @@
    -

    EasySwing1

    @@ -150,7 +143,6 @@
    -

    EasySwing1Sus

    @@ -168,7 +160,6 @@
    -

    EasySwing1Fill

    @@ -186,7 +177,6 @@
    -

    EasySwing2

    @@ -203,7 +193,6 @@
    -

    EasySwing2Sus

    @@ -221,7 +210,6 @@
    -

    EasySwing2Fill

    @@ -239,7 +227,6 @@
    -

    EasySwing42

    @@ -256,7 +243,6 @@
    -

    EasySwing42Sus

    @@ -274,7 +260,6 @@
    -

    EasySwing42Fill

    @@ -292,7 +277,6 @@
    -

    EasySwing42Walk

    @@ -308,7 +292,6 @@
    -

    EasySwing42WalkSus

    @@ -325,7 +308,6 @@
    -

    EasySwing42WalkFill

    @@ -342,7 +324,6 @@
    -

    EasySwingIntro

    @@ -358,7 +339,6 @@
    -

    EasySwingIntro1

    @@ -374,7 +354,6 @@
    -

    EasySwingIntro2

    @@ -390,7 +369,6 @@
    -

    EasySwingIntro3

    @@ -407,7 +385,6 @@
    -

    EasySwingEnd

    diff --git a/mma/docs/html/lib/stdlib/fastblues.html b/mma/docs/html/lib/stdlib/fastblues.html index 71f38c0..a56c3d0 100644 --- a/mma/docs/html/lib/stdlib/fastblues.html +++ b/mma/docs/html/lib/stdlib/fastblues.html @@ -1,4 +1,4 @@ - +

    Fastblues

    @@ -13,7 +13,6 @@
  • FastBluesEnd -

    FastBlues

    @@ -33,7 +32,6 @@
    -

    FastBluesSus

    @@ -54,7 +52,6 @@
    -

    FastBluesWalk

    @@ -74,7 +71,6 @@
    -

    FastBluesWalkSus

    @@ -95,7 +91,6 @@
    -

    FastBlues1

    @@ -116,7 +111,6 @@
    -

    FastBlues1Sus

    @@ -138,7 +132,6 @@
    -

    FastBluesEnd

    diff --git a/mma/docs/html/lib/stdlib/folk.html b/mma/docs/html/lib/stdlib/folk.html index 522dc2a..e874938 100644 --- a/mma/docs/html/lib/stdlib/folk.html +++ b/mma/docs/html/lib/stdlib/folk.html @@ -1,4 +1,4 @@ - +

    Folk

    @@ -11,7 +11,6 @@
  • FolkEnd -

    Folk

    @@ -26,7 +25,6 @@
    -

    FolkWalk

    @@ -41,7 +39,6 @@
    -

    FolkArticulated

    @@ -58,7 +55,6 @@
    -

    FolkIntro

    @@ -73,7 +69,6 @@
    -

    FolkEnd

    diff --git a/mma/docs/html/lib/stdlib/foxtrot.html b/mma/docs/html/lib/stdlib/foxtrot.html index 865b122..f170d45 100644 --- a/mma/docs/html/lib/stdlib/foxtrot.html +++ b/mma/docs/html/lib/stdlib/foxtrot.html @@ -1,4 +1,4 @@ - +

    Foxtrot

    @@ -16,7 +16,6 @@
  • FoxTrot1End -

    Foxtrot

    @@ -36,7 +35,6 @@
    -

    FoxtrotSus

    @@ -57,7 +55,6 @@
    -

    FoxTrotPlus

    @@ -78,7 +75,6 @@
    -

    FoxTrotSusPlus

    @@ -100,7 +96,6 @@
    -

    Foxtrot1

    @@ -122,7 +117,6 @@
    -

    FoxTrot1Sus

    @@ -145,7 +139,6 @@
    -

    FoxTrotIntro

    @@ -165,7 +158,6 @@
    -

    FoxtrotFill

    @@ -185,7 +177,6 @@
    -

    FoxTrotEnd

    @@ -203,7 +194,6 @@
    -

    FoxTrot1End

    diff --git a/mma/docs/html/lib/stdlib/frenchwaltz.html b/mma/docs/html/lib/stdlib/frenchwaltz.html index 3769a40..ee74236 100644 --- a/mma/docs/html/lib/stdlib/frenchwaltz.html +++ b/mma/docs/html/lib/stdlib/frenchwaltz.html @@ -1,35 +1,70 @@ - +

    Frenchwaltz

    -

    These try to do the "French Cafe" sound. +

    These try to do the "French Cafe" sound. The song "Pigalle" works quite well with this. Note the setting of the BassRegister variable which tries to emulate the "switches" on a real accordion. In this case we have an accordion with three reed banks labeled "L", "M" and "H"--this will make large changes to the accordion um-pa-pa stuff +

    + + + +
    +

    Variables

    +
    + + + + + + + + + + + + + +
    BassRegister Sets the bass register, 1=L 2=LM 3=LH 4=LMH 5=M 6=MH 7=H (Default=4).
    CSeq Internal, Chord sequence list,
    BSeq Internal, Bass sequence list.
    +

    -

    FrenchWaltz

    - Accordion umm-paa. Ya either love it or hate it! (8) + Accordion umm-pa-pa. Ya either love it or hate it! (8)
    - - + + + + + +
    Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    -

    FrenchWaltzSus

    @@ -37,9 +72,13 @@
    - - + + + + + + @@ -47,7 +86,6 @@
    Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    -

    FrenchWaltz1

    @@ -56,15 +94,37 @@
    - - + + + + + + +
    Arpeggio Accordion
    Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    + + + + +
    +

    FrenchWaltz1Fill

    + Adds an accending run. (8) +
    + + + + + + + + +
    Arpeggio Accordion
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Accordion
    +
    -

    FrenchWaltz1Sus

    @@ -73,16 +133,219 @@
    - - + + + + + + +
    Arpeggio Accordion
    Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    + + + + +
    +

    FrenchWaltz1FillSus

    + Arpeggios, run and sustained strings. (8) +
    + + + + + + + + + +
    Arpeggio Accordion
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Accordion
    +
    + + + + +
    +

    FrenchWaltz2

    + A simple, little counter melody on a piano. (8) +
    + + + + + + + + + + + +
    Arpeggio Piano1
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    +
    + + + + +
    +

    FrenchWaltz2Fill

    + Add a piano run to the counter melody. (8) +
    + + + + + + + + +
    Arpeggio Piano1
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Piano1
    +
    + + + + +
    +

    FrenchWaltz2Sus

    + Piano counter melody and sustained strings. (8) +
    + + + + + + + + + + + + +
    Arpeggio Piano1
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    +
    + + + + +
    +

    FrenchWaltz2FillSus

    + Piano counter melody and run with sustained strings. (8) +
    + + + + + + + + + +
    Arpeggio Piano1
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Piano1
    +
    + + + + +
    +

    FrenchWaltz3

    + A simple, little counter melody on a viola. (8) +
    + + + + + + + + + + + +
    Arpeggio Viola
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    +
    + + + + +
    +

    FrenchWaltz3Fill

    + Add a string run to the counter melody. (8) +
    + + + + + + + + +
    Arpeggio Viola
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Viola
    +
    + + + + +
    +

    FrenchWaltz2Sus

    + Viola counter melody and sustained strings. (8) +
    + + + + + + + + + + + + +
    Arpeggio Viola
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    +
    + + + + +
    +

    FrenchWaltz3FillSus

    + Viola counter melody and run with sustained strings. (8) +
    + + + + + + + + + +
    Arpeggio Viola
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Chord-Sus Strings
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Viola
    +
    + + + + +
    +

    FrenchWaltzIntro

    + A 4 bar intro. (8) +
    + + + + + + + + + + +
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-Guitar NylonGuitar
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    +
    -

    FrenchWaltzEnd

    @@ -90,8 +353,12 @@
    - - + + + + + + @@ -99,7 +366,6 @@
    Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Strings
    -

    FrenchWaltz1End

    @@ -107,8 +373,12 @@
    - - + + + + + + diff --git a/mma/docs/html/lib/stdlib/guitarballad.html b/mma/docs/html/lib/stdlib/guitarballad.html index 3cc092f..0956967 100644 --- a/mma/docs/html/lib/stdlib/guitarballad.html +++ b/mma/docs/html/lib/stdlib/guitarballad.html @@ -1,4 +1,4 @@ - +

    Guitarballad

    @@ -12,7 +12,6 @@
  • GuitarBalladEnd -

  • Bass Accordion
    Chord Accordion
    Bass-H Accordion
    Bass-L Accordion
    Bass-M Accordion
    Chord-H Accordion
    Chord-L Accordion
    Chord-M Accordion
    Drum-Tam Tambourine
    Drum-Tri OpenTriangle
    Scale Accordion

    GuitarBallad

    @@ -30,7 +29,6 @@
    -

    GuitarBallad1

    @@ -49,7 +47,6 @@
    -

    GuitarBalladSus

    @@ -68,7 +65,6 @@
    -

    GuitarBallad1Sus

    @@ -88,7 +84,6 @@
    -

    GuitarBalladIntro

    @@ -106,7 +101,6 @@
    -

    GuitarBalladEnd

    diff --git a/mma/docs/html/lib/stdlib/hillcountry.html b/mma/docs/html/lib/stdlib/hillcountry.html index 475dc92..b16b98b 100644 --- a/mma/docs/html/lib/stdlib/hillcountry.html +++ b/mma/docs/html/lib/stdlib/hillcountry.html @@ -1,4 +1,4 @@ - +

    Hillcountry

    @@ -13,7 +13,6 @@
  • HillCountryEnd -

    HillCountry

    @@ -29,7 +28,6 @@
    -

    HillCountryPlus

    @@ -46,7 +44,6 @@
    -

    HillCountrySus

    @@ -63,7 +60,6 @@
    -

    HillCountrySusPlus

    @@ -81,7 +77,6 @@
    -

    HillCountryFill

    @@ -97,7 +92,6 @@
    -

    HillCountryIntro

    @@ -113,7 +107,6 @@
    -

    HillCountryEnd

    diff --git a/mma/docs/html/lib/stdlib/jazz-54.html b/mma/docs/html/lib/stdlib/jazz-54.html index 9fc1b1e..09c4cb1 100644 --- a/mma/docs/html/lib/stdlib/jazz-54.html +++ b/mma/docs/html/lib/stdlib/jazz-54.html @@ -1,4 +1,4 @@ - +

    Jazz-54

    @@ -9,7 +9,6 @@
  • Jazz54Intro -

    Jazz54

    @@ -26,7 +25,6 @@
    -

    Jazz54Walk

    @@ -43,7 +41,6 @@
    -

    Jazz54Intro

    diff --git a/mma/docs/html/lib/stdlib/jazzguitar.html b/mma/docs/html/lib/stdlib/jazzguitar.html new file mode 100644 index 0000000..fbbf721 --- /dev/null +++ b/mma/docs/html/lib/stdlib/jazzguitar.html @@ -0,0 +1,320 @@ + + + +

    Jazzguitar

    +

    For jazz ballads. This has ONLY a guitar (well, expect for the sustained versions). Mostly chords, but some bass and arpeggio is included. The song "Django" is a bit of a demo. +

    + + + +
    +

    Variables

    +
    + + + + + +
    SustainVoice Voice for the sustained versions (default=TremoloStrings).
    +
    +

    + + + + +
    +

    JazzGuitar

    + A very basic 4 to the bar accompaniment. (4) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitarWalk

    + Changes the bass pattern to walking. (4) +
    + + + +
    Chord JazzGuitar
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar1

    + Our basic pattern with arpeggios every 4th bar. (4) +
    + + + + +
    Arpeggio JazzGuitar
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitar1Walk

    + Walking bass with arpeggios every 4th bar. (4) +
    + + + + +
    Arpeggio JazzGuitar
    Chord JazzGuitar
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar2

    + Basic pattern with more strum and syncopation. (4) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitar2Walk

    + The strum pattern with walking bass (4) +
    + + + +
    Chord JazzGuitar
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar3

    + Add arpeggios every 4 bars to the syncopated strumming. (4) +
    + + + + +
    Arpeggio JazzGuitar
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitar3Walk

    + Aprpeggios and walking bass. (4) +
    + + + + +
    Arpeggio JazzGuitar
    Chord JazzGuitar
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitarSus

    + Sustained strings added to basic pattern. (4) +
    + + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    +
    + + + + +
    +

    JazzGuitar1Sus

    + Sustained strings added to JazzGuitar1. (4) +
    + + + + + +
    Arpeggio JazzGuitar
    Bass JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    +
    + + + + +
    +

    JazzGuitar2Sus

    + Sustained strings added to JazzGuitar2. (4) +
    + + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    +
    + + + + +
    +

    JazzGuitar3Sus

    + Sustained strings added to JazzGuitar3 (4) +
    + + + + + +
    Arpeggio JazzGuitar
    Bass JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    +
    + + + + +
    +

    JazzGuitarWalkSus

    + Sustained strings added to JazzGuitarWalk. (4) +
    + + + + +
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar1WalkSus

    + Sustained strings added to JazzGuitarWalk1. (4) +
    + + + + + +
    Arpeggio JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar2WalkSus

    + Sustained strings added to JazzGuitarWalk2. (4) +
    + + + + +
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitar3WalkSus

    + Sustained strings added to JazzGuitarWalk3. (4) +
    + + + + + +
    Arpeggio JazzGuitar
    Chord JazzGuitar
    Chord-Sus TremoloStrings
    Walk JazzGuitar
    +
    + + + + +
    +

    JazzGuitarIntro

    + A 4 bar, arpeggiating introduction. (4) +
    + + + + +
    Arpeggio JazzGuitar
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitar1Intro

    + A 4 bar intro with a bass run on bar 4. (4) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitarEnd

    + Soft, 2 bar ending. (2) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    JazzGuitarEnd1

    + Soft, 1 bar ending. (1) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + diff --git a/mma/docs/html/lib/stdlib/jazzwaltz.html b/mma/docs/html/lib/stdlib/jazzwaltz.html index e6a9c21..e5f8efc 100644 --- a/mma/docs/html/lib/stdlib/jazzwaltz.html +++ b/mma/docs/html/lib/stdlib/jazzwaltz.html @@ -1,4 +1,4 @@ - +

    Jazzwaltz

    @@ -15,7 +15,6 @@
  • JazzWaltz1End -

    JazzWaltz

    @@ -34,7 +33,6 @@
    -

    JazzWaltzSus

    @@ -54,7 +52,6 @@
    -

    JazzWaltz1

    @@ -74,7 +71,6 @@
    -

    JazzWaltz1Sus

    @@ -95,7 +91,6 @@
    -

    JazzWaltzIntro

    @@ -114,7 +109,6 @@
    -

    JazzWaltzIntro8

    @@ -133,7 +127,6 @@
    -

    JazzWaltzFill

    @@ -151,7 +144,6 @@
    -

    JazzWaltzEnd

    @@ -169,7 +161,6 @@
    -

    JazzWaltz1End

    diff --git a/mma/docs/html/lib/stdlib/jive.html b/mma/docs/html/lib/stdlib/jive.html index d9504bb..e152d44 100644 --- a/mma/docs/html/lib/stdlib/jive.html +++ b/mma/docs/html/lib/stdlib/jive.html @@ -1,4 +1,4 @@ - +

    Jive

    @@ -20,7 +20,6 @@
  • JiveEnd -

    Jive

    @@ -38,7 +37,6 @@
    -

    JiveClap

    @@ -57,7 +55,6 @@
    -

    JiveSus

    @@ -76,7 +73,6 @@
    -

    JiveClapSus

    @@ -96,7 +92,6 @@
    -

    JivePlus

    @@ -115,7 +110,6 @@
    -

    JiveSusPlus

    @@ -135,7 +129,6 @@
    -

    Jive1

    @@ -153,7 +146,6 @@
    -

    Jive1Clap

    @@ -172,7 +164,6 @@
    -

    Jive1Sus

    @@ -191,7 +182,6 @@
    -

    Jive1ClapSus

    @@ -211,7 +201,6 @@
    -

    Jive1Plus

    @@ -230,7 +219,6 @@
    -

    Jive1SusPlus

    @@ -250,7 +238,6 @@
    -

    JiveIntro

    @@ -269,7 +256,6 @@
    -

    JiveEnd

    diff --git a/mma/docs/html/lib/stdlib/lfusion.html b/mma/docs/html/lib/stdlib/lfusion.html index 7bc3c2c..d31dbef 100644 --- a/mma/docs/html/lib/stdlib/lfusion.html +++ b/mma/docs/html/lib/stdlib/lfusion.html @@ -1,4 +1,4 @@ - +

    Lfusion

    @@ -12,7 +12,6 @@
  • Lfusion1End -

    LFusion

    @@ -41,7 +40,6 @@
    -

    LFusionSus

    @@ -70,7 +68,6 @@
    -

    LFusion1

    @@ -98,7 +95,6 @@
    -

    LFusion1Sus

    @@ -127,7 +123,6 @@
    -

    LFusionEnd

    @@ -150,7 +145,6 @@
    -

    Lfusion1End

    diff --git a/mma/docs/html/lib/stdlib/lighttango.html b/mma/docs/html/lib/stdlib/lighttango.html index d14b43a..9a6e00b 100644 --- a/mma/docs/html/lib/stdlib/lighttango.html +++ b/mma/docs/html/lib/stdlib/lighttango.html @@ -1,4 +1,4 @@ - +

    Lighttango

    @@ -8,11 +8,11 @@
  • LightTangoSus
  • LightTango1
  • LightTango1Sus +
  • LightTangoFill
  • LightTangoIntro
  • LightTangoEnd -

    LightTango

    @@ -33,7 +33,6 @@
    -

    LightTangoSus

    @@ -55,7 +54,6 @@
    -

    LightTango1

    @@ -76,7 +74,6 @@
    -

    LightTango1Sus

    @@ -97,8 +94,26 @@

  • + + + + +
    +

    LightTangoFill

    + A one bar fill pattern. (1) +
    + + + + + + + + + +
    Bass AcousticBass
    Bass-Piano Piano1
    Chord-Accordion Accordion
    Chord-Guitar NylonGuitar
    Drum-Clave Claves
    Drum-Kick KickDrum1
    Drum-Phh PedalHiHat
    Drum-Snare SnareDrum1
    +
    -

    LightTangoIntro

    @@ -119,7 +134,6 @@
    -

    LightTangoEnd

    diff --git a/mma/docs/html/lib/stdlib/lullaby.html b/mma/docs/html/lib/stdlib/lullaby.html new file mode 100644 index 0000000..500a312 --- /dev/null +++ b/mma/docs/html/lib/stdlib/lullaby.html @@ -0,0 +1,125 @@ + + + +

    Lullaby

    +

    Gentle, soft lullaby in 4. Written for "Good Night". +

    + + + +
    +

    Variables

    +
    + + + + + + + + + +
    ChordVoice Voice used in Chord tracks (defaults to JazzGuitar).
    ChordOctave Octave for Chord track (default 4)
    +
    +

    + + + + +
    +

    Lullaby

    + Just a solo guitar in 4. (1) +
    + + +
    Chord JazzGuitar
    +
    + + + + +
    +

    Lullaby1

    + Adds in a bit of bass. (1) +
    + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    +
    + + + + +
    +

    LullabyWalk

    + Adds an 8th note walking bass line. (1) +
    + + + +
    Chord JazzGuitar
    Walk JazzGuitar
    +
    + + + + +
    +

    LullabySus

    + Add some sustained strings to our guitar. (1) +
    + + + +
    Chord JazzGuitar
    Chord-Sus SlowStrings
    +
    + + + + +
    +

    Lullaby1Sus

    + A bit of bass with the strings. (1) +
    + + + + +
    Bass JazzGuitar
    Chord JazzGuitar
    Chord-Sus SlowStrings
    +
    + + + + +
    +

    LullabyWalkSus

    + Strings and walking bass. (1) +
    + + + + +
    Chord JazzGuitar
    Chord-Sus SlowStrings
    Walk JazzGuitar
    +
    + + + + +
    +

    LullabyEnd

    + Two half notes on the guitar. (1) +
    + + +
    Chord JazzGuitar
    +
    + + diff --git a/mma/docs/html/lib/stdlib/mambo.html b/mma/docs/html/lib/stdlib/mambo.html index fb0d4d0..e93a912 100644 --- a/mma/docs/html/lib/stdlib/mambo.html +++ b/mma/docs/html/lib/stdlib/mambo.html @@ -1,4 +1,4 @@ - +

    Mambo

    @@ -16,7 +16,6 @@
  • MamboEnd -

    Mambo

    @@ -37,7 +36,6 @@
    -

    Mambo1

    @@ -58,7 +56,6 @@
    -

    Mambo2

    @@ -80,7 +77,6 @@
    -

    Mambo3

    @@ -102,7 +98,6 @@
    -

    MamboSus

    @@ -124,7 +119,6 @@
    -

    Mambo1Sus

    @@ -146,7 +140,6 @@
    -

    Mambo2Sus

    @@ -169,7 +162,6 @@
    -

    Mambo3Sus

    @@ -192,7 +184,6 @@
    -

    MamboIntro

    @@ -213,7 +204,6 @@
    -

    MamboEnd

    diff --git a/mma/docs/html/lib/stdlib/march.html b/mma/docs/html/lib/stdlib/march.html index f9dbb61..74f1b67 100644 --- a/mma/docs/html/lib/stdlib/march.html +++ b/mma/docs/html/lib/stdlib/march.html @@ -1,4 +1,4 @@ - +

    March

    @@ -15,7 +15,6 @@
  • MarchEnd -

    MilIntro4

    @@ -29,7 +28,6 @@
    -

    MilIntro2

    @@ -43,7 +41,6 @@
    -

    March

    @@ -61,7 +58,6 @@
    -

    March1

    @@ -80,7 +76,6 @@
    -

    March1Slow

    @@ -98,7 +93,6 @@
    -

    March2

    @@ -116,7 +110,6 @@
    -

    March3

    @@ -136,7 +129,6 @@
    -

    March4

    @@ -155,7 +147,6 @@
    -

    MarchEnd

    diff --git a/mma/docs/html/lib/stdlib/merengue.html b/mma/docs/html/lib/stdlib/merengue.html index cb6529c..d70d4a2 100644 --- a/mma/docs/html/lib/stdlib/merengue.html +++ b/mma/docs/html/lib/stdlib/merengue.html @@ -1,4 +1,4 @@ - +

    Merengue

    @@ -14,7 +14,6 @@
  • MerengueEnd -

    Merengue

    @@ -34,7 +33,6 @@
    -

    Merengue1

    @@ -54,7 +52,6 @@
    -

    Merengue2

    @@ -75,7 +72,6 @@
    -

    MerengueSus

    @@ -96,7 +92,6 @@
    -

    Merengue1Sus

    @@ -117,7 +112,6 @@
    -

    Merengue2Sus

    @@ -139,7 +133,6 @@
    -

    MerengueIntro

    @@ -159,7 +152,6 @@
    -

    MerengueEnd

    diff --git a/mma/docs/html/lib/stdlib/metronome.html b/mma/docs/html/lib/stdlib/metronome.html index 0dbcf0e..7b23275 100644 --- a/mma/docs/html/lib/stdlib/metronome.html +++ b/mma/docs/html/lib/stdlib/metronome.html @@ -1,4 +1,4 @@ - +

    Metronome

    @@ -9,7 +9,6 @@
  • Metronome2-4 -

    Metronome2

    @@ -23,7 +22,6 @@
    -

    Metronome4

    @@ -37,7 +35,6 @@
    -

    Metronome2-4

    diff --git a/mma/docs/html/lib/stdlib/metronome3.html b/mma/docs/html/lib/stdlib/metronome3.html index 1cf8fbe..88d83cf 100644 --- a/mma/docs/html/lib/stdlib/metronome3.html +++ b/mma/docs/html/lib/stdlib/metronome3.html @@ -1,4 +1,4 @@ - +

    Metronome3

    @@ -7,7 +7,6 @@
  • Metronome3 -

    Metronome3

    diff --git a/mma/docs/html/lib/stdlib/modernjazz.html b/mma/docs/html/lib/stdlib/modernjazz.html index 2f3f1f9..b219429 100644 --- a/mma/docs/html/lib/stdlib/modernjazz.html +++ b/mma/docs/html/lib/stdlib/modernjazz.html @@ -1,8 +1,22 @@ - +

    Modernjazz

    A jazz style which has a bit of raunch and swing. Works well with Peggy Lee's "Fever". +

    + + + +
    +

    Variables

    +
    + + + + + +
    ApreggioVoice Voice for the alternating apreggios in ModernJazz1 (Default=MutedTrumpet). Also used in Introduction and Ending.
    +

    -

    ModernJazz

    @@ -32,7 +45,6 @@
    -

    ModernJazz1

    @@ -54,7 +66,6 @@
    -

    ModernJazzSus

    @@ -75,7 +86,6 @@
    -

    ModernJazz1Sus

    @@ -98,7 +108,6 @@
    -

    ModernJazzIntro

    @@ -118,7 +127,6 @@
    -

    ModernJazzEnd

    diff --git a/mma/docs/html/lib/stdlib/pianoballad.html b/mma/docs/html/lib/stdlib/pianoballad.html index 28b58a9..0c11e71 100644 --- a/mma/docs/html/lib/stdlib/pianoballad.html +++ b/mma/docs/html/lib/stdlib/pianoballad.html @@ -1,4 +1,4 @@ - +

    Pianoballad

    @@ -12,7 +12,6 @@
  • PianoBalladEnd -

    PianoBallad

    @@ -30,7 +29,6 @@
    -

    PianoBallad1

    @@ -49,7 +47,6 @@
    -

    PianoBalladSus

    @@ -68,7 +65,6 @@
    -

    PianoBallad1Sus

    @@ -88,7 +84,6 @@
    -

    PianoBalladIntro

    @@ -106,7 +101,6 @@
    -

    PianoBalladEnd

    diff --git a/mma/docs/html/lib/stdlib/polka.html b/mma/docs/html/lib/stdlib/polka.html index 862cf69..a405a37 100644 --- a/mma/docs/html/lib/stdlib/polka.html +++ b/mma/docs/html/lib/stdlib/polka.html @@ -1,4 +1,4 @@ - +

    Polka

    @@ -16,7 +16,6 @@
  • PolkaEnd -

    Polka

    @@ -36,7 +35,6 @@
    -

    PolkaSus

    @@ -57,7 +55,6 @@
    -

    PolkaArp

    @@ -78,7 +75,6 @@
    -

    PolkaSusArp

    @@ -100,7 +96,6 @@
    -

    Polka1

    @@ -120,7 +115,6 @@
    -

    Polka1Sus

    @@ -141,7 +135,6 @@
    -

    Polka1Arp

    @@ -162,7 +155,6 @@
    -

    Polka1SusArp

    @@ -184,7 +176,6 @@
    -

    PolkaIntro

    @@ -203,7 +194,6 @@
    -

    PolkaEnd

    diff --git a/mma/docs/html/lib/stdlib/popballad.html b/mma/docs/html/lib/stdlib/popballad.html index 1565c4c..8f49e7d 100644 --- a/mma/docs/html/lib/stdlib/popballad.html +++ b/mma/docs/html/lib/stdlib/popballad.html @@ -1,4 +1,4 @@ - +

    Popballad

    @@ -7,10 +7,11 @@
  • PopBallad
  • PopBallad1
  • PopBallad2 +
  • PopBalladSus +
  • PopBalladIntro
  • PopBalladEnd -

    PopBallad

    @@ -31,7 +32,6 @@
    -

    PopBallad1

    @@ -55,7 +55,6 @@
    -

    PopBallad2

    @@ -74,8 +73,48 @@

  • + + + + +
    +

    PopBalladSus

    + A slightly lighter version, with strings. (4) +
    + + + + + + + + + + + +
    Arpeggio Atmosphere
    Bass AcousticBass
    Chord Piano2
    Chord-Sus TremoloStrings
    Drum-Cabasa Cabasa
    Drum-Cym CrashCymbal1
    Drum-Hh ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Shake Shaker
    Drum-Snare SnareDrum1
    +
    + + + + +
    +

    PopBalladIntro

    + A simple introduction. (4) +
    + + + + + + + + + + +
    Arpeggio Atmosphere
    Bass AcousticBass
    Chord Piano2
    Drum-Cabasa Cabasa
    Drum-Cym CrashCymbal1
    Drum-Hh ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Shake Shaker
    Drum-Snare SnareDrum1
    +
    -

    PopBalladEnd

    diff --git a/mma/docs/html/lib/stdlib/quickstep.html b/mma/docs/html/lib/stdlib/quickstep.html index d27ccbb..37a4615 100644 --- a/mma/docs/html/lib/stdlib/quickstep.html +++ b/mma/docs/html/lib/stdlib/quickstep.html @@ -1,4 +1,4 @@ - +

    Quickstep

    @@ -14,7 +14,6 @@
  • QuickStepEnd -

    QuickStep

    @@ -32,7 +31,6 @@
    -

    QuickStepHit

    @@ -51,7 +49,6 @@
    -

    QuickStepSus

    @@ -70,7 +67,6 @@
    -

    QuickStepHitSus

    @@ -90,7 +86,6 @@
    -

    QuickStepDuh

    @@ -109,7 +104,6 @@
    -

    QuickStepDuhSus

    @@ -129,7 +123,6 @@
    -

    QuickStepIntro

    @@ -147,7 +140,6 @@
    -

    QuickStepEnd

    diff --git a/mma/docs/html/lib/stdlib/rb.html b/mma/docs/html/lib/stdlib/rb.html index e9f2942..9d0ee13 100644 --- a/mma/docs/html/lib/stdlib/rb.html +++ b/mma/docs/html/lib/stdlib/rb.html @@ -1,4 +1,4 @@ - +

    Rb

    @@ -10,7 +10,6 @@
  • R&BEnd -

    R&B

    @@ -32,7 +31,6 @@
    -

    R&BSus

    @@ -54,7 +52,6 @@
    -

    R&BIntro

    @@ -75,7 +72,6 @@
    -

    R&BEnd

    diff --git a/mma/docs/html/lib/stdlib/rhumba.html b/mma/docs/html/lib/stdlib/rhumba.html index a63e50e..c4cd2d6 100644 --- a/mma/docs/html/lib/stdlib/rhumba.html +++ b/mma/docs/html/lib/stdlib/rhumba.html @@ -1,4 +1,4 @@ - +

    Rhumba

    @@ -23,7 +23,6 @@
  • RhumbaEnd1 -

    Rhumba

    @@ -45,7 +44,6 @@
    -

    RhumbaSus

    @@ -68,7 +66,6 @@
    -

    RhumbaTriple

    @@ -89,7 +86,6 @@
    -

    RhumbaTripleSus

    @@ -111,7 +107,6 @@
    -

    RhumbaTriple12

    @@ -132,7 +127,6 @@
    -

    RhumbaTriple12Sus

    @@ -154,7 +148,6 @@
    -

    RhumbaTriple34

    @@ -176,7 +169,6 @@
    -

    RhumbaTriple34Sus

    @@ -198,7 +190,6 @@
    -

    Rhumba1

    @@ -221,7 +212,6 @@
    -

    Rhumba1Sus

    @@ -245,7 +235,6 @@
    -

    Rhumba2

    @@ -268,7 +257,6 @@
    -

    Rhumba2Sus

    @@ -292,7 +280,6 @@
    -

    Rhumba3

    @@ -315,7 +302,6 @@
    -

    Rhumba3Sus

    @@ -339,7 +325,6 @@
    -

    RhumbaIntro

    @@ -360,7 +345,6 @@
    -

    RhumbaEnd

    @@ -383,7 +367,6 @@
    -

    RhumbaEnd1

    diff --git a/mma/docs/html/lib/stdlib/rock-128.html b/mma/docs/html/lib/stdlib/rock-128.html index 9931e6b..fd2308c 100644 --- a/mma/docs/html/lib/stdlib/rock-128.html +++ b/mma/docs/html/lib/stdlib/rock-128.html @@ -1,4 +1,4 @@ - +

    Rock-128

    @@ -10,7 +10,6 @@
  • Rock128End -

    Rock128

    @@ -27,7 +26,6 @@
    -

    Rock128Sus

    @@ -46,7 +44,6 @@
    -

    Rock128Intro

    @@ -63,7 +60,6 @@
    -

    Rock128End

    diff --git a/mma/docs/html/lib/stdlib/rockballad.html b/mma/docs/html/lib/stdlib/rockballad.html index 6fa657c..e2576d5 100644 --- a/mma/docs/html/lib/stdlib/rockballad.html +++ b/mma/docs/html/lib/stdlib/rockballad.html @@ -1,17 +1,37 @@ - +

    Rockballad

    Written for slowish/doo-wop things like "You Belong To Me". +

    + + + +
    +

    Variables

    +
    + + + + + + + + + +
    SusVoice Voice used for sustained voicing in RockBalladVoice (default=ChoirAahs).
    SusVoiceOctave Octave for sustained voices (default=4).
    +

    -

    RockBallad

    @@ -28,8 +48,24 @@

    + + + + +
    +

    RockBallad1

    + Same as the basic pattern, but skips the chord triplet on bar 4. (4) +
    + + + + + + + +
    Bass FretlessBass
    Chord JazzGuitar
    Drum ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum1
    Walk FretlessBass
    +
    -

    RockBalladFill

    @@ -47,8 +83,25 @@

  • + + + + +
    +

    RockBallad1Fill

    + Guitar apreggio fills without 4th bar triplets. (4) +
    + + + + + + + + +
    Arpeggio JazzGuitar
    Bass FretlessBass
    Chord JazzGuitar
    Drum ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum1
    Walk FretlessBass
    +
    -

    RockBalladVoice

    @@ -67,7 +120,6 @@
    -

    RockBalladIntro

    @@ -85,7 +137,6 @@
    -

    RockBalladEnd

    @@ -102,5 +153,21 @@

  • + + + + +
    +

    RockBalladEnd1

    + Simple 2 bar ending. (2) +
    + + + + + + +
    Bass FretlessBass
    Chord JazzGuitar
    Drum ClosedHiHat
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum1
    +
    diff --git a/mma/docs/html/lib/stdlib/samba.html b/mma/docs/html/lib/stdlib/samba.html index f8f39e6..30fa59a 100644 --- a/mma/docs/html/lib/stdlib/samba.html +++ b/mma/docs/html/lib/stdlib/samba.html @@ -1,4 +1,4 @@ - +

    Samba

    @@ -14,7 +14,6 @@
  • SambaEnd -

    Samba

    @@ -35,7 +34,6 @@
    -

    SambaFill

    @@ -57,7 +55,6 @@
    -

    SambaPlus

    @@ -78,7 +75,6 @@
    -

    SambaSus

    @@ -100,7 +96,6 @@
    -

    SambaSusFill

    @@ -123,7 +118,6 @@
    -

    SambaSusPlus

    @@ -145,7 +139,6 @@
    -

    SambaIntro

    @@ -166,7 +159,6 @@
    -

    SambaEnd

    diff --git a/mma/docs/html/lib/stdlib/shuffleboggie.html b/mma/docs/html/lib/stdlib/shuffleboggie.html new file mode 100644 index 0000000..f67ce1c --- /dev/null +++ b/mma/docs/html/lib/stdlib/shuffleboggie.html @@ -0,0 +1,137 @@ + + + +

    Shuffleboggie

    +

    A blues-like shuffle beat. Written for Kansas City. +

    + + + + +
    +

    ShuffleBoggie

    + Blues with a shuffle style. (2) +
    + + + + + + + + + + + +
    Bass SlapBass1
    Bass-Piano Piano2
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Ohh OpenHiHat
    Drum-Snare SnareDrum2
    +
    + + + + +
    +

    ShuffleBoggie1

    + Adds an articulated guitar riff to the basic beat. (2) +
    + + + + + + + + + + + + +
    Arpeggio CleanGuitar
    Bass SlapBass1
    Bass-Piano Piano2
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Ohh OpenHiHat
    Drum-Snare SnareDrum2
    +
    + + + + +
    +

    ShuffleBoggieSus

    + Blues with violins. Sort of odd, but we can call them fiddles! (2) +
    + + + + + + + + + + + + +
    Bass SlapBass1
    Bass-Piano Piano2
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Chord-Sus Strings
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Ohh OpenHiHat
    Drum-Snare SnareDrum2
    +
    + + + + +
    +

    ShuffleBoggieIntro

    + A two bar intro. Short, loud and sweet. (2) +
    + + + + + + + + + +
    Bass SlapBass1
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum2
    +
    + + + + +
    +

    ShuffleBoggieIntro4

    + A four bar intro. (4) +
    + + + + + + + + + +
    Bass SlapBass1
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum2
    +
    + + + + +
    +

    ShuffleBoggieEnd

    + Very simple ending, hits on 1, 2 and 3 of last bar. (2) +
    + + + + + + + + + +
    Bass SlapBass1
    Chord-Guitar MutedGuitar
    Chord-Piano Piano2
    Chord-Sax TenorSax
    Drum-Chh ClosedHiHat
    Drum-Clap HandClap
    Drum-Kick KickDrum1
    Drum-Snare SnareDrum2
    +
    + + diff --git a/mma/docs/html/lib/stdlib/ska.html b/mma/docs/html/lib/stdlib/ska.html index 5fbe6dd..e3d90c8 100644 --- a/mma/docs/html/lib/stdlib/ska.html +++ b/mma/docs/html/lib/stdlib/ska.html @@ -1,4 +1,4 @@ - +

    Ska

    @@ -12,7 +12,6 @@
  • SkaEnd -

    Ska

    @@ -34,7 +33,6 @@
    -

    Ska1

    @@ -57,7 +55,6 @@
    -

    SkaSus

    @@ -80,7 +77,6 @@
    -

    Ska1Sus

    @@ -104,7 +100,6 @@
    -

    SkaClap

    @@ -127,7 +122,6 @@
    -

    SkaEnd

    diff --git a/mma/docs/html/lib/stdlib/slowblues.html b/mma/docs/html/lib/stdlib/slowblues.html index 6a7312f..3232060 100644 --- a/mma/docs/html/lib/stdlib/slowblues.html +++ b/mma/docs/html/lib/stdlib/slowblues.html @@ -1,4 +1,4 @@ - +

    Slowblues

    @@ -18,7 +18,6 @@
  • SlowBluesEnd -

    SlowBlues

    @@ -36,7 +35,6 @@
    -

    SlowBluesFill

    @@ -54,7 +52,6 @@
    -

    SlowBluesFill1

    @@ -72,7 +69,6 @@
    -

    SlowBluesFill2

    @@ -90,7 +86,6 @@
    -

    SlowBluesFill3

    @@ -108,7 +103,6 @@
    -

    SlowBluesSus

    @@ -127,7 +121,6 @@
    -

    SlowBluesWalk4

    @@ -144,7 +137,6 @@
    -

    SlowBluesWalk4Sus

    @@ -162,7 +154,6 @@
    -

    SlowBluesWalk8

    @@ -180,7 +171,6 @@
    -

    SlowBluesWalk8Sus

    @@ -199,7 +189,6 @@
    -

    SlowBluesIntro

    @@ -216,7 +205,6 @@
    -

    SlowBluesEnd

    diff --git a/mma/docs/html/lib/stdlib/slowbolero.html b/mma/docs/html/lib/stdlib/slowbolero.html index afcad6d..3d62f6f 100644 --- a/mma/docs/html/lib/stdlib/slowbolero.html +++ b/mma/docs/html/lib/stdlib/slowbolero.html @@ -1,4 +1,4 @@ - +

    Slowbolero

    @@ -10,7 +10,6 @@
  • SlowBoleroEnd -

    SlowBolero

    @@ -32,7 +31,6 @@
    -

    SlowBoleroSus

    @@ -55,7 +53,6 @@
    -

    SlowBoleroIntro

    @@ -77,7 +74,6 @@
    -

    SlowBoleroEnd

    diff --git a/mma/docs/html/lib/stdlib/slowcountry.html b/mma/docs/html/lib/stdlib/slowcountry.html index da757ee..01080d2 100644 --- a/mma/docs/html/lib/stdlib/slowcountry.html +++ b/mma/docs/html/lib/stdlib/slowcountry.html @@ -1,4 +1,4 @@ - +

    Slowcountry

    @@ -14,7 +14,6 @@
  • SlowCountryEnd -

    SlowCountry

    @@ -32,7 +31,6 @@
    -

    SlowCountrySus

    @@ -51,7 +49,6 @@
    -

    SlowCountryFill

    @@ -70,7 +67,6 @@
    -

    SlowCountryWalk

    @@ -86,7 +82,6 @@
    -

    SlowCountryWalkSus

    @@ -103,7 +98,6 @@
    -

    SlowCountryWalkFill

    @@ -122,7 +116,6 @@
    -

    SlowCountryIntro

    @@ -139,7 +132,6 @@
    -

    SlowCountryEnd

    diff --git a/mma/docs/html/lib/stdlib/slowjazz.html b/mma/docs/html/lib/stdlib/slowjazz.html index c673b50..42e9150 100644 --- a/mma/docs/html/lib/stdlib/slowjazz.html +++ b/mma/docs/html/lib/stdlib/slowjazz.html @@ -1,4 +1,4 @@ - +

    Slowjazz

    @@ -21,7 +21,6 @@
  • SlowJazz2End -

    SlowJazz

    @@ -39,7 +38,6 @@
    -

    SlowJazzSus

    @@ -58,7 +56,6 @@
    -

    SlowJazzWalk

    @@ -75,7 +72,6 @@
    -

    SlowJazzWalkSus

    @@ -93,7 +89,6 @@
    -

    SlowJazz1

    @@ -111,7 +106,6 @@
    -

    SlowJazz1Sus

    @@ -130,7 +124,6 @@
    -

    SlowJazz1Walk

    @@ -147,7 +140,6 @@
    -

    SlowJazz1WalkSus

    @@ -165,7 +157,6 @@
    -

    SlowJazz2

    @@ -183,7 +174,6 @@
    -

    SlowJazz2Sus

    @@ -202,7 +192,6 @@
    -

    SlowJazzIntro

    @@ -220,7 +209,6 @@
    -

    SlowJazz1Intro

    @@ -238,7 +226,6 @@
    -

    SlowJazz2Intro

    @@ -255,7 +242,6 @@
    -

    SlowJazzEnd

    @@ -272,7 +258,6 @@
    -

    SlowJazz2End

    diff --git a/mma/docs/html/lib/stdlib/softrock.html b/mma/docs/html/lib/stdlib/softrock.html index 6aa4d33..2418439 100644 --- a/mma/docs/html/lib/stdlib/softrock.html +++ b/mma/docs/html/lib/stdlib/softrock.html @@ -1,4 +1,4 @@ - +

    Softrock

    @@ -13,7 +13,6 @@
  • SoftRockEnd -

    SoftRock

    @@ -31,7 +30,6 @@
    -

    SoftRockSus

    @@ -50,7 +48,6 @@
    -

    SoftRock1

    @@ -69,7 +66,6 @@
    -

    SoftRock1Sus

    @@ -89,7 +85,6 @@
    -

    SoftRockIntro

    @@ -106,7 +101,6 @@
    -

    SoftRockSusIntro

    @@ -124,7 +118,6 @@
    -

    SoftRockEnd

    diff --git a/mma/docs/html/lib/stdlib/softshoe.html b/mma/docs/html/lib/stdlib/softshoe.html index adebdf8..6f6971c 100644 --- a/mma/docs/html/lib/stdlib/softshoe.html +++ b/mma/docs/html/lib/stdlib/softshoe.html @@ -1,8 +1,22 @@ - +

    Softshoe

    Syncopated ditty for the old dancers. Written for "Me and My Shadow". +

    + + + +
    +

    Variables

    +
    + + + + + +
    ChordVoice Voice used in Chord tracks (defaults to Piano2).
    +

    -

    Softshoe

    @@ -30,7 +43,6 @@
    -

    SoftShoePlus

    @@ -49,7 +61,6 @@
    -

    SoftShoeSus

    @@ -68,7 +79,6 @@
    -

    SoftShoeSusPlus

    @@ -88,7 +98,6 @@
    -

    SoftShoeIntro

    @@ -105,7 +114,6 @@
    -

    SoftShoeEnd

    diff --git a/mma/docs/html/lib/stdlib/son.html b/mma/docs/html/lib/stdlib/son.html index 7b188a4..2e9574c 100644 --- a/mma/docs/html/lib/stdlib/son.html +++ b/mma/docs/html/lib/stdlib/son.html @@ -1,4 +1,4 @@ - +

    Son

    @@ -10,7 +10,6 @@
  • SonEnd -

    Son

    @@ -33,7 +32,6 @@
    -

    SonSus

    @@ -57,7 +55,6 @@
    -

    SonIntro

    @@ -80,7 +77,6 @@
    -

    SonEnd

    diff --git a/mma/docs/html/lib/stdlib/swing.html b/mma/docs/html/lib/stdlib/swing.html index 9a88ccd..2929643 100644 --- a/mma/docs/html/lib/stdlib/swing.html +++ b/mma/docs/html/lib/stdlib/swing.html @@ -1,4 +1,4 @@ - +

    Swing

    @@ -34,7 +34,6 @@
  • Swing2End -

    Swing

    @@ -55,7 +54,6 @@
    -

    SwingWalk

    @@ -76,7 +74,6 @@
    -

    SwingTriple

    @@ -97,7 +94,6 @@
    -

    SwingPlus

    @@ -119,7 +115,6 @@
    -

    SwingWalkPlus

    @@ -141,7 +136,6 @@
    -

    SwingSus

    @@ -163,7 +157,6 @@
    -

    SwingPlusSus

    @@ -186,7 +179,6 @@
    -

    SwingWalkSus

    @@ -208,7 +200,6 @@
    -

    SwingWalkPlusSus

    @@ -231,7 +222,6 @@
    -

    Swing1

    @@ -252,7 +242,6 @@
    -

    Swing1Walk

    @@ -273,7 +262,6 @@
    -

    Swing1Triple

    @@ -293,7 +281,6 @@
    -

    Swing1Sus

    @@ -315,7 +302,6 @@
    -

    Swing1WalkSus

    @@ -337,7 +323,6 @@
    -

    Swing1Plus

    @@ -359,7 +344,6 @@
    -

    Swing1PlusSus

    @@ -382,7 +366,6 @@
    -

    Swing1WalkPlus

    @@ -404,7 +387,6 @@
    -

    Swing1WalkPlusSus

    @@ -427,7 +409,6 @@
    -

    Swing2

    @@ -449,7 +430,6 @@
    -

    Swing2Triple

    @@ -469,7 +449,6 @@
    -

    Swing2Plus

    @@ -492,7 +471,6 @@
    -

    Swing2Sus

    @@ -515,7 +493,6 @@
    -

    Swing2PlusSus

    @@ -539,7 +516,6 @@
    -

    SwingIntro

    @@ -560,7 +536,6 @@
    -

    SwingIntro2

    @@ -581,7 +556,6 @@
    -

    SwingEnd

    @@ -600,7 +574,6 @@
    -

    Swing1End

    @@ -621,7 +594,6 @@
    -

    Swing2End

    diff --git a/mma/docs/html/lib/stdlib/tango.html b/mma/docs/html/lib/stdlib/tango.html index 39cca89..6a7e6f8 100644 --- a/mma/docs/html/lib/stdlib/tango.html +++ b/mma/docs/html/lib/stdlib/tango.html @@ -1,4 +1,4 @@ - +

    Tango

    @@ -9,7 +9,6 @@
  • TangoEnd -

    Tango

    @@ -30,7 +29,6 @@
    -

    Tango1

    @@ -51,7 +49,6 @@
    -

    TangoEnd

    diff --git a/mma/docs/html/lib/stdlib/vienesewaltz.html b/mma/docs/html/lib/stdlib/vienesewaltz.html index d392024..638793b 100644 --- a/mma/docs/html/lib/stdlib/vienesewaltz.html +++ b/mma/docs/html/lib/stdlib/vienesewaltz.html @@ -1,4 +1,4 @@ - +

    Vienesewaltz

    @@ -11,7 +11,6 @@
  • VieneseWaltzEnd -

    VieneseWaltz

    @@ -28,7 +27,6 @@
    -

    VieneseWaltzSus

    @@ -46,7 +44,6 @@
    -

    VieneseWaltz1

    @@ -64,7 +61,6 @@
    -

    VieneseWaltz1Sus

    @@ -83,7 +79,6 @@
    -

    VieneseWaltzEnd

    diff --git a/mma/docs/html/lib/stdlib/waltz.html b/mma/docs/html/lib/stdlib/waltz.html index 47e6894..68127dd 100644 --- a/mma/docs/html/lib/stdlib/waltz.html +++ b/mma/docs/html/lib/stdlib/waltz.html @@ -1,4 +1,4 @@ - +

    Waltz

    @@ -17,7 +17,6 @@
  • WaltzEnd -

    Waltz

    @@ -36,7 +35,6 @@
    -

    WaltzSus

    @@ -56,7 +54,6 @@
    -

    Waltz1

    @@ -77,7 +74,6 @@
    -

    Waltz1Sus

    @@ -99,7 +95,6 @@
    -

    WaltzWalk

    @@ -117,7 +112,6 @@
    -

    WaltzWalkSus

    @@ -136,7 +130,6 @@
    -

    Waltz1Walk

    @@ -156,7 +149,6 @@
    -

    Waltz1WalkSus

    @@ -177,7 +169,6 @@
    -

    WaltzIntro

    @@ -196,7 +187,6 @@
    -

    Waltz1Intro

    @@ -215,7 +205,6 @@
    -

    WaltzEnd

    diff --git a/mma/docs/html/lib/stdlib/zydeco.html b/mma/docs/html/lib/stdlib/zydeco.html index a9bdaf1..6a77458 100644 --- a/mma/docs/html/lib/stdlib/zydeco.html +++ b/mma/docs/html/lib/stdlib/zydeco.html @@ -1,4 +1,4 @@ - +

    Zydeco

    @@ -13,7 +13,6 @@
  • ZydecoPlusEnd -

    Zydeco

    @@ -29,7 +28,6 @@
    -

    ZydecoPlus

    @@ -46,7 +44,6 @@
    -

    ZydecoSus

    @@ -63,7 +60,6 @@
    -

    ZydecoSusPlus

    @@ -81,7 +77,6 @@
    -

    ZydecoIntro

    @@ -97,7 +92,6 @@
    -

    ZydecoEnd

    @@ -113,7 +107,6 @@
    -

    @@ -225,7 +223,7 @@ just sets the variable $test with no value. @@ -233,15 +231,21 @@ just sets the variable $test with no value. + MIDISMF section here. + + +.mmaDB) is not updated, MMA will not be able to auto-load an unknown groove. Please refer to the detailed discussion - here for details. + here for details.


    @@ -272,7 +276,7 @@ The current installation of

    MMA will update the groove database with all files in the - current LIBPATH. All files must have a ``.mma'' + current LIBPATH. All files must have a ``.mma'' extension. Any directory containing a file named MMAIGNORE will be ignored. Note, that MMAIGNORE consists of all uppercase letters and is usually an empty file. @@ -283,18 +287,19 @@ The current installation of just in case something really goes wrong.

    +details here. @@ -326,21 +332,6 @@ The current installation of - - - - - - - - - - - - - - -

    ZydecoPlusEnd

    diff --git a/mma/docs/html/lib/yamaha/mambo.html b/mma/docs/html/lib/yamaha/mambo.html new file mode 100644 index 0000000..da3d8e9 --- /dev/null +++ b/mma/docs/html/lib/yamaha/mambo.html @@ -0,0 +1,309 @@ + + + +

    Mambo

    +

    Original file: mambo.sty ... insert your comments here! +

    + + + + +
    +

    Main-A

    + Good, basic beat. (4) +
    + + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-4 Piano1
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Fill-AA

    + An okay single bar fill for Main-A. (1) +
    + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-4 Piano1
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Fill-AB

    + Single bar horn fill. (1) +
    + + + + + + + + + + + + +
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-4 Piano1
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Intro-A

    + Good horns, but odd sounding piano/bass. (2) +
    + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-16 TenorSax
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-4 Piano1
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Openhighconga OpenHighConga
    Drum-Vibraslap VibraSlap
    +
    + + + + +
    +

    Ending-A

    + Rolling drums and final horns. (1) +
    + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-16 TenorSax
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-4 Piano1
    Drum-Lowconga LowConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    +
    + + + + +
    +

    Break-AA

    + A nice transition section. (2) +
    + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-4 Piano1
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Main-B

    + Nice variation of main pattern with horn section. (4) +
    + + + + + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-16 TenorSax
    Bass-3 TenorSax
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-2 BrassSection
    Drum-Cabasa Cabasa
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Fill-BA

    + Abrupt horns. Good for ending loop-back. (1) +
    + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-2 BrassSection
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Mutehighconga MuteHighConga
    Drum-Ridecymbal2 RideCymbal2
    +
    + + + + +
    +

    Fill-BB

    + Sharp horns make this a possible intro. (1) +
    + + + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Chord-2 BrassSection
    Drum-Cabasa Cabasa
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Intro-B

    + Decent enough introduction. (2) +
    + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-16 TenorSax
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Drum-Cabasa Cabasa
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    +
    + + + + +
    +

    Ending-B

    + Pretty busy, but might be okay with a slower tempo. (1) +
    + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highbongo HighBongo
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + + + +
    +

    Break-BB

    + Good fill with drums on bar 1 and horns on 2. (2) +
    + + + + + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-13 JazzGuitar
    Bass-9 Piano1
    Chord-12 Piano1
    Chord-15 BrassSection
    Drum-Cabasa Cabasa
    Drum-Claves Claves
    Drum-Cowbell CowBell
    Drum-Highagogo HighAgogo
    Drum-Highbongo HighBongo
    Drum-Hightimbale HighTimbale
    Drum-Lowbongo LowBongo
    Drum-Lowconga LowConga
    Drum-Lowtom2 LowTom2
    Drum-Maracas Maracas
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    +
    + + diff --git a/mma/docs/html/lib/yamaha/quando-g.s280.html b/mma/docs/html/lib/yamaha/quando-g.s280.html new file mode 100644 index 0000000..83980ac --- /dev/null +++ b/mma/docs/html/lib/yamaha/quando-g.s280.html @@ -0,0 +1,332 @@ + + + +

    Quando-G.S280

    +

    Converted from QUANDO-G.S280.sty. A nice, light samba. Use in a tempo range from 80 to 100 bpm (faster than that it sounds too busy). Library filename: yamaha/quando-g.s280.mma. +

    + + + + +
    +

    Main-A

    + Steady Samba beat. (8) +
    + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-9 Piano1
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Fill-AA

    + Good fill for repeats with Main-A. (1) +
    + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-13 CleanGuitar
    Chord-15 Marimba
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Intro-A

    + A one bar intro with a heavy hit on beat 1. (1) +
    + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Mutehighconga MuteHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Ending-A

    + Good ending to go with Main-A. (2) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Main-B

    + Adds horn section to Main-A. (8) +
    + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Mutehighconga MuteHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Fill-BB

    + Fill for Main-B. (1) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-13 CleanGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Fill-BA

    + Simple fill with horns. (1) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-13 CleanGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Intro-B

    + This is an 8 bar introduction. The first 6 bars are a just a Main-A, but bars 7 and 8 have the anticipated hits. (8) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Ending-B

    + This 8 bar ending duplicates Main-B with a single bar "ending". (8) +
    + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Highagogo HighAgogo
    Drum-Lowagogo LowAgogo
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Main-C

    + Pretty much like Main-B, but the horns are softer. (8) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Fill-CC

    + Abrupt fill with hit on 1. (1) +
    + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-9 Piano1
    Drum-Mutehighconga MuteHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Intro-C

    + Pretty much like Intro-B. (8) +
    + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Ending-C

    + This 8 bar ending duplicates Main-C with an "end" on the last bar. (8) +
    + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Highagogo HighAgogo
    Drum-Lowagogo LowAgogo
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Main-D

    + Much like Main-A, but a bit brighter percussion. (8) +
    + + + + + + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-13 CleanGuitar
    Chord-15 Marimba
    Chord-9 Piano1
    Drum-Handclap HandClap
    Drum-Highagogo HighAgogo
    Drum-Lowagogo LowAgogo
    Drum-Lowconga LowConga
    Drum-Mutehighconga MuteHighConga
    Drum-Openhighconga OpenHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + + + +
    +

    Fill-DD

    + Loud fill with a brass hit on beat 1. (1) +
    + + + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 SteelGuitar
    Chord-15 Marimba
    Chord-16 BrassSection
    Chord-9 Piano1
    Drum-Mutehighconga MuteHighConga
    Drum-Shaker Shaker
    Drum-Tambourine Tambourine
    +
    + + diff --git a/mma/docs/html/lib/yamaha/w-rock.html b/mma/docs/html/lib/yamaha/w-rock.html new file mode 100644 index 0000000..7c83c1f --- /dev/null +++ b/mma/docs/html/lib/yamaha/w-rock.html @@ -0,0 +1,165 @@ + + + +

    W-Rock

    +

    A very basic rock style. Original file: w-rock.sty. Library filename: yamaha/w-rock.mma. +

    + + + + +
    +

    Intro-A

    + A drum-only intro. Probably not that useful? (1) +
    + + + +
    Drum-Closedhihat ClosedHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Main-A

    + Good rhythm with drums and guitar. (2) +
    + + + + + + + + +
    Bass-11 FingeredBass
    Bass-14 MutedGuitar
    Chord-12 Piano1
    Chord-13 OverDriveGuitar
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Fill-AB

    + Fill sounds pretty much like MAIN-A pattern. (1) +
    + + + + + + + + +
    Bass-11 FingeredBass
    Bass-14 MutedGuitar
    Chord-12 Piano1
    Chord-13 OverDriveGuitar
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Main-B

    + Much like "A" with an added horn section. (4) +
    + + + + + + + + + + +
    Bass-11 FingeredBass
    Bass-14 MutedGuitar
    Bass-15 BrassSection
    Bass-16 AltoSax
    Chord-12 Piano1
    Chord-13 OverDriveGuitar
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Ending-A

    + Single bar ending. Not too final sounding. (1) +
    + + + + + + +
    Bass-14 MutedGuitar
    Chord-13 OverDriveGuitar
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Ending-B

    + A drum-only ending. (1) +
    + + + + +
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Fill-AA

    + Okay fill or change bar. (1) +
    + + + + + + + + +
    Bass-11 FingeredBass
    Bass-14 MutedGuitar
    Chord-12 Piano1
    Chord-13 OverDriveGuitar
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Fill-BA

    + A cymbal crash on beat 1 creates a fill. (1) +
    + + + + + + + +
    Bass-11 FingeredBass
    Chord-12 Piano1
    Drum-Crashcymbal1 CrashCymbal1
    Drum-Kickdrum1 KickDrum1
    Drum-Pedalhihat PedalHiHat
    Drum-Snaredrum1 SnareDrum1
    +
    + + + + +
    +

    Fill-BB

    + No drums, just bass and piano. (1) +
    + + + +
    Bass-11 FingeredBass
    Chord-12 Piano1
    +
    + + diff --git a/mma/docs/html/lib/yamaha/western.html b/mma/docs/html/lib/yamaha/western.html new file mode 100644 index 0000000..b492cc6 --- /dev/null +++ b/mma/docs/html/lib/yamaha/western.html @@ -0,0 +1,236 @@ + + + +

    Western

    +

    Original file: WESTERN.STY. Try this if you like a classic fiddle or banjo sound. Library file: yamaha/western.sty. +

    + + + + +
    +

    Main-A

    + A bit like a train taking off. (2) +
    + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Drum-Kickdrum2 KickDrum2
    Drum-Ridebell RideBell
    Drum-Scratchpush ScratchPush
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Fill-AA

    + A fill which sounds better than the main pattern. (1) +
    + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Ridebell RideBell
    Drum-Scratchpush ScratchPush
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Fill-AB

    + Goes well with the train. (1) +
    + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Intro-A

    + A pluck on 1,2,3 with added snare. (1) +
    + + + + + +
    Bass-9 Piano1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Snaredrum2 SnareDrum2
    Drum-Squareclick SquareClick
    +
    + + + + +
    +

    Ending-A

    + A banjo run with a final chord. (1) +
    + + + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Crashcymbal1 CrashCymbal1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Midtom1 MidTom1
    Drum-Ridebell RideBell
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Main-B

    + Very blue-grassy with picked banjo. (4) +
    + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Kickdrum2 KickDrum2
    Drum-Ridebell RideBell
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Fill-BA

    + Somehow the train is running over the banjo. (1) +
    + + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Hightom1 HighTom1
    Drum-Kickdrum2 KickDrum2
    Drum-Ridebell RideBell
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Fill-BB

    + And I thought the banjo had been run over. (1) +
    + + + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Ridebell RideBell
    Drum-Scratchpush ScratchPush
    Drum-Snaredrum2 SnareDrum2
    Drum-Sticks Sticks
    +
    + + + + +
    +

    Intro-B

    + A banjo introduction. (4) +
    + + + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Midtom1 MidTom1
    Drum-Midtom2 MidTom2
    Drum-Ridebell RideBell
    Drum-Snaredrum2 SnareDrum2
    +
    + + + + +
    +

    Ending-B

    + Fiddle sounding end. Okay. (1) +
    + + + + + + + + + + + + + +
    Bass-11 AcousticBass
    Bass-13 CleanGuitar
    Bass-14 Violin
    Bass-15 Banjo
    Bass-9 Piano1
    Chord-12 SteelGuitar
    Chord-16 Piano1
    Drum-Crashcymbal1 CrashCymbal1
    Drum-Crashcymbal2 CrashCymbal2
    Drum-Kickdrum2 KickDrum2
    Drum-Midtom1 MidTom1
    Drum-Snaredrum2 SnareDrum2
    +
    + + diff --git a/mma/docs/html/mma.html b/mma/docs/html/mma.html index 549ba5c..23fcec5 100644 --- a/mma/docs/html/mma.html +++ b/mma/docs/html/mma.html @@ -48,7 +48,7 @@ and may not completely reflect all the details in the originals. version is created with mklibdoc.py, supplied with the binary distribution.

    This page and all the other MMA materials are the responsibility of - Bob van der Poel . + Bob van der Poel . diff --git a/mma/docs/html/ref/img1.png b/mma/docs/html/ref/img1.png index f1cea8765647a9d387cf4e7918c66b7ec4d66d1c..effeab0650648305e6d306ff0fd5f50e484c5733 100644 GIT binary patch delta 9 QcmaFPc!hC7;>40-02O2eCjbBd delta 26 hcmcb@_?&S`sfMjm-_Yik#Y;=qY!py+HsJiUfLLf&yz$e7@?%lgHXU;4yFAoh3 zefRF&nKNeu1qD~FTGi3fk(QSB|NnoWLM0_7quqZ`09lMBL4Lsu4$p3+0XZ?AE{-7_ zGm|5ZZjj;#XMD)i#_OA{Lv0mGUK zGpYTv8md^@0(J*zx@!w;bx##{5onEKSoY22O;g7G))cOZA`Bw)Cy2M4&OZgThr!d; K&t;ucLK6Usuu6&m literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!py+HIN7jhACRLJ;1l9{_wL=9GiR2UmxqRi zzI*phP*8Bys#P5w9cgK4|NsAYad81ER8msfy?eK2t3)l3!&nmJ7tG-B>_!@p!(QU) z>&m{7M_%08+C`!`5Gd5->Eal|G1Ihrqu?O}9@ndvFQl>bJ9sm{oZKWS(Wu&@&#JG& z>KyRo1e1(#K_r`}+P=@1KVRRzV3C%Ge#-2ex3}(O?m2#MGtV&-$@O=7MSZ3TRNjnh zI-YW-BDm7!^6&VzRbQ_AU)cI}RlD!!>v}IY>+NcP8e($LqW#{Uy1LzUadl~RpI^jO UaP%_T0$s!4>FVdQ&MBb@0Pz-Tod5s; diff --git a/mma/docs/html/ref/img12.png b/mma/docs/html/ref/img12.png index 9bca1ba237e40871e70c474f82a97d19c6aa49ee..ac5ae8a83a9c3525d0949d9dd359aab1390f4683 100644 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!py+HIN7jhACRLJ;1l9{_wL=9GiR2UmxqRi zzI*phP*8Bys#P5w9cgK4|NsAYad81ER8msfy?eK2t3)l3!&nmJ7tG-B>_!@p)8y&m z7{W2rw0ooAAp;)QtCugNvGhB5GryeNBq`CT+M>^@ufpma@Z!py+HsJiUfLLf&yz$e7@?%lgHXU;4yFAoh3 zefRF&nKNeu1qD~FTGi3fk(QSB|NnoWLM0_7quqZ`09lMBL4Lsu4$p3+0Xgg?p1!W^ z8+qi#t*u=oiUWZ{F`h1tAsjQ4BaUv6;s|Ga$kfK`u!DgkocSVKTd2bphOTLiCy#Oq zC@E~=T9GTx@xJN7idX@|nhGi zb;069EZpP^@(DK1W|K|AEvSVH^XBn*v$Hen0HFioQ2Fv%=O#vV-tK7XC=3*apJB98nlmJD5vTfmaP~GqVVp}!&Yz1(d+u^ k?3CJeXWP<$i-qNU1HF7|P#fUffB*mh07*qoM6N<$f;@bzxc~qF delta 384 zcmV-`0e}9+1Hc0ziBL{Q4GJ0x0000DNk~Le0000=0000M1Oos70phhMSdk%1e*gz` zNliruu?!y47+zf+u+RrWAEO*fnm$Mjq@9z?A<-s2ms`|e_Z3s}@)0aR19=Ql{zrrHV5vlnitjV;_g?@oH@ zRiMD^9nZtcW5b^AX1{t}>h2|wstwA!^>>`!?X&yecJJLAqQL?MyLYqhR^BbRd&}wl zuN6TyZg~4_x9+Rb-H-2eZ>%-j!wnV?znpzw_wMlSeYP)lhf5>e_4gJQC+)wxn!0`@ eUKM71U;zL*x=K#9`pdik0000%eZC$ diff --git a/mma/docs/html/ref/img14.png b/mma/docs/html/ref/img14.png index 99cf23151632942374905160694149e7c907f914..763679b56436e40c6ec5f86755c1fa3cc2324ad7 100644 GIT binary patch literal 298 zcmV+_0oDGAP)4gdfE07*qoM6N<$f-r-6cK`qY literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+q!py+HD6?s%5RjuD;1l9{_wL=9GiR2UmxqRi zzI*rX%$YNSf`Y47tx8Kv`~UyHi;D|T;qKkLr#=Y*>1Qkn@(X5gcy=QV$YC$>^mS$5 z$RjUqZS5ja90(MO_H=O!;h32`S*bM>X@ZM7m6pKcc1+w6p5n`yeY{L*+znw{P-!|^qyM9-9?he}Y z@#O|wdZ{GVy?gg;u-JYS;cB2*b>5ag?z$?ox9^V5+ZOG~eR>1KwtZXTH+=*;E&FxC z&fVOzU%Nrf`;E{UO{x3tVt@-+)L{WsQ?=(eNY$p=3D2_^Zm5kd+&%A3dg)c5!0a8* z!^&gBp6+J9dR^-7C6KBO%DeSo&-5a980tLHwv+mw4xO>a#{jU{4Hg0(P zY`5;K(%p~mb#JUS+rteO5Wk##VE69u?tQi|c85zN-1YYs7ANh$yPCRwBwiI}d|&|p XIl4+twff7v00000NkvXXu0mjfZPm`W delta 215 zcmZ3>{D{%IGr-TCmrII^fq{Y7)59eQNDBb5C<`+K1LG-i=W-xNJ-{c#_3qufGiS~$ zFE4-h?wzr*@tHGcCOV4Npa1w}KTri@NswPKgTu2MX+REpiKnkC`$islacgTAiQ+(@ zP?)ESV+hC0Xe2`69V41Qkn@(X5gcy=QV$cgrJaSY*@ znLOj9!R$meo+_g=b2y!~CDq=$JUYiBe8=I@6CMk3C!YpE?ZzV^{tAZG{1YzBF=2ES zn>&Lu{mjc2qZA`Wp6fHC5B9vAYAoI;F}ZC1oUPTWv-IBZFhqtVvAs6@Ap*39!PC{x JWt~$(698-gONIad literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRv!py+HcuL&49LO;U@Ck9fd-v|lnKR4F%R@s$ z-@SWhY;1hy%o#yJ!BwkPb#!#3rKSD<|KG*M1*lv}Non`)-K}D&vOo@FNswPKgTu2M zX+REpiKnkC`$islacgTAiQ+(@P_n0sV+hC04aFLu0*-qX10rbF2G9EFcn+I*!3Os8&?Jv%d#IYDsk-Fvqbj!oNL vzWHF#?y&ru`n)M`_E&#@=Nl5cLxQ2LsysUC<-+ek>li#;{an^LB{Ts5s7GVh diff --git a/mma/docs/html/ref/img17.png b/mma/docs/html/ref/img17.png index 99b68e53399c959d494a5853afff5bff3e1e70e1..2be0cf7df95113fa0b8165ca4eb17f867f96b182 100644 GIT binary patch delta 195 zcmZ3mdKI;Vst0PzSxbN~PV literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^qChOp!py+HnD|Z80?084@Ck9fd-v|lnKR4F%R@s$ z-@SWhY;1hy%o#yJ!BwkPb#!#3rKSD<|KG*M1*lv}Non`)-K}D&vOo@FNswPKgTu2M zX+REpiKnkC`$islacgTAiQ+(@&=gM>#}J9B$v5^kCgw9SPjFdayj$|yy?bXjRGV|; zC)_9&TcIM}@jjQ~vtot$j9Xh=#a-Us(!Jd)&=OGY_<*T}UAg#N!F#rqY#VFy^LGPv zZT+8@+4i?QKks($DxppmX_iFg+Z(FC=W6`^{Z3cSpzO%Dn|I3f8gE*!Du4HF-(LPR s_pa~VUHV-#vn4L2_`|06hYqqb6moBCT>08#2GD&Bp00i_>zopr00kv^0ssI2 diff --git a/mma/docs/html/ref/img18.png b/mma/docs/html/ref/img18.png index d91c99e5d2f230d5840f2339bf2c3b644a03e416..02455238377884cbcdf2d525315e748aed725b87 100644 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRv!py+HcuL&49LO;U@Ck9fd-v|lnKR4F%R@s$ z-@SWhY;1hy%o#yJ!BwkPb#!#3rKSD<|KG*M1*lv}Non`)-K}D&vOo@FNswPKgTu2M zX+Tc0r;B3<$IRp#XBir!9iF7M-QB$~<9}Y;+uee9?(TLxa&7J%p55hd8VWCVyp7(| zxap=t*!LWTk5$@yr3Or=Zj?PcGm|+%aP8fDw-k;|+g-l-V9@Tc{G0l`DR1^ye}Cs2 d61zi!p{=SsI_l-Z??CGqJYD@<);T3K0RRz#U-19{ delta 267 zcmaFLxQNN9Gr-TCmrII^fq{Y7)59eQNQ(loI14ia17qShO$#7LE5Ikj_3qufGiS~$ zFE5{Hs#w2mzxz6%1Y=2%UoeBivm0qZ4tt5GuPggT9(i$VYZr;)K%mfMPZ!4!iK)pE zTN@IuGO`KmY`$o0gOd=Q!NC5lIBahNRYq!{gfX3v0`oZG_|u5wX2$mV$CgxQ)X=2ZQ! zJ&*PHh-PMH z|Ns9)L_`1p03sqHySuxE7G)g(0004WQchC7LEr*}2P1RN zaPJ1G2C;o_Z@bN~d$s>=X@>oGZ*JR-suGC=8w6n^+pv50Z7BQu?ky%TcEq;X+;=X4 z**mIt?)JXD56s@zy}Nby6={TCWOMMc@4~?a0C5YpfvM|Am;e9(07*qoM6N<$f_&a{ AC;$Ke delta 249 zcmV3?COeJ46_BQ2+n{hDk(0 zR2Y?Gm^p!A<^~232}d($GR&Se6HLzp@jE9lOxZetVeZxm5OO|54TKT{Q`2Y7ltdB) zQ@cT61B3@BZ|;PXQ>ShPl9iLT&t#aibM?uYXetpT*dPcS*@l_3;cTy!aQ0M|owHYK zLfF>3_s*Vq63o6db7s?QM}%HvbMUiw!@&js{a2bMy37q%00000NkvXXu0mjfL2_mu diff --git a/mma/docs/html/ref/img2.png b/mma/docs/html/ref/img2.png index 2e46384ec7598d9e8566d6e537b428f89df6edc0..2d8f92f12bebbc7254c2421afe947a116e0bd805 100644 GIT binary patch delta 9 QcmZ3-G@EHc`oyX&01`(81ONa4 delta 26 hcmbQuw2o;)x&V8Lr>`sfMjm-_Yik#Y;=qY1+W}@W2j>6) diff --git a/mma/docs/html/ref/img20.png b/mma/docs/html/ref/img20.png index 80f2d562cc287451ec04e820bdb4848d09e00524..ab5197d1cc93ab2cefcdf3d642368c3654f5bb1c 100644 GIT binary patch delta 248 zcmZ3^)X!wp8Q|y6%O%Cdz`(%k>ERLtq(y;PoQ0Wzfidx$rUj6r72p%%diU<#nKNgW zmzPg8Rjl8(-+diWg0UpXFPOpM*^M+HXR@b@V~E7mw&6q^zAbW2xa zsF=WdriZLN-HwO6#SPYo#xgu}{-9-$x+6=hW7pPnFZu}VoE-UO!yMT zqqI0omUU8$c0aS{OwR3L3s<=)9b|L7al&j(6mzP+?bn`1dze$RnO@GajY{~oGBo?# wo5)h`GkKj+^L88)SSWr|=Fc1Bf&vBxjsB%qUcdI93UnWXr>mdKI;Vst02m!wQvd(} literal 295 zcmV+?0oeYDP)O~X0001zNkl5bJFK^C5UQnA*9U7esB^{k9t+2%+wRzy&nH-G8rx zsm;4zgRR{C>^6|n-tR39wEgarZM)G;!EGi4z}UB;Y+mmTK`^%E?%jLuTmrLqMDO0c t==MG^d*AO3>e*MM5qgo$!OOmj008n4z^2$Y9Fzb6002ovPDHLkV1grDen$WR diff --git a/mma/docs/html/ref/img21.png b/mma/docs/html/ref/img21.png index 442957c4e3426d963fe365383c5b87687c9e51e1..34f8a5220f862fbbc77bd8eeb1303a928328080a 100644 GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^qChOp!py+HnD|Z80?5${@Ck9fd-v|lnKR4F%R@s$ z-@SWx=FAyELBUn4R;8t-{r~^p#l;1vP)SK?_wL=6!VM>Z9LAC$zhDN3XE)M-oHkDv z#}J9B$ule)6Q8lM32?d_ryHG_XDaM-p5>#px`EG4tH#84*Ej|2TzFfAn1e5;pPk|& z#1g#QF@d>-T|NI@%jDqYd90JBPTqDtWyY4`uP0|_XbGy^P~ech**0_Y!<_X~3%-R+ zo4YwY+v&!&-QUm6s}wr3&!jl*a*lgTTuSkW&E5+`zCOOzyt4n_=(m-3+^TgYX81y?23l zFA(c(0P`VuH<;SFn-@fF+Wod0Aqb)Fg1`kd!QFqagQ?BCUxTgO{p>c7(%$ba4Yd94 zlWn`vO~Gv@1i;w0p=@674M8xr`+C<`+K1Eb8QnL)pF|XU?2i zUS9t0-8*Ar<1=T@Omvi}mt4^03RJ;Z666=m;PC858j!+}hejqBsyJ z6zA#U7{W0#dB({GmgNR#=5V?eryHG_+4WX?&4q$rgM z6V|W@sXr9D(K$2V*p<-LVQX2sGtSJJ$(iJHZ|`hj9aHCGriin5?n+xo3qM22WQ%mvv4FO#lr`PNDz+ diff --git a/mma/docs/html/ref/img23.png b/mma/docs/html/ref/img23.png index 27b49bc8d4567b0a3c44a6f03033113523187e3c..d1a9663a506b4c7492f9ec0dd0a0b7712c5470cb 100644 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRv!py+HcuL&49LUiM@Ck9fd-v|lnKR4F%iq0w zXKZYI=FAyELBUn4R&{iAq@|_(|Nq~`#RaHVNl9tje)n}i7Gp_}UoeBivm0qZPL!vM zV+hC0?THSv?`ukaGrOcKQ2zYOIE5BVYjSMSd#k_8CC-@2ak_95!z=d+<5q=F$v}%4JYD@<);T3K0RXqhSG52D diff --git a/mma/docs/html/ref/img24.png b/mma/docs/html/ref/img24.png index 4120bfa5e8bb33ef205986311edd77fc1acff7d2..22b6ccf5d5385c13cc0e16658977bb0e49016bfe 100644 GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+q!py+HD6?s%5Rju4;1l9{_wL=9GiR2Um%n@W z&e+)a%$YN*R;}vj=txUT`~UyHi;D|Tp^}o)?%lg37j(G-IgBMie!&b5&u*jvIdPsY zjv*W~lV_Z4U|DW(W)7!oak|l&nVk>L&EZs9=CdVbhNbwqRw3a9N9LS#NQzRKFkuag zkorTR8=W%)j$H{|9k!OGJLAlpnVd;J_x8>f)-iQ1W{Nm_=dSgI(uYY543Yea%c9b} R{sL`c@O1TaS?83{1OTJqQlS6< literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRv!py+HcuL&49LUiP@Ck9fd-v|lnKR4F%R@s$ z-@SWhY;1hy%o#yJ!BwkPb#!$6|Nq~`#RaHVNl9tUoeBivm0qZPOhhmV+hC0 z494v8_xIFT4OeAe)so}LKD;Wl{J@%4wV>74)pF|XU?2C zQAeWw|Ns9kE-pZEB_*ZZyLWqby3Pc07)yfuf*Bm1-ADs+*h@TpUD-GC$ctNByGRrV z0)=`#T^vIsrY1*hZAkQGVxHi#pn0{#wK-8oH)M%&FfTpNP{=EAK9=E`^9L=1two`{ z9Z_3Se8rsvoaQn%GG{cczBh+8xLd4YrD^2xX>*x^qE3f<>Lx^#KfAUm^u@9VX2MJf zZ-N8L-mPj~p72I?^{mZ)@=TkAPk;ab literal 0 HcmV?d00001 diff --git a/mma/docs/html/ref/img27.png b/mma/docs/html/ref/img27.png new file mode 100644 index 0000000000000000000000000000000000000000..015abd0e5ef4259bca434bf150e4e0b8775312ce GIT binary patch literal 268 zcmV+n0rUQeP)pl!iU50wr>`sfMjm-_Yik#Y;=qZCwE%LN2rB>p diff --git a/mma/docs/html/ref/img4.png b/mma/docs/html/ref/img4.png index 1e711fd102353e966a9cf8a882cdf8b825d7b90c..0bde52fa440d45014509b606cc0c63585ed5ef8b 100644 GIT binary patch delta 9 QcmX@lxQB5<(8Sa%026@&&;S4c delta 26 hcmdnPc%E@WkN|s$r>`sfMjm-_Yik#Y;=qaixd3WM2eSYG diff --git a/mma/docs/html/ref/img5.png b/mma/docs/html/ref/img5.png index 6a406ee6adb430f98161c58d406562c71d0bb3c6..845f3e6c67e5f4b5486e1030111b22003512aca0 100644 GIT binary patch delta 9 QcmaFGc%5-V%Ea`sfMjm-_Yik#Y;=qZCWdLzB2o?YU diff --git a/mma/docs/html/ref/img6.png b/mma/docs/html/ref/img6.png index cc7d1d5126b3947aef4813f03327cbb4f3dcf64f..d0059cf29b50c3c0ae45d92033b3ba1f10b65d77 100644 GIT binary patch delta 9 Qcmcc0c!+UA%Ea`sfMjm-_Yik#Y;=qZCi2!W{2iE`q diff --git a/mma/docs/html/ref/img7.png b/mma/docs/html/ref/img7.png index 12468cea5e185e29e0c3a4bfa9e687358d7328b9..03b6063d91497beeb1be87a09d3c1fae3766acea 100644 GIT binary patch delta 9 QcmeBU`pq~Yabn3V026}*9RL6T delta 26 hcmey(*vB*>QGmU~)7O=KBaghewY7^xap1(bxd3c62mk;8 diff --git a/mma/docs/html/ref/img8.png b/mma/docs/html/ref/img8.png index 6481bb040a4c6a2e9f06ed470f57219b8046347a..5126e6046ce1746de8ee7af1c96d74a7c640a02c 100644 GIT binary patch delta 9 QcmdnMIG1rk+{8kA01>VOe*gdg delta 26 hcmbQsxPfs(oB(@?r>`sfMjm-_Yik#Y;=qZ~P5@;h2VwvK diff --git a/mma/docs/html/ref/img9.png b/mma/docs/html/ref/img9.png index c254496ae270d2d1c318b76b40727aba44641241..8589f07ce4dc8a46c90e45b291b93aea96550d32 100644 GIT binary patch delta 9 QcmaFBc$RTO;>40102J*65&!@I delta 26 hcmX@h_<(Ujq5yk|r>`sfMjm-_Yik#Y;=qY<`2cS82lW5| diff --git a/mma/docs/html/ref/index.html b/mma/docs/html/ref/index.html index 03c8c96..c7b8d6e 100644 --- a/mma/docs/html/ref/index.html +++ b/mma/docs/html/ref/index.html @@ -23,17 +23,17 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up previous
    - Next: Next: Overview and Introduction - Up: Up: Main MMA Reference

    @@ -50,7 +50,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    LOST LOGO + ALT="LOST LOGO">

    Reference Manual

    @@ -58,7 +58,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    Bob van der Poel

    Wynndel, BC, Canada

    -

    October 15, 2006

    +

    March 7, 2007

    @@ -69,565 +69,579 @@ original version by: Nikos Drakos, CBLU, University of Leeds


    -
  • Patterns +
  • Including Existing Patterns in New Definitions +
  • Multiplying and Shifting Patterns
    -
  • Sequences
    -
  • Grooves
    -
  • Riffs -
  • Musical Data Format
    -
  • Lyrics
    -
  • Solo and Melody Tracks
    -
  • Chord Voicing -
      -
    • Voicing -
        -
      • Voicing Mode -
      • Voicing Range -
      • Voicing Center
      • Voicing Move + HREF="node11.html">Automatic Melodies: Aria Tracks
      • Voicing Dir + HREF="node12.html">Chord Voicing + + HREF="node12.html#SECTION001210000000000000000">Voicing +
        • ChordAdjust + HREF="node12.html#SECTION001211000000000000000">Voicing Mode
        • Compress + HREF="node12.html#SECTION001212000000000000000">Voicing Range
        • DupRoot + HREF="node12.html#SECTION001213000000000000000">Voicing Center
        • Invert + HREF="node12.html#SECTION001214000000000000000">Voicing Move
        • Limit + HREF="node12.html#SECTION001215000000000000000">Voicing Dir
        • NoteSpan + HREF="node12.html#SECTION001216000000000000000">Voicing Rmove +
      • Range + HREF="node12.html#SECTION001220000000000000000">ChordAdjust
      • DefChord + HREF="node12.html#SECTION001230000000000000000">Compress
      • PrintChord + HREF="node12.html#SECTION001240000000000000000">DupRoot
      • Notes -
      -
      + HREF="node12.html#SECTION001250000000000000000">Invert
    • Harmony -
        + HREF="node12.html#SECTION001260000000000000000">Limit
      • Harmony + HREF="node12.html#SECTION001270000000000000000">NoteSpan
      • HarmonyOnly + HREF="node12.html#SECTION001280000000000000000">Range
      • HarmonyVolume -
      -
      + HREF="node12.html#SECTION001290000000000000000">DefChord
    • Tempo and Timing -
        + HREF="node12.html#SECTION0012100000000000000000">PrintChord
      • Tempo + HREF="node12.html#SECTION0012110000000000000000">Notes +
      +
    • Time + HREF="node13.html">Harmony +
      • TimeSig + HREF="node13.html#SECTION001310000000000000000">Harmony
      • BeatAdjust + HREF="node13.html#SECTION001320000000000000000">HarmonyOnly
      • Fermata + HREF="node13.html#SECTION001330000000000000000">HarmonyVolume +
      +
    • Cut -
    -
    + HREF="node14.html">Tempo and Timing +
    -
  • Sequences
    -
  • Grooves
    -
  • Riffs -
  • Musical Data Format
    -
  • Lyrics
    -
  • Solo and Melody Tracks
    -
  • Chord Voicing -
      -
    • Voicing -
        -
      • Voicing Mode -
      • Voicing Range -
      • Voicing Center
      • Voicing Move + HREF="node11.html">Automatic Melodies: Aria Tracks
      • Voicing Dir + HREF="node12.html">Chord Voicing + + HREF="node12.html#SECTION001210000000000000000">Voicing +
        • ChordAdjust + HREF="node12.html#SECTION001211000000000000000">Voicing Mode
        • Compress + HREF="node12.html#SECTION001212000000000000000">Voicing Range
        • DupRoot + HREF="node12.html#SECTION001213000000000000000">Voicing Center
        • Invert + HREF="node12.html#SECTION001214000000000000000">Voicing Move
        • Limit + HREF="node12.html#SECTION001215000000000000000">Voicing Dir
        • NoteSpan + HREF="node12.html#SECTION001216000000000000000">Voicing Rmove +
      • Range + HREF="node12.html#SECTION001220000000000000000">ChordAdjust
      • DefChord + HREF="node12.html#SECTION001230000000000000000">Compress
      • PrintChord + HREF="node12.html#SECTION001240000000000000000">DupRoot
      • Notes -
      -
      + HREF="node12.html#SECTION001250000000000000000">Invert
    • Harmony -
        + HREF="node12.html#SECTION001260000000000000000">Limit
      • Harmony + HREF="node12.html#SECTION001270000000000000000">NoteSpan
      • HarmonyOnly + HREF="node12.html#SECTION001280000000000000000">Range
      • HarmonyVolume -
      -
      + HREF="node12.html#SECTION001290000000000000000">DefChord
    • Tempo and Timing -
        + HREF="node12.html#SECTION0012100000000000000000">PrintChord
      • Tempo + HREF="node12.html#SECTION0012110000000000000000">Notes +
      +
    • Time + HREF="node13.html">Harmony +
      • TimeSig + HREF="node13.html#SECTION001310000000000000000">Harmony
      • BeatAdjust + HREF="node13.html#SECTION001320000000000000000">HarmonyOnly
      • Fermata + HREF="node13.html#SECTION001330000000000000000">HarmonyVolume +
      +
    • Cut -
    -
    + HREF="node14.html">Tempo and Timing +
    • Swing + HREF="node14.html#SECTION001410000000000000000">Tempo
    • Volume and Dynamics -

      -Bob -2006-10-15 +bob +2007-03-07
      diff --git a/mma/docs/html/ref/mupex/arp4s.png b/mma/docs/html/ref/mupex/arp4s.png index e28181e08b074b4481ee75c015f2e496ce95703d..044231ee68a28472fc9dd9d50a7e176617a7350a 100644 GIT binary patch delta 3444 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 delta 2698 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 EM?jtkm;e9( diff --git a/mma/docs/html/ref/mupex/bassb8.png b/mma/docs/html/ref/mupex/bassb8.png index ee83a5295aa27d0bff45bda8d6cd81339b9bad6d..d39ec465fce3f98dad4adcd862b3683457ef3ca2 100644 GIT binary patch literal 4836 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 AR{#J2 diff --git a/mma/docs/html/ref/mupex/chord43.png b/mma/docs/html/ref/mupex/chord43.png index dca90aabee856b998d796aeb8cdb737bab332fa7..ad30247aa5a6e061a3924d1193c55fc7584f40d2 100644 GIT binary patch literal 5474 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 literal 3770 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 F{Re|N|Kk7v diff --git a/mma/docs/html/ref/mupex/cmajor.png b/mma/docs/html/ref/mupex/cmajor.png index 38e8f8253d5080c22ad5590db73952cc5aa7212c..c0642b1f7d0b30c898ee775b983900a94ef7d89e 100644 GIT binary patch literal 6218 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 L(`mfz`sBX=d2bFb literal 4179 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 E4+11^CjbBd diff --git a/mma/docs/html/ref/mupex/fermata2.png b/mma/docs/html/ref/mupex/fermata2.png index f9e5ab117a986aa845228f2aa678e0c34a1da007..7942da00737ab31c86126712678306d4b52b682d 100644 GIT binary patch literal 8269 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 literal 3723 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 IT)h?ZKZLO~r2qf` diff --git a/mma/docs/html/ref/mupex/soloeg.png b/mma/docs/html/ref/mupex/soloeg.png index 6350fa215522e3593d0053557cd49488bd67ccfd..ccd37263cdcc4dc0fd3692f25230efbc86a7aa8f 100644 GIT binary patch literal 8291 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 literal 9094 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 diff --git a/mma/docs/html/ref/mupex/swingdrum8-3.png b/mma/docs/html/ref/mupex/swingdrum8-3.png index ec241e78813e599068188687b51f95a6c279e596..81eb33ca600f85f804e8dcd58ada6f8b4c9565fb 100644 GIT binary patch literal 3682 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 literal 2466 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 diff --git a/mma/docs/html/ref/mupex/swingdrum8.png b/mma/docs/html/ref/mupex/swingdrum8.png index 405df9eeab86e0bf084d95f7e8bd3885c3438022..72b6386a7eb56c70c953515b2c23e1a0f1656a39 100644 GIT binary patch literal 2388 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 P(5lyvHxcDm9HRdVk1r`7 delta 4525 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 diff --git a/mma/docs/html/ref/mupex/tilde2.png b/mma/docs/html/ref/mupex/tilde2.png index 6dafab7c62d00a49fdb1b10892dcfa6ff799d248..2c25cd8b2fde2c2dfae8852696142ba957248087 100644 GIT binary patch literal 7205 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 LHPNlS35)y>A99}l delta 4971 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 HMD6|$<5^rD diff --git a/mma/docs/html/ref/mupex/trip3.png b/mma/docs/html/ref/mupex/trip3.png index f667ea3a0647edecc662f329bb89393e4ae75876..31562194bc38a33aee9b42b6506c0dd49a7a60c0 100644 GIT binary patch literal 5550 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 a4@_zZbXw6z&CKVK2NLP%p7NYg{eJ*KgML8( diff --git a/mma/docs/html/ref/node1.html b/mma/docs/html/ref/node1.html index 79eac85..4c6f582 100644 --- a/mma/docs/html/ref/node1.html +++ b/mma/docs/html/ref/node1.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
      - Next: Next: Running - Up: Up: Reference Manual - Previous: Previous: Reference Manual

      @@ -49,32 +49,32 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -87,9 +87,9 @@ Overview and Introduction

      Musical MIDI Accompaniment, MMA ,1.1 generates standard + HREF="#foot192">1.1 generates standard MIDI1.2 files which can be used as a backup track for a soloist. + HREF="#foot193">1.2 files which can be used as a backup track for a soloist. It was written especially for me--I am an aspiring saxophonist and wanted a program to ``play'' the piano and drums so I could practice my jazz solos. With @@ -121,7 +121,7 @@ License, Version and Legalities

      The program MMA was written by and is copyright Robert van der Poel, -2002--2006. +2002--2007.

      This program, the accompanying documentation, and library files can be @@ -140,40 +140,51 @@ The current version of this package is maintained at: http://www.mellowood.ca/mma/.

      -This document reflects version 1.0-rc2 +This document reflects version 1.1 of MMA .

      - - +
      -
      -
      Warning: This program - is currently in a beta state. The commands used in the - input files, the output, the overall logic and anything else you - can think of might change in the future. - + +
      +
      +
      This program + has recently changed its status from beta to a 1.x version. + I have done everything I can to ensure that the program functions + as advertised, but I assume no responsibilty for anything + it does to your computer or data. +

      -

      +


      -
      +

      -

      This manual most likely has lots of errors. Spelling, grammar, and -probably a number of the examples need fixing. Please give me a hand -and report anything...it'll make it much easier for me to -generate a really good product for all of us to enjoy. +
      Sorry for this disclaimer, but we live in paranoid times. +
      +

      +

      +
      +
      +
      +

      +

      This manual most likely has lots of errors. Spelling, grammar, and + probably a number of the examples need fixing. Please give me a hand + and report anything...it'll make it much easier for me to + generate a really good product for all of us to enjoy. -
      +
      -
      +

      -

      +


      -
      +

      -

      +
      +

      @@ -185,12 +196,12 @@ About this Manual This manual was written by the program author--and this is always a very bad idea. But, having no volunteers, the choice is no manual at all or my bad perspectives.1.3 + HREF="#foot232">1.3

      MMA is a large and complex program. It really does need a manual; and users really need to refer to the manual to get the most out of -the program. Even the author refers to the manual. Really. +the program. Even the author frequently refers to the manual. Really.

      I have tried to present the various commands in a logical and useful @@ -218,12 +229,12 @@ Typographic Conventions

    • -
    • Important stuff is emphasized: important. +
    • Important stuff is emphasized: important.

    • Websites look like this: http://users.xplornet.com/~bvdp + HREF="http://www.mellowood.ca/mma/index.html">http://www.mellowood.ca/mma/index.html

    • Filenames are set in bold typewriter font: filename.mma @@ -236,12 +247,12 @@ Typographic Conventions

      - - +
      + +
      + A command from a file -
      A command from a file
      - -
      +

    • @@ -251,12 +262,12 @@ Typographic Conventions

      - - +
      + +
      + $ enter this -
      $ enter this
      - -
      +

      @@ -341,7 +352,7 @@ many others are available for Linux systems. For Windows and Mac systems I'm sure there are many, many choices.

      -You'll need a text editor like vi, emacs, etc. to create +You'll need a text editor like vi, emacs, etc. to create input files. Don't use a word processor!

      @@ -352,7 +363,7 @@ input files. Don't use a word processor!

      • The executable Python script, mma1.4, must somewhere in your + HREF="#foot347">1.4, must somewhere in your path. For users running Windows or Mac, please check MMA website for details on how to install on these systems. @@ -374,16 +385,22 @@ input files. Don't use a word processor!

      -The script install will install +The scripts cp-install or ln-install will install MMA properly on most Linux -systems. It assumes that main script is to be installed in +systems. Both scripts assume that main script is to be installed in /usr/local/bin and the support files in /usr/local/share/mma. If you want an alternate location, you can edit the paths in the script. The only supported alternate to use is /usr/share/mma.

      -In addition, you can run +The difference between the two scripts is that ln-install creates +symbolic links to the current location; cp-install copies the files. +Which to use it up to you, but if you have unpacked the distribution in +a stable location it is probably easier to use the link version. + +

      +In addition, you can run MMA from the directory created by the untar. This is not recommended, but will show some of MMA 's @@ -392,7 +409,7 @@ stuff. In this case you'll have to execute the program file

      You should be ``root'' (or at least, you need write permissions in -/usr/local/) to run the install script. +/usr/local/) to run either install script.

      If you want to install @@ -430,12 +447,12 @@ To create a MIDI file you need to:

      - - +
      + +
      + $ mma myfile <ENTER> -
      $ mma myfile <ENTER>
      - -
      +

      will invoke @@ -466,7 +483,7 @@ An input file consists of the following information:

      1. MMA directives. These include TEMPO, TIME, - VOLUME, etc. Directives. + VOLUME, etc. Directives.

      2. @@ -500,7 +517,7 @@ Comments

        Proper indentation, white space and comments are a -good thing--and you really should use them. But, in most cases +good thing--and you really should use them. But, in most cases MMA really doesn't care: @@ -525,11 +542,11 @@ Proper indentation, white space and comments are a

        Each line is initially parsed for comments. A comment is anything following a ``//'' (2 forward slashes).1.5 + HREF="#foot315">1.5

        Comments are stripped from the input stream. Lines starting with the COMMENT directive are also ignored. See the -comment discussion for details. +comment discussion for details.

        @@ -545,17 +562,17 @@ a file which looked something like:

        - - +
        - -
        Tempo 120 + +
        + Tempo 120
        Fm
        C7 -
        ...
        +
        ... -
        +

        and end up with a MIDI file which played the specified chords over a @@ -634,7 +651,7 @@ of the chord or drum note can occur anywhere in the bar). To make the input files look more musical, MMA supports REPEATs and REPEATENDINGs. However, complexities like -D.S. and Coda are not internally supported (but can be +D.S. and Coda are not internally supported (but can be created by using the GOTO command).

        @@ -652,36 +669,36 @@ This means that the command:

        - - +
        + +
        + Tempo 120 -
        Tempo 120
        - -
        +

        could be entered in your file as:

        - - +
        + +
        + TEMPO 120 -
        TEMPO 120
        - -
        +

        or even

        - - +
        + +
        + TeMpO 120 -
        TeMpO 120
        - -
        +

        for the exact same results. @@ -694,12 +711,12 @@ The only exceptions are the names for chords, notes in SOLOs, and filenames. In keeping with standard chord notation, chord names are in mixed case; this is detailed in Musical Data. Filenames are covered in -Paths and Filenames. +Paths and Filenames.



        Footnotes

        -
        ...,...,1.1
        Musical MIDI Accompaniment and the short form @@ -709,14 +726,14 @@ are in mixed case; this is detailed in Musical no association between the two.
        -
        ... +
        ... MIDI1.2
        MIDI is an acronym for Musical Instrument Digital Interface.
        -
        ... perspectives.... perspectives.1.3
        The problem, all humor aside, is that the viewpoints of a program's author and user are quite @@ -724,14 +741,14 @@ different. The two ``see'' problems and solutions differently, and for a user manual the programmer's view is not the best.
        -
        ...mma...mma1.4
        In the distribution this is mma.py. It is renamed to save a few keystrokes when entering the command.
        -
        ... slashes).... slashes).1.5
        The first choice for a comment character was a single ``#'', but that sign is used for @@ -740,26 +757,26 @@ a user manual the programmer's view is not the best.

        - next - up - previous
        - Next: Next: Running - Up: Up: Reference Manual - Previous: Previous: Reference Manual
        -Bob -2006-10-15 +bob +2007-03-07
        diff --git a/mma/docs/html/ref/node10.html b/mma/docs/html/ref/node10.html index 01cceff..62b8326 100644 --- a/mma/docs/html/ref/node10.html +++ b/mma/docs/html/ref/node10.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
        - Next: Chord Voicing - Up: Next: Automatic Melodies: Aria Tracks + Up: Reference Manual - Previous: Previous: Lyrics

        @@ -49,22 +49,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -111,12 +111,12 @@ the top of a song:

        - - +
        + +
        + Solo Voice TenorSax -
        Solo Voice TenorSax
        - -
        +

        On the other hand, MELODY tracks save and restore grooves just @@ -125,15 +125,15 @@ in a song file:

        - - +
        - -
        Melody Voice TenorSax + +
        + Melody Voice TenorSax
        Groove Blues -
        ... musical data
        +
        ... musical data -
        +

        no one will be surprised to find that the MELODY track @@ -160,18 +160,18 @@ be covered later in this chapter):

        - - +
        - -
        Solo Riff 4c;2d;4f; + +
        + Solo Riff 4c;2d;4f;
        F
        Solo Riff 4.a;8g#;4a;4c+;
        -F
        +F -
        +

        In this example the melody has been added to the song file. @@ -185,14 +185,14 @@ rewritten as:

        - - +
        - -
        F {4c;2d;4f;} + +
        + F {4c;2d;4f;}
        -F {4.a;8g#;4a;4c+;}
        +F {4.a;8g#;4a;4c+;} -
        +

        By default the note data is inserted into the SOLO track. If @@ -211,7 +211,7 @@ The notes in a SOLO or MELODY track are specified series of ``chords''. Each chord can be a single note, or several notes (all with the same duration). Each chord in the bar is delimited with a single semicolon.10.1 + HREF="#foot4027">10.1

        Each chord can have several parts. All missing parts will default to the value in the previous chord. The various parts of a chord must be @@ -230,7 +230,7 @@ specified in the order given in the following table.

        Pitch
        The note in standard musical notation. The lowercase letters ``a'' to ``g'' are recognized as well as ``r'' to specify a - rest (please note the exception for Drum Solo Tracks, + rest (please note the exception for Drum Solo Tracks, here).

        @@ -240,7 +240,7 @@ specified in the order given in the following table. (sharp), ``&'' (flat) or ``n'' (natural). Please note that an accidental will override the current KEYSIG for the current bar (just like in real musical notation). Unlike standard musical - notation the accidental will apply to similarly named notes + notation the accidental will apply to similarly named notes in different octaves.

        @@ -275,9 +275,9 @@ Please note that when you specify a chord in WIDTH="19" HEIGHT="33" ALIGN="MIDDLE" BORDER="0" SRC="img4.png" ALT="$>$"> in the chord specification - (here) Of course, it is + (here) Of course, it is probably easier to set accented beats with the ACCENT - directive (here). + directive (here).

        @@ -313,12 +313,12 @@ space and tab characters (which are ignored by

        -
        - - +
        - Solo Notation -
        - + + +
        + Solo Notation +
        + Lost Image

        @@ -327,10 +327,9 @@ space and tab characters (which are ignored by

        - - +
        - -
        KeySig 1b + +
        + KeySig 1b
        F { 4ca-; 2da-; 4fd; }
        @@ -338,14 +337,16 @@ F { 4.af; 8g#f; 4af; c+f; }
        F { 4ca-; 2da-; 4fc; }
        -F { 1af; }
        +F { 1af; } -
        +

        -

        +

        @@ -378,14 +379,14 @@ It can be handled in three different ways in your score:

        • - - +
          - -
          F {4c;d;e;4+2f;} + +
          + F {4c;d;e;4+2f;}
          -F {2r;2c;}
          +F {2r;2c;} -
          +

          In this case you @@ -396,14 +397,14 @@ In this case you

        • - - +
          - -
          F {4c;d;e;4+2f~}; + +
          + F {4c;d;e;4+2f~};
          -F {2r;2c;}
          +F {2r;2c;} -
          +

          This time a ~ character has been added to the end of @@ -413,14 +414,14 @@ This time a ~ character has been added to the end of

        • - - +
          - -
          F {4c;d;e;4+2f~;} + +
          + F {4c;d;e;4+2f~;}
          -F {~2c;}
          +F {~2c;} -
          +

          The cleanest method is shown here. The ~forces the @@ -448,16 +449,16 @@ empty chord marker:

          - - +
          - -
          C {4c;d;e;4+2f~;} + +
          + C {4c;d;e;4+2f~;}
          C {~<>~;}
          -C {~2c;}
          +C {~2c;} -
          +

          @@ -477,18 +478,18 @@ confusion! For example, the following all generate four quarter note

          - - +
          - -
          Solo Riff 4f; 4f; 4f; 4f; + +
          + Solo Riff 4f; 4f; 4f; 4f;
          Solo Riff 4f; f; f; f;
          Solo Riff 4f; 4; 4; 4;
          -Solo Riff 4f; ; ; ;
          +Solo Riff 4f; ; ; ; -
          +

          @@ -515,12 +516,12 @@ set the key signature for the song:

          - - +
          + +
          + KeySig 2b -
          KeySig 2b
          - -
          +

          The argument consists of a single digit ``0'' to ``7'' followed by a @@ -551,16 +552,15 @@ command. This will accomplish two things:

          Setting the key signature effects the notes used in SOLO or MELODY tracks and sets a MIDI Key Signature event.10.2 + HREF="#foot4032">10.2

          To summarize, the following are all valid KEYSIG directives:

          - - +
          - -
          KeySig 2# Major + +
          + KeySig 2# Major
          KeySig 1b
          @@ -568,9 +568,10 @@ KeySig 0b Min
          KeySig F Min
          -KeySig A Major
          +KeySig A Major -
          +

          @@ -586,17 +587,17 @@ of ``{ }'' expressions in a chord line. They will be assigned to the tracks specified in the AUTOSOLOTRACKS directive.

          -By default, four tracks are assigned: Solo, Solo-1, -Solo-2, and Solo-3. This order can be changed: +By default, four tracks are assigned: Solo, Solo-1, +Solo-2, and Solo-3. This order can be changed:

          - - +
          + +
          + AutoSoloTracks Melody-Oboe Melody-Trumpet Melody-Horn -
          AutoSoloTracks Melody-Oboe Melody-Trumpet Melody-Horn
          - -
          +

          Any number of tracks can be specified in this command, but they must @@ -609,35 +610,35 @@ for tracks set as HARMONYONLY. Again, an example:

          - - +
          - -
          AutoSoloTracks Solo-1 Solo-2 Solo-3 Solo-4 + +
          + AutoSoloTracks Solo-1 Solo-2 Solo-3 Solo-4
          Solo-2 HarmonyOnly 3Above
          -Solo-3 HarmonyOnly 8Above
          +Solo-3 HarmonyOnly 8Above -
          +

          Of course, some voicing is also set ...and a chord line:

          - - +
          + +
          + C {4a;b;c;d;} -
          C {4a;b;c;d;}
          - -
          +

          -The note data {4a;b;c;d;} will be set to the Solo-1 +The note data {4a;b;c;d;} will be set to the Solo-1 track. But, if you've not set any other note data by way of -RIFF commands to Solo-2 and Solo-3, the note data +RIFF commands to Solo-2 and Solo-3, the note data will also be copied to these two tracks. Note that the track -Solo-4 is unaffected since it is not a +Solo-4 is unaffected since it is not a HARMONYONLY track. This feature can be very useful in creating harmony lines with the harmonies going to different instruments. The supplied file egs/harmony.mma shows an example. @@ -655,16 +656,16 @@ first thing to do is to set a track as a drum solo type:

          - - +
          + +
          + Solo-MyDrums DrumType -
          Solo-MyDrums DrumType
          - -
          +

          This will create a new SOLO track with the name -Solo-MyDrums and set its ``Drum'' flag. If the track already +Solo-MyDrums and set its ``Drum'' flag. If the track already exists and has data in it, the command will fail. The MIDI channel 10 is automatically assigned to all tracks created in this manner. You cannot change a ``drum'' track back to a normal track. @@ -690,12 +691,12 @@ Some examples:

          - - +
          + +
          + Solo-MyDrums Riff 4 SnareDrum1; ; r ; SnareDrum1; -
          Solo-MyDrums Riff 4 SnareDrum1; ; r ; SnareDrum1;
          - -
          +

          would create a snare hit on beats 1, 2 and 4 of a bar. Note how the @@ -703,12 +704,12 @@ second hit uses the default tone set in the first beat.

          - - +
          + +
          + Solo-MyDrums Riff 8,38;;;; -
          Solo-MyDrums Riff 8,38;;;;
          - -
          +

          creates 4 hits, starting on beat 1. Instead of ``names'' @@ -717,12 +718,12 @@ how ``,'' is used to separate the initial length from the first tone.

          - - +
          + +
          + Solo-MyDrums Riff 4 SnareDrum1,53,81; r; 4 SideKick ; -
          Solo-MyDrums Riff 4 SnareDrum1,53,81; r; 4 SideKick ;
          - -
          +

          creates a ``chord'' of 3 tones on beat 1, a rest on beat 2, and a @@ -744,10 +745,9 @@ the following example:

          - - +
          - -
          Begin Solo-Block + +
          + Begin Solo-Block
            DrumType
            Tone LowWoodBlock
          @@ -757,21 +757,20 @@ End Solo-Block Riff 4r; SnareDrum; * ; ;
             ...
          -Solo-Block Riff 4;;;;
          +Solo-Block Riff 4;;;; -
          +

          The first solo created will have a rest on beat 1, a SnareDrum on beat 2 and LowWoodBlock on beats 3 and 4. The second will have LowWoodBlock on each beat. -

          -



          Footnotes

          -
          ... semicolon.... semicolon.10.1
          I have borrowed heavily from the notation program MUP for the syntax used here. For notation I highly @@ -781,36 +780,36 @@ on each beat. HREF="http://www.Arkkra.com/">http://www.Arkkra.com/.
          -
          ... event.... event.10.2
          For the most part, MIDI Key Signature events are ignored by playback - programs. However, they may be used in other MIDI programs + programs. However, they may be used in other MIDI programs which handle notation.

          - next - up - previous
          - Next: Chord Voicing - Up: Next: Automatic Melodies: Aria Tracks + Up: Reference Manual - Previous: Previous: Lyrics
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node11.html b/mma/docs/html/ref/node11.html index acb5951..d19506e 100644 --- a/mma/docs/html/ref/node11.html +++ b/mma/docs/html/ref/node11.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Chord Voicing - +Automatic Melodies: Aria Tracks + @@ -26,1281 +26,259 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Harmony - Up: Next: Chord Voicing + Up: Reference Manual - Previous: Previous: Solo and Melody Tracks

          - -Subsections - - - -

          - +
          -Chord Voicing +Automatic Melodies: Aria Tracks

          -In music, a chord is simply defined as two more notes played -simultaneously. Now, this doesn't mean that you can play just any two -or three notes and get a chord which sounds nice--but whatever you do -get will be a chord of some type. And, to further confuse the unwary, -different arrangements of the same notes sound better (or worse) in -different musical situations. +ARIA tracks are designed to let +MMA automatically generate +something resembling melody. Honest, this will never put real +composers on the unemployment line (well, no more than they are mostly +there already).

          -As a simple example, consider a C major chord. Built on the first, -third and fifth notes of a C major scale it can be manipulated into a -variety of sounds: +You might want to use an ARIA to embellish a section of a song (like +an introduction or an ending). Or you can have +MMA generate a complete +melody over the song chords.

          -

          - Lost Image - -
          +In a traditional song the melody depends on two parts: patterns +(IE. note lengths, volume, articulation) and pitch (usually determined +by the chords in a song). If you have been using +MMA at all you will +know that that chords are the building block of what +MMA does +already. So, to generate a melody we just need some kind of +pattern. And, since +MMA already uses patterns in most things it +does, it is a short step to use a specialized pattern to generate a +melody.

          -These are all C major chords ...but they all have a different -sound or color. The different forms a chord can take are called -``voicings''. Again, this manual is not intended to be a primer on -musical theory--that's a subject for which lots of lessons with your -favorite music teacher is recommended. You'll need a bit of -basic music theory if you want to understand how and why -MMA creates its tracks. +It might serve to look at the sample song files enclosed in this +package in the directory egs/aria. Compile and play them. Not too bad?

          -The different options in this chapter effect not only the way chords -are constructed, but also the way bass lines and other tracks are -formed. +Just like other track, you can create as many ARIAs as you +want. So, you can have the tracks ARIA-1, ARIA, and +ARIA-SILLY all at the same time. And, the majority of other +commands (like OCTAVE, ARTICULATE, etc.) apply to ARIAs.

          -There are generally two ways in -MMA to take care of voicings. - -

          - -

            -
          1. use -MMA 's extensive VOICING options, most likely with - the ''Optimal'' voicing algorithm, - -

            -

          2. -
          3. do everything by yourself with the commands INVERT and - COMPRESS. - -

            -

          4. -
          - -

          -The commands LIMIT and DUPROOT may be used independently -for both variants. - -

          - -

          -Voicing -

          - -

          -The VOICING command is used to set the voicing mode and several -other options relating to the selected mode. The command needs to have -a CHORD track specified and a series of Option=Value pairs. For -example: - -

          - - -
          - -
          Chord-Piano Voicing Mode=Optimal Rmove=10 Range=9
          - -
          - -

          -In the following sections all the options available will be covered. - -

          - -

          -Voicing Mode -

          - -

          -The easiest way to deal with chord voicings is via the -VOICING MODE=XX option. - -

          -When choosing the inversion of a chord to play an accompanist will -take into consideration the style of the piece and the chord -sequences. In a general sense, this is referred to as ``voicing''. - -

          -A large number of the library files have been written to take -advantage of the following voicing commands. However, not all styles -of music take well to the concept. And, don't forget about the other -commands since they are useful in manipulating bass lines, as well as -other chord tracks (e.g., sustained strings). - -

          - -MMA has a variety of sophisticated, intelligent -algorithms11.1 to deal with voicing. - -

          -As a general rule you should not use the INVERT and -COMPRESS commands in conjunction with the VOICING -command. If you do, you may create beautiful sounds. But, the results -are more likely to be less-than-pleasing. Use of voicing and other -combinations will display various warning messages. - -

          -The main command to enable voicings is: - -

          - - -
          - -
          Chord Voicing Mode=Type
          - -
          - -

          -As mentioned above, this command can only be applied to CHORD -tracks. Also note that this effects all bars in the sequence ... -you cannot have different voicings for different bars in the sequence -(attempting to do this would make no sense). - -

          -The following MODE types are available: +The following commands are important to note:

          -
          Optimal
          -
          A basic algorithm which automatically chooses the best - sounding voicing depending on the voicing played before. Always try - this option before anything else. It might work just fine without - further work. - -

          -The idea behind this algorithm is to keep voicings in a sequence - close together. A pianist leaves his or her fingers where they are, - if they still fit the next chord. Then, the notes closest to the - fingers are selected for the next chord. This way characteristic - notes are emphasized. +

          Range
          +
          Just like scale tracks. A RANGE of 2 would let +MMA work on a 2 +octave chord, etc.

          -
          Root
          -
          This Option may for example be used to turn off - VOICING within a song. VOICING MODE=ROOT means nothing - else than doing nothing, leaving all chords in root position. +
          ScaleType
          +
          Much like a scale track. By default, the setting for this +is CHORD. But, you can use AUTO, SCALE or CHROMATIC. AUTO and SCALE +are identical and force +MMA to select notes from the scale associated +with the current chord; CHROMATIC generates an 11 tone scale starting +at the root note of the chord.

          -
          None
          -
          This is the same as the ROOT option. - -

          -

          -
          Invert
          -
          Rather than basing the inversion selection on an - analysis of past chords, this method quite stupidly tries to keep - chords around the base point of ``C'' by inverting ``G'' and ``A'' - chords upward and ``D'', ``E'' and ``F'' downward. The chords are - also compressed. Certainly not an ideal algorithm, but it can be - used to add variety in a piece. - -

          -

          -
          Compressed
          -
          Does the same as the stand-alone COMPRESS - command. Like ROOT, it is only added to be used in some parts - of a song where VOICING MODE=OPTIMAL is used. +
          Direction
          +
          As +MMA processes the song it moves a note-selection pointer +up or down. By default DIRECTION is set to the single value "1" which +tells +MMA to add 1 after each note is generated. However, you can set +the value to an integer -4 to 4 or the special value "r". With "r" a +random value -1, 0 or 1 will be used. Important: in an ARIA +track the sequence size/point is ignored for DIRECTION.

          - -

          -Voicing Range -

          +A bit more detail on defining an ARIA:

          -To get wider or closer voicings, you may define a range for the -voicings. This can be adjusted with the RANGE option: +First, here is a simplified sample track definition:

          - -
          - -
          Chord-Guitar Voicing Mode=Optimal Range=12
          - -
          - -

          -In most cases the default value of 12 should work just fine. But, you -may want to fine tune ...it's all up to you. This command only -effects chords created with MODE=OPTIMAL. - -

          - -

          -Voicing Center -

          - -

          -Just minimizing the Euclidean distance between chords doesn't do the -trick as there could be runaway progressions that let the voicings -drift up or down infinitely. - -

          -When a chord is ``voiced'' or moved to a new position, a ``center -point'' must be used as a base. By default, the fourth degree of the -scale corresponding to the chord is a reasonable choice. However, you -can change this with: - -

          - - -
          - -
          Chord-1 Voicing Center=<value>
          - -
          - -

          -The value in this command can be any number in the range 0 to -12. Try different values. The color of your whole song might change. - -

          -Note that the value is the note in the scale, not a chord-note position. - -

          -This command only effects chords created with MODE=OPTIMAL. - -

          - -

          -Voicing Move -

          - -

          -To intensify a chord progression you may want to have ascending or -descending movement of voicings. This option, in conjunction with the -DIR optional (see below) sets the number of bars over which a -movement is done. - -

          -For the MOVE option to have any effect you must also set the -direction to either -1 or 1. Be careful that you don't force the chord -too high or low on the scale. Use of this command in a REPEAT -section can cause unexpected results. For this reason you should -include a SEQ command at the beginning of repeated sections of -your songs. - -

          -In most cases the use of this command is limited to a section of a -song, its use is not recommended in groove files. You might want to do -something like this in a song: - -

          - - - +
          - -
          ..select groove with voicing + +
          + Begin Aria
          -chords.. +Voice JazzGuitar
          -Chord-Piano Voicing Move=5 Dir=1 +Volume f
          -more chords.. +Sequence 1.5 8 90; 2 8 90; 2.5 8 90;
          -Chord-Piano Voicing Move=5 Dir=-1 +3 8 90; 3.5 8 90; 4 8 90; 4.5 8 90
          -more chords..
          +Direction r 0 0 1 -1 0 0 1 r + -
          +

          - -

          -Voicing Dir -

          +Next assume that we have a few bars of music with only a CMajor +chord the default RANGE of ``1'' and the default SCALETYPE +of ``Scale'. The following table shows the notes which would be generated +for each time event:

          -This option is used in conjunction with the MOVE option to set -the direction (-1 or 1) of the movement. - -

          - -

          -Voicing Rmove -

          - -

          -As an alternate to movement in a specified direction, random movement -can add some color and variety to your songs. The command option is -quite useful (and safe to use) in groove files. The argument for this -option is a percentage value specifying the frequency to apply a move -in a random direction. - -

          -For example: - -

          - - -
          - -
          Chord-3 Voicing Mode=Optimal Rmove=20
          - -
          - -

          -would cause a movement (randomly up or down) in 20% of the bars. As -noted earlier, using explicit movement instructions can move the chord -into an undesirable range or even ``off the keyboard''; however, the -algorithm used in RMOVE has a sanity check to ensure that the chord -center position remains, approximately, in a two octave range. - -

          - -

          -
          -ChordAdjust -

          - -

          -The actual notes used in a chord are derived from a table which -contains the notes for each variation of a ``C'' chord--this data is -converted to the desired chord by adding or subtracting a constant -value according to the following table: - -

          -

          - - -
          - - -
          - - - +
          +
          G$\flat$-6
          + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + + + + + + + + + + + + + -
          EventOffset PointerNote
          G-5
          10c
          G$\sharp$-4
          20c
          A$\flat$-4
          31e
          A-3
          43 .. 0c
          A$\sharp$-2
          54 .. 0c
          B$\flat$-2
          6-2 .. 2g
          7randomc, e or g
          8randomc, e, or g
          9....etc.
          -
          - -
          - - - - - - - - - - - - - - - - - - - - - -
          B-1
          C$\flat$-1
          B$\sharp$0
          C0
          C$\sharp$1
          D$\flat$1
          D2
          -
          - -
          - - - - - - - - - - - - - - - - - - - - - -
          D$\sharp$3
          E$\flat$3
          E4
          F$\flat$4
          E$\sharp$5
          F5
          F$\sharp$6
          -
          - - -
          - -
          - -

          -This means that when -MMA encounters an ``Am'' chord it adjusts the -notes in the chord table down by 3 MIDI values; an ``F'' chord is -adjusted 5 MIDI values up. This also means that ``A'' chords will -sound lower than ``F'' chords. - -

          -In most cases this works just fine; but, there are times when the -``F'' chord might sound better lower than the ``A''. You can -force a single chord by prefacing it with a single ``-'' or ``+'' -, details here. But, if the -entire song needs adjustment you can use CHORDADJUST -command to raise or lower selected chord pitches: - -

          - - -
          - -
          ChordAdjust E=-1 F=-1 Bb=1
          - -
          - -

          -Each item in the command consists of a pitch (``B$\flat$'', ``C'', -etc.) an ``='' and an octave specifier (-1, 0 or 1). The pitch values -are case sensitive and must be in upper case; there must not be -a space on either side of the ``=''. - -

          -To a large extent the need for octave adjustments depends on the chord -range of a song. For example, the supplied song ``A Day In The Life Of -A Fool'' needs all ``E'' and ``F'' chords to be adjusted down an -octave. - -

          -The value ``0'' will reset the adjustment to the original value; -setting a value a second time has no effect. - -

          - -

          -
          -Compress -

          - -

          -When -MMA grabs the notes for a chord, the notes are spread out from -the root position. This means that if you specify a ``C13'' you will -have an ``A'' nearly 2 octaves above the root note as part of the -chord. Depending on your instrumentation, pattern, and the chord -structure of your piece, notes outside of the ``normal'' single octave -range for a chord may sound strange. - -

          - - -
          - -
          Chord Compress 1
          - -
          - -

          -Forces -MMA to put all chord notes in a single octave range. - -

          -This command is only effective in CHORD and ARPEGGIO -tracks. A warning message is printed if it is used in other contexts. - -

          -Notes: COMPRESS takes any value between 1 and 5 as arguments -(however, some values will have no effect as detailed above). You can -specify a different COMPRESS for each bar in a sequence. -Repeated values can be represented with a ``/'': - -

          - - -
          - -
          Chord Compress 1 / 0 /
          - -
          - -

          -To restore to its default (off) setting, use a ``0'' as the argument. - -

          -For a similar command, with different results, see the LIMIT -command (here). - -

          - -

          -
          -DupRoot -

          - -

          -To add a bit of fullness to chords, it is quite common of keyboard -players to duplicate the root tone of a chord into a lower (or higher) -octave. This is accomplished in -MMA with the command: - -

          - - -
          - -
          DupRoot -1 1 -1 1
          - -
          - -

          -The command determines whether or not the root tone of a chord is -duplicated in another octave. By default notes are not added. A value -of -1 will add a note one octave lower than the root note, -2 will add -the tone 2 octaves lower, etc. Similarly, the value of 1 will add a -note one octave higher than the root tone, etc. - -

          -Only the values -9 to 9 are permitted. - -

          -The volume used for the generated note is an adjusted average of the -notes in the chord. This volume is always less than the chord -notes--which is probably what you want. If you want a loud bass note, -create a second track (probably a BASS track) with the -appropriate pattern. - -

          -Different values can be used in each bar of the sequence. - -

          -The option is reset to 0 after all SEQUENCE or SEQCLEAR -commands. - -

          -The DUPROOT command is only valid in CHORD tracks. - -

          - -

          -
          -Invert -

          - -

          -By default -MMA uses chords in the root position. By example, the -notes of a C major chord are C, E and G. Chords can be inverted -(something musicians do all the time). Sticking with the C major -chord, the first inversion shifts the root note up an octave and the -chord becomes E, G and C. The second inversion is G, C and E. - -

          - -MMA extends the concept of inversion a bit by permitting the shift -to be to the left or right, and the number of shifts is not limited. -So, you could shift a chord up several octaves by using large invert -values.11.2 -

          -Inversions apply to each bar of a sequence. So, the following is a good example: - -

          - - -
          - -
          SeqSize 4 -
          -Chord-1 Sequence STR1 -
          -Chord-1 Invert 0 1 0 1
          - -
          - -

          -Here the sequence pattern size is set to 4 bars and the pattern -for each bar in the Chord-1 track is set to ``STR1''. Without the next line, -this would result in a rather boring, repeating pattern. But, the -Invert command forces the chord to be in the root position for the -first bar, the first inversion for the second, etc. - -

          -You can use a negative Invert value: - -

          - - -
          - -
          Chord-1 Invert -1
          - -
          - -

          -In this case the C major chord becomes G, C and E. - -

          -Note that using fewer Invert arguments than the current sequence size -is permitted. -MMA simply expands the number of arguments to the -current sequence size. You may use a ``/'' for a repeated value. - -

          -A SEQUENCE or CLEARSEQ command resets INVERT to 0. - -

          -This command on has an effect in CHORD and ARPEGGIO -tracks. And, frankly, ARPEGGIOs sound a bit odd with -inversions. - -

          -If you use a large value for INVERT you can force the notes out -of the normal MIDI range. In this case the lowest or highest possible -MIDI note value will be used. - -

          - -

          -
          -Limit -

          - -

          -If you use ``jazz'' chords in your piece, some people might not like -the results. To some folks, chords like 11th, 13th, and variations -have a dissonant sound. And, sometimes they are in a chart, but don't -really make sense. The LIMIT command can be used to set the -number of notes of a chord used. - -

          -For example: - -

          - - -
          - -
          Chord Limit 4
          - -
          - -

          -will limit any chords used in the CHORD track to the first 4 -notes of a chord. So, if you have a C11 chord which is C, E, G, -B$\flat$, D, and F, the chord will be truncated to C, E, G and -B$\flat$. - -

          -This command only applies to CHORD and ARPEGGIO tracks. -It can be set for other tracks, but the setting will have no effect. - -

          -Notes: LIMIT takes any value between 0 and 8 as an argument. -The ``0'' argument will disable the command. This command applies to -all chords in the sequence--only one value can be given in the -command. - -

          -To restore to its default (off) setting, use a ``0'' as the argument. - -

          -For a similar command, with different results, see the COMPRESS -command (here). - -

          - -

          -
          -NoteSpan -

          - -

          -Many instruments have a limited range. For example, the bass section -of an accordion is limited to a single octave11.3To emulate these sounds it is a simple matter of limiting -MMA 's -output to match the instrument. For example, in the ``frenchwaltz'' -file you will find the directive: - -

          - - -
          - -
          Chord NoteSpan 48 59
          - -
          - -

          -which forces all CHORD tones to the single octave represented -by the MIDI values 48 though 59. - -

          -This command is applied over other voicing commands like OCTAVE -and RANGE and even TRANSPOSE. Notes will still be -calculated with respect to these settings, but then they'll be forced -into the limited NOTESPAN. - -

          -NOTESPAN expects two arguments: The first is the range start, the -second the range end (first and last notes to use). The values are -MIDI tones and must be in the range 0 to 127. The first value must be -less than the second, and the range must represent at least one full -octave (12 notes). It can be applied to all tracks except DRUM. - -

          - -

          -
          -Range -

          - -

          -For ARPEGGIO and SCALE tracks you can specify the number -of octaves used. The effects of the RANGE command is slightly -different between the two. - -

          -SCALE: Scale tracks, by default, create three octave scales. -The RANGE value will modify this to the number of octaves -specified. For example: - -

          - - -
          - -
          Scale Range 1
          - -
          - -

          -will force the scales to one octave. A value of 4 would create 4 -octave scales, etc. - -

          -You can use fractional values when specifying RANGE. For example: - -

          - - -
          - -
          Scale Range .3
          - -
          - -

          -will create a scale of 2 notes.11.4 And, - -

          - - -
          - -
          Scale Range 1.5
          - -
          - -

          -will create a scale of 10 notes. Now, this gets a bit more confusing for you if -you have set SCALETYPE CHROMATIC. In this case a RANGE 1 would -generate 12 notes, and RANGE 1.5 18. - -

          -Partial scales are useful in generating special effects. - -

          -ARPEGGIO: Normally, arpeggios use a single octave.11.5The RANGE command specifies the number of octaves11.6 to use. A fractional value can be used; the exact result -depends on the number of notes in the current chord. - -

          -In all cases the values of ``0'' and ''1'' have the same effect. - -

          -For both SCALE and ARPEGGIO there will always be a minimum of -two notes in the sequence. - -

          - -

          -
          -DefChord -

          - -

          - -MMA comes with a large number of chord types already defined. In -most cases, the supplied set (see this list) is sufficient for all the ``modern'' or -``pop'' charts normally encountered. However, there are those times -when you want to do something else, or something different. +

          -You can define additional chord types at any time, or redefine -existing chord types. The DEFCHORD command makes no distinction -between a new chord type or a redefinition, with the exception that a -warning message is printed for the later. +In the above table the ``..'' notation indicates that the offset is +out-of-range and converted to the second value.

          -The syntax of the command is quite strict: - -

          - - -
          - -
          DefChord NAME (NoteList) (ScaleList)
          - -
          +If you were to change the SCALETYPE or RANGE you would get a +completely different series.

          -where: +Please note the following:

            -
          • Name can be any string, but cannot contain a ``/'', ``>'' or - space. It is case sensitive. Examples of valid names include - ``dim'', ``NO3'' and ``foo-12-xx''. +
          • ARIAs are not saved or modified by GROOVE commands. Well, almost +...the sequence size will be adjusted to match the new size from the +groove. This might be unexpected: + +

            + +

              +
            • Load a groove. Let's say it has a SEQSIZE of 4. +
            • +
            • Create an ARIA. Use 4 patterns to match the groove size (if you + don't +MMA will expand the sequence size for the ARIA, just + like other tracks). +
            • +
            • Process a few bars of music. +
            • +
            • Load a new groove, but this time with a SEQSIZE of 2. Now, the + ARIA will be truncated. This behaviour is duplicated in other + tracks as well, but it might be unexpected here. +
            • +

          • -
          • NoteList is a comma separated list of note offsets - (actually MIDI note values), all of which are enclosed in a set of - ``()''s. There must be at least 2 note offsets and no more than 8 - and all values must be in the range 0 to 24. Using an existing chord - type, a ``7'' chord would be defined with (0, 4, 7, 10). In the case - of a C7 chord, this translates to the notes (c, e, g, b$\flat$). - -

            -

          • -
          • ScaleList is a list of note offsets (again, MIDI note - values), all of which are enclosed in a set of ``()''s. There must - be exactly 7 values in the list and all values must be in the range - 0 to 24. Following on the C7 example above, the scale list would be - (0, 2, 4, 5, 7, 9, 10) or the notes (c, d, e, f, g, a, b$\flat$). +
          • DIRECTION can not be changed on a bar per bar basis. It applies to +the entire sequence.

          -Some examples might clarify. First, assume that you have a section of -your piece which has a major chord, but you only want the root and -fifth to sound for the chords and you want the arpeggios and bass -notes to only use the root. You could create new patterns, but -it's just as easy to create a new chord type. +You can make dramatic changes to your songs with a few simple +tricks. Try modifying the DIRECTION settings just slightly; use +several patterns and SEQRND to generate less predicable +patterns; use HARMONLYONLY with a different voice and pattern.

          - - -
          - -
          DefChord 15 (0,4) (0, 0, 0, 0, 0, 0, 0) -
          -15 C / G / -
          -16 C15 / G15
          - -
          +Oh, and have fun!

          -In this case a normal Major chords will be used in line 15. In line 16 -the new ``15'' will be used. Note the trick in the scale: by setting -all the offsets to ``0'' only the root note is available to the -WALK and BASS tracks. - -

          -Sometimes you'll see a new chord type that -MMA doesn't know. You -could write the author and ask him to add this new type, but if it is -something quite odd or rare, it might be easier to define it in your -song. Let's pretend that you've encountered a ``Cmaj12'' A reasonable -guess is that this is a major 7 with an added 12th (just the 5th up an -octave). You could change the ``maj12'' part of the chord to a ``M7'' -or ``maj7'' and it should sound fine. But: - -

          - - -
          - -
          DefChord maj12 (0, 4, 7, 11, 19) (0, 2, 4, 5, 7, 9, 11)
          - -
          - -

          -is much more fun. Note a few details: - -

          - -

            -
          • The name ``maj12'' can be used with any chord. You can have - ``Cmaj12'' or G$\flat$maj12''. - -

            -

          • -
          • ``maj12'' a case sensitive name. The name ``Maj12'' is quite - different (and unknown). - -

            -

          • -
          • A better name might be ``maj(add12)''. - -

            -

          • -
          • The note and scale offsets are MIDI values. They are easy to - figure if you think of the chord as a ``C''. Just count off notes - from ``C'' on a keyboard (C is note 0). - -

            -

          • -
          • Do Not include a chord name (ie: C or B$\flat$) in the - definition. Just the type. - -

            -

          • -
          - -

          -The final example handles a minor problem in -MMA and ``diminished'' -chords. In most of the music the author of -MMA encounters, the -marking ``dim'' on a chord usually means a ``diminished 7th''. So, -when -MMA initializes it creates a copy of the ``dim7'' and calls it -``dim''. But, some people think that ``dim'' should reference a -``diminished triad''. It's pretty easy to change this by creating a -new definition for ``dim'': - -

          - - -
          - -
          DefChord dim (0, 3, 6) (0, 2, 3, 5, 6, 8, 9 )
          - -
          - -

          -In this example the scale notes use the same notes as those in a -``dim7''. You might want to change the B$\flat{}\flat$ (9) to B$\flat$ -(10) or B (11). If you really disagree with the choice to make a dim7 -the default you could even put this in a mmarc file. - -

          -It is even easier to use the non-standard notation ``dim3'' to specify -a diminished triad. - -

          - -

          -PrintChord -

          - -

          -This command can be used to make the create of custom chords a bit -simpler. Simply pass one or more chord types after the command and -they will be displayed on your terminal. Example: - -

          - - -
          - -
          PrintChord m M7 dim
          - -
          - -

          -in a file should display: - -

          - - -
          - -
          m : (0, 3, 7) (0, 2, 3, 5, 7, 9, 11) Minor triad. -
          -M7 : (0, 4, 7, 11) (0, 2, 4, 5, 7, 9, 11) Major 7th. -
          -dim : (0, 3, 6, 9) (0, 2, 3, 5, 6, 8, 9) Diminished. -MMA assumes a - diminished 7th.
          - -
          - -

          -From this you can cut and paste, change the chord or scale and insert -the data into a DEFCHORD command. - -

          - -

          -Notes -

          - -

          - -MMA makes other adjustments on-the-fly to your chords. This is done -to make the resulting sounds ``more musical'' ...to keep life -interesting, the definition of ``more musical'' is quite elusive. The -following notes will try to list some of the more common adjustments -made ``behind your back''. - -

          - -

            -
          • Just before the notes (MIDI events) for a chord are generated - the first and last notes in the chord are compared. If they are a - separated by a half-step (or 1 MIDI value) or an octave plus - half-step, the volume of the first note is halved. This happens in - chords such as a Major-7th or Flat-9th. If the adjustment is - not done the dissonance between the two tones overwhelms the ear. - -

            -

          • -
          -

          Footnotes

          -
          -
          ... -algorithms11.1
          -
          Great thanks are due to Alain Brenzikofer who not - only pressured me into including the VOICING options, but - wrote a great deal of the actual code. - -
          -
          ... -values.11.2
          -
          The term ``shift'' is used here, but that's not - quite what -MMA does. The order of the notes in the internal buffer - stays the same, just the octave for the notes is changed. So, if the - chord notes are ``C E G'' with the MIDI values ``0, 4, 7'' an invert - of 1 would change the notes to ``C$^{2}$ E G'' and the MIDI values - to ``12, 4, 7''. - -
          -
          ... octave11.3
          -
          Some accordions - have ``freebass'' switches which overcomes this, but that is the - exception. - -
          -
          ... notes.11.4
          -
          Simple math here: take the number of notes in a scale (7) and -multiply by .3. Take the integer result as the number of notes. - -
          -
          ... octave.11.5
          -
          Not quite true: they -use whatever notes are in the chord, which might exceed an octave span. - -
          -
          ... octaves11.6
          -
          Again, not quite true: the -command just duplicates the arpeggio notes the number of times specified in the -RANGE setting. - -
          -

          +
          - next - up - previous
          - Next: Harmony - Up: Next: Chord Voicing + Up: Reference Manual - Previous: Previous: Solo and Melody Tracks
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node12.html b/mma/docs/html/ref/node12.html index a2ea753..95eb149 100644 --- a/mma/docs/html/ref/node12.html +++ b/mma/docs/html/ref/node12.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Harmony - +Chord Voicing + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Tempo and Timing - Up: Next: Harmony + Up: Reference Manual - Previous: Chord Voicing + Previous: Automatic Melodies: Aria Tracks

          @@ -49,296 +49,1259 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

          - +
          -Harmony +Chord Voicing +

          + +

          +In music, a chord is simply defined as two more notes played +simultaneously. Now, this doesn't mean that you can play just any two +or three notes and get a chord which sounds nice--but whatever you do +get will be a chord of some type. And, to further confuse the unwary, +different arrangements of the same notes sound better (or worse) in +different musical situations. + +

          +As a simple example, consider a C major chord. Built on the first, +third and fifth notes of a C major scale it can be manipulated into a +variety of sounds: + +

          +

          + Lost Image + +
          + +

          +These are all C major chords ...but they all have a different +sound or color. The different forms a chord can take are called +``voicings''. Again, this manual is not intended to be a primer on +musical theory--that's a subject for which lots of lessons with your +favorite music teacher is recommended. You'll need a bit of +basic music theory if you want to understand how and why +MMA creates its tracks. + +

          +The different options in this chapter effect not only the way chords +are constructed, but also the way bass lines and other tracks are +formed. + +

          +There are generally two ways in +MMA to take care of voicings. + +

          + +

            +
          1. use +MMA 's extensive VOICING options, most likely with + the ''Optimal'' voicing algorithm, + +

            +

          2. +
          3. do everything by yourself with the commands INVERT and + COMPRESS. + +

            +

          4. +
          + +

          +The commands LIMIT and DUPROOT may be used independently +for both variants. + +

          + +

          +Voicing +

          + +

          +The VOICING command is used to set the voicing mode and several +other options relating to the selected mode. The command needs to have +a CHORD track specified and a series of Option=Value pairs. For +example: + +

          + + + +
          + Chord-Piano Voicing Mode=Optimal Rmove=10 Range=9 + +
          + +

          +In the following sections all the options available will be covered. + +

          + +

          +Voicing Mode +

          + +

          +The easiest way to deal with chord voicings is via the +VOICING MODE=XX option. + +

          +When choosing the inversion of a chord to play an accompanist will +take into consideration the style of the piece and the chord +sequences. In a general sense, this is referred to as ``voicing''. + +

          +A large number of the library files have been written to take +advantage of the following voicing commands. However, not all styles +of music take well to the concept. And, don't forget about the other +commands since they are useful in manipulating bass lines, as well as +other chord tracks (e.g., sustained strings). + +

          + +MMA has a variety of sophisticated, intelligent +algorithms12.1 to deal with voicing. + +

          +As a general rule you should not use the INVERT and +COMPRESS commands in conjunction with the VOICING +command. If you do, you may create beautiful sounds. But, the results +are more likely to be less-than-pleasing. Use of voicing and other +combinations will display various warning messages. + +

          +The main command to enable voicings is: + +

          + + + +
          + Chord Voicing Mode=Type + +
          + +

          +As mentioned above, this command can only be applied to CHORD +tracks. Also note that this effects all bars in the sequence ... +you cannot have different voicings for different bars in the sequence +(attempting to do this would make no sense). + +

          +The following MODE types are available: + +

          +

          +
          Optimal
          +
          A basic algorithm which automatically chooses the best + sounding voicing depending on the voicing played before. Always try + this option before anything else. It might work just fine without + further work. + +

          +The idea behind this algorithm is to keep voicings in a sequence + close together. A pianist leaves his or her fingers where they are, + if they still fit the next chord. Then, the notes closest to the + fingers are selected for the next chord. This way characteristic + notes are emphasized. + +

          +

          +
          Root
          +
          This Option may for example be used to turn off + VOICING within a song. VOICING MODE=ROOT means nothing + else than doing nothing, leaving all chords in root position. + +

          +

          +
          None
          +
          This is the same as the ROOT option. + +

          +

          +
          Invert
          +
          Rather than basing the inversion selection on an + analysis of past chords, this method quite stupidly tries to keep + chords around the base point of ``C'' by inverting ``G'' and ``A'' + chords upward and ``D'', ``E'' and ``F'' downward. The chords are + also compressed. Certainly not an ideal algorithm, but it can be + used to add variety in a piece. + +

          +

          +
          Compressed
          +
          Does the same as the stand-alone COMPRESS + command. Like ROOT, it is only added to be used in some parts + of a song where VOICING MODE=OPTIMAL is used. + +

          +

          +
          + +

          + +

          +Voicing Range +

          + +

          +To get wider or closer voicings, you may define a range for the +voicings. This can be adjusted with the RANGE option: + +

          + + + +
          + Chord-Guitar Voicing Mode=Optimal Range=12 + +
          + +

          +In most cases the default value of 12 should work just fine. But, you +may want to fine tune ...it's all up to you. This command only +effects chords created with MODE=OPTIMAL. + +

          + +

          +Voicing Center +

          + +

          +Just minimizing the Euclidean distance between chords doesn't do the +trick as there could be runaway progressions that let the voicings +drift up or down infinitely. + +

          +When a chord is ``voiced'' or moved to a new position, a ``center +point'' must be used as a base. By default, the fourth degree of the +scale corresponding to the chord is a reasonable choice. However, you +can change this with: + +

          + + + +
          + Chord-1 Voicing Center=<value> + +
          + +

          +The value in this command can be any number in the range 0 to +12. Try different values. The color of your whole song might change. + +

          +Note that the value is the note in the scale, not a chord-note position. + +

          +This command only effects chords created with MODE=OPTIMAL. + +

          + +

          +Voicing Move +

          + +

          +To intensify a chord progression you may want to have ascending or +descending movement of voicings. This option, in conjunction with the +DIR optional (see below) sets the number of bars over which a +movement is done. + +

          +For the MOVE option to have any effect you must also set the +direction to either -1 or 1. Be careful that you don't force the chord +too high or low on the scale. Use of this command in a REPEAT +section can cause unexpected results. For this reason you should +include a SEQ command at the beginning of repeated sections of +your songs. + +

          +In most cases the use of this command is limited to a section of a +song, its use is not recommended in groove files. You might want to do +something like this in a song: + +

          + + + +
          + ..select groove with voicing +
          +chords.. +
          +Chord-Piano Voicing Move=5 Dir=1 +
          +more chords.. +
          +Chord-Piano Voicing Move=5 Dir=-1 +
          +more chords..
          + +
          + +

          + +

          +Voicing Dir +

          + +

          +This option is used in conjunction with the MOVE option to set +the direction (-1 or 1) of the movement. + +

          + +

          +Voicing Rmove +

          + +

          +As an alternate to movement in a specified direction, random movement +can add some color and variety to your songs. The command option is +quite useful (and safe to use) in groove files. The argument for this +option is a percentage value specifying the frequency to apply a move +in a random direction. + +

          +For example: + +

          + + + +
          + Chord-3 Voicing Mode=Optimal Rmove=20 + +
          + +

          +would cause a movement (randomly up or down) in 20% of the bars. As +noted earlier, using explicit movement instructions can move the chord +into an undesirable range or even ``off the keyboard''; however, the +algorithm used in RMOVE has a sanity check to ensure that the chord +center position remains, approximately, in a two octave range. + +

          + +

          +
          +ChordAdjust +

          + +

          +The actual notes used in a chord are derived from a table which +contains the notes for each variation of a ``C'' chord--this data is +converted to the desired chord by adding or subtracting a constant +value according to the following table: + +

          +

          + + + +
          + + + +
          + + + + + + + + + + + + + + + + + + + + + + +
          G$\flat$-6
          G-5
          G$\sharp$-4
          A$\flat$-4
          A-3
          A$\sharp$-2
          B$\flat$-2
          +
          + +
          + + + + + + + + + + + + + + + + + + + + + +
          B-1
          C$\flat$-1
          B$\sharp$0
          C0
          C$\sharp$1
          D$\flat$1
          D2
          +
          + +
          + + + + + + + + + + + + + + + + + + + + + +
          D$\sharp$3
          E$\flat$3
          E4
          F$\flat$4
          E$\sharp$5
          F5
          F$\sharp$6
          +
          + + +
          + +
          + +

          +This means that when +MMA encounters an ``Am'' chord it adjusts the +notes in the chord table down by 3 MIDI values; an ``F'' chord is +adjusted 5 MIDI values up. This also means that ``A'' chords will +sound lower than ``F'' chords. + +

          +In most cases this works just fine; but, there are times when the +``F'' chord might sound better lower than the ``A''. You can +force a single chord by prefacing it with a single ``-'' or ``+'' +, details here. But, if the +entire song needs adjustment you can use CHORDADJUST +command to raise or lower selected chord pitches: + +

          + + + +
          + ChordAdjust E=-1 F=-1 Bb=1 + +
          + +

          +Each item in the command consists of a pitch (``B$\flat$'', ``C'', +etc.) an ``='' and an octave specifier (-1, 0 or 1). The pitch values +are case sensitive and must be in upper case; there must not be +a space on either side of the ``=''. + +

          +To a large extent the need for octave adjustments depends on the chord +range of a song. For example, the supplied song ``A Day In The Life Of +A Fool'' needs all ``E'' and ``F'' chords to be adjusted down an +octave. + +

          +The value ``0'' will reset the adjustment to the original value; +setting a value a second time has no effect. + +

          + +

          +
          +Compress +

          + +

          +When +MMA grabs the notes for a chord, the notes are spread out from +the root position. This means that if you specify a ``C13'' you will +have an ``A'' nearly 2 octaves above the root note as part of the +chord. Depending on your instrumentation, pattern, and the chord +structure of your piece, notes outside of the ``normal'' single octave +range for a chord may sound strange. + +

          + + + +
          + Chord Compress 1 + +
          + +

          +Forces +MMA to put all chord notes in a single octave range. + +

          +This command is only effective in CHORD and ARPEGGIO +tracks. A warning message is printed if it is used in other contexts. + +

          +Notes: COMPRESS takes any value between 1 and 5 as arguments +(however, some values will have no effect as detailed above). You can +specify a different COMPRESS for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

          + + + +
          + Chord Compress 1 / 0 / + +
          + +

          +To restore to its default (off) setting, use a ``0'' as the argument. + +

          +For a similar command, with different results, see the LIMIT +command (here). + +

          + +

          +
          +DupRoot +

          + +

          +To add a bit of fullness to chords, it is quite common of keyboard +players to duplicate the root tone of a chord into a lower (or higher) +octave. This is accomplished in +MMA with the command: + +

          + + + +
          + DupRoot -1 1 -1 1 + +
          + +

          +The command determines whether or not the root tone of a chord is +duplicated in another octave. By default notes are not added. A value +of -1 will add a note one octave lower than the root note, -2 will add +the tone 2 octaves lower, etc. Similarly, the value of 1 will add a +note one octave higher than the root tone, etc. + +

          +Only the values -9 to 9 are permitted. + +

          +The volume used for the generated note is an adjusted average of the +notes in the chord. This volume is always less than the chord +notes--which is probably what you want. If you want a loud bass note, +create a second track (probably a BASS track) with the +appropriate pattern. + +

          +Different values can be used in each bar of the sequence. + +

          +The option is reset to 0 after all SEQUENCE or SEQCLEAR +commands. + +

          +The DUPROOT command is only valid in CHORD tracks. + +

          + +

          +
          +Invert +

          + +

          +By default +MMA uses chords in the root position. By example, the +notes of a C major chord are C, E and G. Chords can be inverted +(something musicians do all the time). Sticking with the C major +chord, the first inversion shifts the root note up an octave and the +chord becomes E, G and C. The second inversion is G, C and E. + +

          + +MMA extends the concept of inversion a bit by permitting the shift +to be to the left or right, and the number of shifts is not limited. +So, you could shift a chord up several octaves by using large invert +values.12.2 +

          +Inversions apply to each bar of a sequence. So, the following is a good example: + +

          + + + +
          + SeqSize 4 +
          +Chord-1 Sequence STR1 +
          +Chord-1 Invert 0 1 0 1
          + +
          + +

          +Here the sequence pattern size is set to 4 bars and the pattern +for each bar in the Chord-1 track is set to ``STR1''. Without the next line, +this would result in a rather boring, repeating pattern. But, the +Invert command forces the chord to be in the root position for the +first bar, the first inversion for the second, etc. + +

          +You can use a negative Invert value: + +

          + + + +
          + Chord-1 Invert -1 + +
          + +

          +In this case the C major chord becomes G, C and E. + +

          +Note that using fewer Invert arguments than the current sequence size +is permitted. +MMA simply expands the number of arguments to the +current sequence size. You may use a ``/'' for a repeated value. + +

          +A SEQUENCE or CLEARSEQ command resets INVERT to 0. + +

          +This command on has an effect in CHORD and ARPEGGIO +tracks. And, frankly, ARPEGGIOs sound a bit odd with +inversions. + +

          +If you use a large value for INVERT you can force the notes out +of the normal MIDI range. In this case the lowest or highest possible +MIDI note value will be used. + +

          + +

          +
          +Limit +

          + +

          +If you use ``jazz'' chords in your piece, some people might not like +the results. To some folks, chords like 11th, 13th, and variations +have a dissonant sound. And, sometimes they are in a chart, but don't +really make sense. The LIMIT command can be used to set the +number of notes of a chord used. + +

          +For example: + +

          + + + +
          + Chord Limit 4 + +
          + +

          +will limit any chords used in the CHORD track to the first 4 +notes of a chord. So, if you have a C11 chord which is C, E, G, +B$\flat$, D, and F, the chord will be truncated to C, E, G and +B$\flat$. + +

          +This command only applies to CHORD and ARPEGGIO tracks. +It can be set for other tracks, but the setting will have no effect. + +

          +Notes: LIMIT takes any value between 0 and 8 as an argument. +The ``0'' argument will disable the command. This command applies to +all chords in the sequence--only one value can be given in the +command. + +

          +To restore to its default (off) setting, use a ``0'' as the argument. + +

          +For a similar command, with different results, see the COMPRESS +command (here). + +

          + +

          +
          +NoteSpan +

          + +

          +Many instruments have a limited range. For example, the bass section +of an accordion is limited to a single octave12.3To emulate these sounds it is a simple matter of limiting +MMA 's +output to match the instrument. For example, in the ``frenchwaltz'' +file you will find the directive: + +

          + + + +
          + Chord NoteSpan 48 59 + +
          + +

          +which forces all CHORD tones to the single octave represented +by the MIDI values 48 though 59. + +

          +This command is applied over other voicing commands like OCTAVE +and RANGE and even TRANSPOSE. Notes will still be +calculated with respect to these settings, but then they'll be forced +into the limited NOTESPAN. + +

          +NOTESPAN expects two arguments: The first is the range start, the +second the range end (first and last notes to use). The values are +MIDI tones and must be in the range 0 to 127. The first value must be +less than the second, and the range must represent at least one full +octave (12 notes). It can be applied to all tracks except DRUM. + +

          + +

          +
          +Range +

          + +

          +For ARPEGGIO and SCALE tracks you can specify the number +of octaves used. The effects of the RANGE command is slightly +different between the two. + +

          +SCALE: Scale tracks, by default, create three octave scales. +The RANGE value will modify this to the number of octaves +specified. For example: + +

          + + + +
          + Scale Range 1 + +
          + +

          +will force the scales to one octave. A value of 4 would create 4 +octave scales, etc. + +

          +You can use fractional values when specifying RANGE. For example: + +

          + + + +
          + Scale Range .3 + +
          + +

          +will create a scale of 2 notes.12.4 And, + +

          + + + +
          + Scale Range 1.5 + +
          + +

          +will create a scale of 10 notes. Now, this gets a bit more confusing for you if +you have set SCALETYPE CHROMATIC. In this case a RANGE 1 would +generate 12 notes, and RANGE 1.5 18. + +

          +Partial scales are useful in generating special effects. + +

          +ARPEGGIO: Normally, arpeggios use a single octave.12.5The RANGE command specifies the number of octaves12.6 to use. A fractional value can be used; the exact result +depends on the number of notes in the current chord. + +

          +In all cases the values of ``0'' and ''1'' have the same effect. + +

          +For both SCALE and ARPEGGIO there will always be a minimum of +two notes in the sequence. + +

          + +

          +
          +DefChord

          -MMA can generate harmony notes for you ...just like hitting two -or more keys on the piano! And you don't have to take lessons. +MMA comes with a large number of chord types already defined. In +most cases, the supplied set (see this list) is sufficient for all the ``modern'' or +``pop'' charts normally encountered. However, there are those times +when you want to do something else, or something different.

          -Automatic harmonies are available for the following track types: Bass, -Walk, Arpeggio, Scale, Solo and Melody. +You can define additional chord types at any time, or redefine +existing chord types. The DEFCHORD command makes no distinction +between a new chord type or a redefinition, with the exception that a +warning message is printed for the later.

          -Just in case you are thinking that -MMA is a wonderful musical -creator when it comes to harmonies, don't be fooled. -MMA 's ideas of -harmony are quite facile. It determines harmony notes by finding a -note lower or higher than the current note being sounded within the -current chord. And its notion of ``open'' is certainly not that of -traditional music theory. But, the sound isn't too bad. +The syntax of the command is quite strict:

          -

          -
          -Harmony -

          - -

          -To enable harmony notes, use a command like: - -

          - - - +
          + + +
          + DefChord NAME (NoteList) (ScaleList) -
          Solo Harmony 2
          +
          + +

          +where: + +

          + +

            +
          • Name can be any string, but cannot contain a ``/'', ``>'' or + space. It is case sensitive. Examples of valid names include + ``dim'', ``NO3'' and ``foo-12-xx''. + +

            +

          • +
          • NoteList is a comma separated list of note offsets + (actually MIDI note values), all of which are enclosed in a set of + ``()''s. There must be at least 2 note offsets and no more than 8 + and all values must be in the range 0 to 24. Using an existing chord + type, a ``7'' chord would be defined with (0, 4, 7, 10). In the case + of a C7 chord, this translates to the notes (c, e, g, b$\flat$). + +

            +

          • +
          • ScaleList is a list of note offsets (again, MIDI note + values), all of which are enclosed in a set of ``()''s. There must + be exactly 7 values in the list and all values must be in the range + 0 to 24. Following on the C7 example above, the scale list would be + (0, 2, 4, 5, 7, 9, 10) or the notes (c, d, e, f, g, a, b$\flat$). + +

            +

          • +
          + +

          +Some examples might clarify. First, assume that you have a section of +your piece which has a major chord, but you only want the root and +fifth to sound for the chords and you want the arpeggios and bass +notes to only use the root. You could create new patterns, but +it's just as easy to create a new chord type. + +

          + + +
          + DefChord 15 (0,4) (0, 0, 0, 0, 0, 0, 0) +
          +15 C / G / +
          +16 C15 / G15
          -
          +

          -You can set a different harmony method for each bar in your sequence. +In this case a normal Major chords will be used in line 15. In line 16 +the new ``15'' will be used. Note the trick in the scale: by setting +all the offsets to ``0'' only the root note is available to the +WALK and BASS tracks.

          -The following are valid harmony methods: - -

          -
          2 or 2Below
          -
          Two part harmony. The harmony note - selected is lower (on the scale). - -

          -

          -
          2Above
          -
          The same as ``2'', but the harmony note is raised an - octave. - -

          -

          -
          3 or 3Below
          -
          Three part harmony. The harmony notes - selected are lower. - -

          -

          -
          3Above
          -
          The same as ``3'', but both notes are raised an - octave. - -

          -

          -
          Open or OpenBelow
          -
          Two part harmony, however the gap - between the two notes is larger than in ``2''. - -

          -

          -
          OpenAbove
          -
          Same as ``Open'', but the added note is above the - original. - -

          -

          -
          8 or 8Below
          -
          A note 1 octave lower is added. - -

          -

          -
          8Above
          -
          A note 2 octave higher is added. - -

          -

          -
          16 or 16Below
          -
          A single note two octaves below is - added. - -

          -

          -
          16Above
          -
          A single note two octaves above are added. - -

          -

          -
          24 or 24Below
          -
          A single note three octaves below is - added. - -

          -

          -
          24Above
          -
          A single note three octaves above is added. - -

          -

          -
          - -

          -You can combine any of the above harmony modes by using a ``+''. For -example: - -

          -
          OPEN+8Below
          -
          will produce harmony notes with an ``Open'' - harmony and a note an octave below the current note. - -

          -

          -
          3Above+16
          -
          will generate 2 harmony notes above the current - note plus a note 2 octaves below. - -

          -

          -
          8Below+8Above+16Below
          -
          will generate 3 notes: one 2 octaves - below the current, one an octave below, and one an octave above. - -

          -

          -
          - -

          -There is no limit to the number of modes you can concatenate. Any -duplicate notes generated will be ignored. - -

          -All harmonies are created using the current chord. - -

          -To disable harmony use a ``0'', ``-'' or ``None''. - -

          -Be careful in using harmonies. They can make your song sound heavy, -especially with BASS notes (applying a different volume may -help). - -

          -The command has no effect in DRUM or CHORD tracks. +Sometimes you'll see a new chord type that +MMA doesn't know. You +could write the author and ask him to add this new type, but if it is +something quite odd or rare, it might be easier to define it in your +song. Let's pretend that you've encountered a ``Cmaj12'' A reasonable +guess is that this is a major 7 with an added 12th (just the 5th up an +octave). You could change the ``maj12'' part of the chord to a ``M7'' +or ``maj7'' and it should sound fine. But:

          -

          -
          -HarmonyOnly -

          - -

          -As a added feature to the automatic harmony generation discussed in -the previous section, it is possible to set a track so that it -only plays the harmony notes. For example, you might want to -set up two arpeggio tracks with one playing quarter notes on a piano -and a harmony track playing half notes on a violin. The following -snippet is extracted from the song file ``Cry Me A River'' and sets up -2 different choir voices: - -

          - - - +
          + + +
          + DefChord maj12 (0, 4, 7, 11, 19) (0, 2, 4, 5, 7, 9, 11) -
          Begin Arpeggio -
              Sequence A4 -
              Voice ChoirAahs -
              Invert 0 1 2 3 -
              SeqRnd -
              Octave 5 -
              RSkip 40 -
              Volume p -
              Articulate 99 -
          -End -
                       -
          -Begin Arpeggio-2 -
              Sequence A4 -
              Voice VoiceOohs -
              Octave 5 -
              RSkip 40 -
              Volume p -
              Articulate 99 -
              HarmonyOnly Open -
          -End
          +
          + +

          +is much more fun. Note a few details: + +

          + +

            +
          • The name ``maj12'' can be used with any chord. You can have + ``Cmaj12'' or G$\flat$maj12''. + +

            +

          • +
          • ``maj12'' a case sensitive name. The name ``Maj12'' is quite + different (and unknown). + +

            +

          • +
          • A better name might be ``maj(add12)''. + +

            +

          • +
          • The note and scale offsets are MIDI values. They are easy to + figure if you think of the chord as a ``C''. Just count off notes + from ``C'' on a keyboard (C is note 0). + +

            +

          • +
          • Do Not include a chord name (ie: C or B$\flat$) in the + definition. Just the type. + +

            +

          • +
          + +

          +The final example handles a minor problem in +MMA and ``diminished'' +chords. In most of the music the author of +MMA encounters, the +marking ``dim'' on a chord usually means a ``diminished 7th''. So, +when +MMA initializes it creates a copy of the ``dim7'' and calls it +``dim''. But, some people think that ``dim'' should reference a +``diminished triad''. It's pretty easy to change this by creating a +new definition for ``dim'': + +

          + + +
          + DefChord dim (0, 3, 6) (0, 2, 3, 5, 6, 8, 9 ) -
          +

          -Just like the HARMONY command, above, you can have different -settings for each bar in your sequence. Setting a bar (or the entire -sequence) to '`-'' or ``0'' disables both the HARMONY and -HARMONYONLY settings. +In this example the scale notes use the same notes as those in a +``dim7''. You might want to change the B$\flat{}\flat$ (9) to B$\flat$ +(10) or B (11). If you really disagree with the choice to make a dim7 +the default you could even put this in a mmarc file.

          -The command has no effect in DRUM or CHORD tracks. - -

          -If you want to use this feature with SOLO or MELODY -tracks you can duplicate the notes in your RIFF or in-line -notation or with the AUTOHARMONYTRACKS - COMMAND. +It is even easier to use the non-standard notation ``dim3'' to specify +a diminished triad.

          -

          -
          -HarmonyVolume -

          +

          +PrintChord +

          -By default, -MMA will use a volume (velocity) of 80% of that used by -the original note for all harmony notes it generates. You can change -this with the the HARMONYVOLUME command. For example: +This command can be used to make the create of custom chords a bit +simpler. Simply pass one or more chord types after the command and +they will be displayed on your terminal. Example:

          - - +
          + +
          + PrintChord m M7 dim -
          Begin Solo -
            Voice JazzGuitar -
            Harmony Open -
            HarmonyVolume 80 -
          -End
          - -
          +

          -You can specify different values for each bar in the sequence. The -values are percentages and must be greater than 0 (large values works -just fine if you want the harmony louder than the original). The -command has no effect in DRUM or CHORD tracks. -


          +in a file should display: + +

          + + + +
          + m : (0, 3, 7) (0, 2, 3, 5, 7, 9, 11) Minor triad. +
          +M7 : (0, 4, 7, 11) (0, 2, 4, 5, 7, 9, 11) Major 7th. +
          +dim : (0, 3, 6, 9) (0, 2, 3, 5, 6, 8, 9) Diminished. +MMA assumes a + diminished 7th.
          + +
          + +

          +From this you can cut and paste, change the chord or scale and insert +the data into a DEFCHORD command. + +

          + +

          +Notes +

          + +

          + +MMA makes other adjustments on-the-fly to your chords. This is done +to make the resulting sounds ``more musical'' ...to keep life +interesting, the definition of ``more musical'' is quite elusive. The +following notes will try to list some of the more common adjustments +made ``behind your back''. + +

          + +

            +
          • Just before the notes (MIDI events) for a chord are generated + the first and last notes in the chord are compared. If they are a + separated by a half-step (or 1 MIDI value) or an octave plus + half-step, the volume of the first note is halved. This happens in + chords such as a Major-7th or Flat-9th. If the adjustment is + not done the dissonance between the two tones overwhelms the ear. + +

            +

          • +
          +

          Footnotes

          +
          +
          ... +algorithms12.1
          +
          Great thanks are due to Alain Brenzikofer who not + only pressured me into including the VOICING options, but + wrote a great deal of the actual code. + +
          +
          ... +values.12.2
          +
          The term ``shift'' is used here, but that's not + quite what +MMA does. The order of the notes in the internal buffer + stays the same, just the octave for the notes is changed. So, if the + chord notes are ``C E G'' with the MIDI values ``0, 4, 7'' an invert + of 1 would change the notes to ``C$^{2}$ E G'' and the MIDI values + to ``12, 4, 7''. + +
          +
          ... octave12.3
          +
          Some accordions + have ``freebass'' switches which overcomes this, but that is the + exception. + +
          +
          ... notes.12.4
          +
          Simple math here: take the number of notes in a scale (7) and +multiply by .3. Take the integer result as the number of notes. + +
          +
          ... octave.12.5
          +
          Not quite true: they +use whatever notes are in the chord, which might exceed an octave span. + +
          +
          ... octaves12.6
          +
          Again, not quite true: the +command just duplicates the arpeggio notes the number of times specified in the +RANGE setting. + +
          +

          - next - up - previous
          - Next: Tempo and Timing - Up: Next: Harmony + Up: Reference Manual - Previous: Chord Voicing + Previous: Automatic Melodies: Aria Tracks
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node13.html b/mma/docs/html/ref/node13.html index 300c4b4..6976eb3 100644 --- a/mma/docs/html/ref/node13.html +++ b/mma/docs/html/ref/node13.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Tempo and Timing - +Harmony + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Swing - Up: Next: Tempo and Timing + Up: Reference Manual - Previous: Harmony + Previous: Chord Voicing

          @@ -49,834 +49,296 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

          - +
          -Tempo and Timing +Harmony

          -MMA has a rich set of commands to adjust and vary the timing of your -song. +MMA can generate harmony notes for you ...just like hitting two +or more keys on the piano! And you don't have to take lessons. + +

          +Automatic harmonies are available for the following track types: Bass, +Walk, Arpeggio, Scale, Solo and Melody. + +

          +Just in case you are thinking that +MMA is a wonderful musical +creator when it comes to harmonies, don't be fooled. +MMA 's ideas of +harmony are quite facile. It determines harmony notes by finding a +note lower or higher than the current note being sounded within the +current chord. And its notion of ``open'' is certainly not that of +traditional music theory. But, the sound isn't too bad.

          -

          -Tempo -

          - -

          -The tempo of a piece is set in Beats per Minute with the ``Tempo'' -directive. - -

          - - -
          - -
          Tempo 120
          - -
          - -

          -sets the tempo to 120 beats/minute. You can also use the tempo command -to increase or decrease the current rate by including a leading ``+'', -``-'' or ``*'' in the rate. For example (assuming the current rate is -120): - -

          - - -
          - -
          Tempo +10
          - -
          - -

          -will increase the current rate to 130 beats/minute. - -

          -The tempo can be changed series of beats, much like a rit. or acc. in -real music. Assuming that a time signature of 4/4, the current tempo -is 120, and there are 4 beats in a bar, the command: - -

          - - -
          - -
          Tempo 100 1
          - -
          - -

          -will cause 4 tempo entries to be placed in the current bar (in the -MIDI meta track). The start of the bar will be 115, the 2nd beat will -be at 110, the 3rd at 105 and the last at 100. - -

          -You can also vary an existing rate using a ``+'', ``-'' or ``*'' in -the rate. - -

          -You can vary the tempo over more than one bar. For example: - -

          - - -
          - -
          Tempo +20 5.5
          - -
          - -

          -tells -MMA to increase the tempo by 20 beats per minute and to step -the increase over the next five and a half bars. Assuming a start -tempo of 100 and 4 beats/bar, the meta track will have a tempo -settings of 101, 102, 103 ...120. This will occur over 22 beats -(5.5 bars * 4 beats) of music. - -

          -Using the multiplier is handy if you are switching to ``double time'': - -

          - - -
          - -
          Tempo *2
          - -
          - -

          -and to return: - -

          - - -
          - -
          Temp *.5
          - -
          - -

          -Note that the ``+'', ``-'' or ``*'' sign must not be separated -from the tempo value by any spaces. The value for TEMPO can be -any value, but will be converted to integer for the final setting. - -

          - -

          +


          -Time -

          +Harmony + + +

          +To enable harmony notes, use a command like:

          -MMA doesn't really understand time signatures. It just cares about -the number of beats in a bar. So, if you have a piece in -4/4 time you would use: - -

          - - - +
          + +
          + Solo Harmony 2 -
          Time 4
          - -
          +

          -For 3/4 use: +You can set a different harmony method for each bar in your sequence.

          +The following are valid harmony methods: - -
          - -
          Time 3
          - -
          +

          +
          2 or 2Below
          +
          Two part harmony. The harmony note + selected is lower (on the scale).

          -For 6/8 you'd probably want either ``2'' or ``6''. - -

          -Changing the time also cancels all existing sequences. So, after a -time directive you'll need to set up your sequences or load a new -groove.13.1 -

          - -

          -TimeSig -

          - -

          -Even though -MMA doesn't really use Time Signatures, some MIDI -programs do recognize and use them. So, here's a command which will -let you insert a Time Signature in your MIDI output: - -

          - - -
          - -
          TimeSig NN DD
          - -
          - -

          -The NN parameter is the time signature numerator (the number of beats -per bar). In 3/4 you would set this to ``3''. - -

          -The DD parameter is the time signature denominator (the length of the -note getting a single beat). In 3/4 you would set this to -``4''. - -

          -The NN value must be an integer in the range of 1 to 126. The DD value -must be one of 1, 2, 4, 8, 16, 32 or 64. - -

          - -MMA assumes that all songs are in 4/4 and places that -MIDI event at offset 0 in the Meta track. - -

          -The TIMESIG value is remembered by GROOVEs and is -properly set when grooves are switched. You should probably have a -time signature in any groove library files you create (the supplied -files all do). - -

          -The common time signatures ``common'' and ``cut'' are supported. They -are translated by -MMA to 4/4 and 2/2. - -

          - -

          -
          -BeatAdjust -

          - -

          -Internally, -MMA tracks its position in a song according to beats. -For example, in a 4/4 piece the beat position is -incremented by 4 after each bar is processed. For the most part, this -works fine; however, there are some conditions when it would be nice -to manually adjust the beat position: - -

          - -

            -
          • You may want to insert some extra (silent) beats at the end of - bar to simulate a pause, - -

            -

          • -
          • You may want to delete some beats to handle a ``short'' bar. - -

            -

          • -
          - -

          -Both instances will be dealt with in turn. In this - example a pause is simulated at the end of bar -10. One problem with this logic is that the inserted beat will be -silent, but certain notes (percussive things like piano) often will -continue to sound (this is related to the decay of the note, not that - -MMA has not turned off the note). Frankly, this really doesn't -work too well ...which is why the FERMATA -(details here) was added. - -

          - -
          - -
          - Adding Extra Beats -
          - - - -
          - -
          Time 4 -
          -1 Cm / / / -
          ... -
          -10 Am / C / -
          -BeatAdjust 1 -
          ...
          - -
          - - -
          - -

          - -

          -In this example the problem of -the ``short bar'' is handled. In this example, the sheet music has the -majority of the song in 4/4 time, but bar 4 is in -2/4. This could be handled by setting the TIME -setting to 2 and creating some different patterns. Forcing silence on -the last 2 beats and backing up the counter is a bit easier. - -

          - -
          - -
          - Short Bar Adjustment -
          - - - -
          - -
          1 Cm / / / -
          ... -
          -4 Am / z! / -
          -BeatAdjust -2 -
          ...
          - -
          - - -
          - -

          - -

          -Note that the adjustment factor can be a partial beat. For example: - -

          - - -
          - -
          BeatAdjust .5
          - -
          - -

          -will insert half of a beat between the current bars. - -

          - -

          -
          -Fermata -

          - -

          -A ``fermata'' or ``pause'' in written music tells the musician to hold -a note for a longer period than the notation would otherwise indicate. -In standard music notation it is represented by a -`` -\rotatebox{270}{\textbf{(\raisebox{.5ex}{.}}}'' -above a note. - -

          -To indicate all this -MMA uses a command like: - -

          - - -
          - -
          Fermata 1 1 200
          - -
          - -

          -Note that there are three parts to the command: - -

          - -

            -
          1. The beat offset from the current point in the score to apply the - ``pause''. The offset can be positive or negative and is calculated - from the current bar. Positive numbers will apply to the next bar; - negative to the previous. For offsets into the next bar you use - offsets starting at ``0''; for offsets into the previous bar an - offset of ``-1'' represents the last beat in that bar. - -

            -For example, if you were in 4/4 time and wanted the - quarter note at the end of the next bar to be paused, you would use - an offset of 3. The same effect can be achieved by putting the - FERMATA command after the bar and using an offset of -1. - -

            -

          2. -
          3. The duration of the pause in beats. For example, if you have a - quarter note to pause your duration would be 1, a half note (or 2 - quarter notes) would be 2. - -

            -

          4. -
          5. The adjustment. This represented as a percentage of the current - value. For example, to force a note to be held for twice the normal - time you would use 200 (two-hundred percent). You can use a value - smaller than 100 to force a shorter note, but this is seldom done. - -

            -

          6. -
          - -

          -This example shows how you can -place a FERMATA before or after the effected bar. - -

          - -
          - -
          - Fermata -
          - - Lost Image - -

          - - -
          - -
          -MMA Equivalent -
          -
          -Fermata 3 1 200 -
          -C -
          -Gm7
          - -
          - -
          -

          - - -
          - -
          Alternate -
          -
          -C -
          -Fermata -1 1 200 -
          -Gm7
          - -
          - - -

          - -

          - -

          -Here the second example shows -the first four bars of a popular torch song. The problem with the -piece is that the first beat of bar four needs to be paused, and the -accompaniment style has to switch in the middle of the bar. The -example shows how to split the fourth bar with the first beat on one -line and the balance on a second. The ``z!''s are used to ``fill in'' -the 4 beats skipped by the BEATADJUST. - -

          - -
          - -
          - Fermata with Cut -
          - -

          - Lost Image - -

          - - -
          - -
          C C#dim -
          -G7 -
          -C / C#dim -
          -G7 z! -
          -Fermata -4 1 200 -
          -Cut -3 -
          -BeatAdjust -3.5 -
          -Groove EasySwing -
          -z! G7 C7
          - -
          - -

          - - -

          - -

          - -

          -The following conditions will generate warning messages: - -

          - -

            -
          • A beat offset greater than one bar, - -

            -

          • -
          • A duration greater than one bar, - -

            -

          • -
          • An adjustment value less than 100. - -

            -

          • -
          - -

          -This command works by adjusting the global tempo in the MIDI meta -track at the point of the fermata. In most cases you can put more than -one FERMATA command in the same bar, but they should be in beat -order (no checks are done). If the FERMATA command has a -negative position argument, special code is invoked to remove any -note-on events in the duration specified, after the start of the -beat.13.2 This means that extra rhythm notes will -not be sounded--probably what you expect a held note to sound like. - -

          - -

          -
          -Cut -

          - -

          -This command was born of the need to simulate a ``cut'' or, more -correctly, a ``caesura''. This is indicated in music by two parallel -lines put at the top of a staff indicating the end of a musical -thought. The symbol is also referred to as ``railroad tracks''. - -

          -The idea is to stop the music on all tracks, pause briefly, and -resume.13.3 -

          - -MMA provides the CUT command to help deal with this -situation. But, before the command is described in detail, a -diversion: just how is a note or chord sustained in a MIDI file? - -

          -Assume that a -MMA input file (and the associated library) -files dictates that some notes are to be played from beat 2 to beat 4 -in an arbitrary bar. What -MMA does is: - -

          - -

            -
          • determine the position in the piece as a midi offset to the - current bar, - -

            -

          • -
          • calculate the start and end times for the notes, - -

            -

          • -
          • adjust the times (if necessary) based on adjustable features - such as STRUM, ARTICULATE, RTIME, etc., - -

            -

          • -
          • insert the required MIDI ``note on'' and ``note off'' commands - at the appropriate point in the track. - -

            -

          • -
          - -

          -You may think that a given note starts on beat 2 and ends (using -ARTICULATE 100) right on beat 3--but you would most likely be -wrong. So, if you want the note or chord to be ``cut'', what point do -you use to instruct -MMA correctly? Unfortunately, the simple answer -is ``it depends''. Again, the answers will consist of some examples. - -

          -In this first case you wish to stop the track in the middle of the last -bar. The simplest answer is: - -

          - - -
          - -
          1 C -
          ... -
          -36 C / z! / -
          - -
          - -

          -Unfortunately, this will ``almost'' work. But, any chords which are -longer than one or two beats may continue to sound. This, often, gives -a ``dirty'' sound to the end of the piece. The simple solution is to -add to the end of the piece: - -

          - - -
          - -
          Cut -2
          - -
          - -

          -Depending on the rhythm you might have to fiddle a bit with the cut -value. But, the example here puts a ``all notes off'' message in all -the active tracks at the start of beat 3. The exact same result can be -achieved by placing: - -

          - - -
          - -
          Cut 3
          - -
          - -

          -before the final bar. - -

          -In this second example a tiny bit of silence is desired between bars 4 and -5 (this might be the end of a musical introduction). The following bit should -work: - -

          - - -
          - -
          1 C -
          -2 G -
          -3 G -
          -4 C -
          -Cut -
          -BeatAdjust .2 -
          -5 G -
          ...
          - -
          - -

          -In this case the ``all notes off'' is placed at the end of bar 4 and -two-tenths of a beat is inserted at the same location. Bar 5 continues -the track. - -

          -The final example show how you might combine CUT with -FERMATA. In this case the sheet music shows a caesura after the -first quarter note and fermatas over the quarter notes on beats 2, 3 -and 4. - -

          - - -
          - -
          1 C C#dim -
          -2 G7 -
          -3 C / C#dim -
          -Fermata 1 3 120 -
          -Cut 1.9 -
          -Cut 2.9 -
          -Cut 3.9 -
          -4 G7 / C7 / -
          -5 F6
          - -
          - -

          -A few tutorial notes on the above: - -

          - -

            -
          • The command - -

            - - -
            - -
            Fermata 1 3 120
            - -
            - -

            -applies a slow-down in tempo to the second beat for the following - bar (an offset of 1), for 3 beats. These 3 beats will be played 20% - slower than the set tempo. - -

            -

          • -
          • The three CUT commands insert MIDI ``all notes off'' in - all the active tracks just before beats 2, 3 and 4. - -

            -

          • -
          - -

          -Finally, the proper syntax for the command: - -

          - - -
          - -
          [Voice] Cut [Offset]
          - -
          - -

          -If the voice is omitted, MIDI ``all notes off'' will be inserted into -each active track. - -

          -If the offset is omitted, the current bar position will be used. This -the same as using an offset value of 0. -


          Footnotes

          -
          -
          ... -groove.13.1
          -
          The time value is saved/restored with grooves so - setting a time is redundant in this case. -
          -
          ... -beat.13.2
          -
          Technically speaking, -MMA determines an interval - starting 5% of a beat after the start of the fermata to a point 5% - of a beat before the end. Any MIDI Note-On events in this range (in - all tracks) are deleted. +
          2Above
          +
          The same as ``2'', but the harmony note is raised an + octave. +

          -
          ... -resume.13.3
          -
          The answer to the music theory question of whether - the ``pause'' takes time from the current beat or is treated - as a ``fermata'' is not clear--but as far as -MMA is concerned the - command has no effect on timing. +
          3 or 3Below
          +
          Three part harmony. The harmony notes + selected are lower. +

          -

          +
          3Above
          +
          The same as ``3'', but both notes are raised an + octave. + +

          +

          +
          Open or OpenBelow
          +
          Two part harmony, however the gap + between the two notes is larger than in ``2''. + +

          +

          +
          OpenAbove
          +
          Same as ``Open'', but the added note is above the + original. + +

          +

          +
          8 or 8Below
          +
          A note 1 octave lower is added. + +

          +

          +
          8Above
          +
          A note 2 octave higher is added. + +

          +

          +
          16 or 16Below
          +
          A single note two octaves below is + added. + +

          +

          +
          16Above
          +
          A single note two octaves above are added. + +

          +

          +
          24 or 24Below
          +
          A single note three octaves below is + added. + +

          +

          +
          24Above
          +
          A single note three octaves above is added. + +

          +

          +
          + +

          +You can combine any of the above harmony modes by using a ``+''. For +example: + +

          +
          OPEN+8Below
          +
          will produce harmony notes with an ``Open'' + harmony and a note an octave below the current note. + +

          +

          +
          3Above+16
          +
          will generate 2 harmony notes above the current + note plus a note 2 octaves below. + +

          +

          +
          8Below+8Above+16Below
          +
          will generate 3 notes: one 2 octaves + below the current, one an octave below, and one an octave above. + +

          +

          +
          + +

          +There is no limit to the number of modes you can concatenate. Any +duplicate notes generated will be ignored. + +

          +All harmonies are created using the current chord. + +

          +To disable harmony use a ``0'', ``-'' or ``None''. + +

          +Be careful in using harmonies. They can make your song sound heavy, +especially with BASS notes (applying a different volume may +help). + +

          +The command has no effect in DRUM or CHORD tracks. + +

          + +

          +
          +HarmonyOnly +

          + +

          +As a added feature to the automatic harmony generation discussed in +the previous section, it is possible to set a track so that it +only plays the harmony notes. For example, you might want to +set up two arpeggio tracks with one playing quarter notes on a piano +and a harmony track playing half notes on a violin. The following +snippet is extracted from the song file ``Cry Me A River'' and sets up +2 different choir voices: + +

          + + + +
          + Begin Arpeggio +
              Sequence A4 +
              Voice ChoirAahs +
              Invert 0 1 2 3 +
              SeqRnd +
              Octave 5 +
              RSkip 40 +
              Volume p +
              Articulate 99 +
          +End +
                       +
          +Begin Arpeggio-2 +
              Sequence A4 +
              Voice VoiceOohs +
              Octave 5 +
              RSkip 40 +
              Volume p +
              Articulate 99 +
              HarmonyOnly Open +
          +End
          + +
          + +

          +Just like the HARMONY command, above, you can have different +settings for each bar in your sequence. Setting a bar (or the entire +sequence) to '`-'' or ``0'' disables both the HARMONY and +HARMONYONLY settings. + +

          +The command has no effect in DRUM or CHORD tracks. + +

          +If you want to use this feature with SOLO or MELODY +tracks you can duplicate the notes in your RIFF or in-line +notation or with the AUTOHARMONYTRACKS + COMMAND. + +

          + +

          +
          +HarmonyVolume +

          + +

          +By default, +MMA will use a volume (velocity) of 80% of that used by +the original note for all harmony notes it generates. You can change +this with the the HARMONYVOLUME command. For example: + +

          + + + +
          + Begin Solo +
            Voice JazzGuitar +
            Harmony Open +
            HarmonyVolume 80 +
          +End
          + +
          + +

          +You can specify different values for each bar in the sequence. The +values are percentages and must be greater than 0 (large values works +just fine if you want the harmony louder than the original). The +command has no effect in DRUM or CHORD tracks. +


          - next - up - previous
          - Next: Swing - Up: Next: Tempo and Timing + Up: Reference Manual - Previous: Harmony + Previous: Chord Voicing
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node14.html b/mma/docs/html/ref/node14.html index 8c59e8e..8541607 100644 --- a/mma/docs/html/ref/node14.html +++ b/mma/docs/html/ref/node14.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Swing - +Tempo and Timing + @@ -26,282 +26,910 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Volume and Dynamics - Up: Next: Swing + Up: Reference Manual - Previous: Tempo and Timing + Previous: Harmony

          + +Subsections -

          + + +
          + +

          +
          -Swing +Tempo and Timing

          -In jazz and swing music there is a convention to apply special timing -to eighth notes. Normally, the first of a pair of eights is lengthened -and the second is shortened. In the sheet music this can is sometimes -notated as sequences of a dotted eighth followed by a sixteenth. But, -if you were to foolish enough to play the song with this timing you'd -get a funny look from a jazz musician who will tell you to ``swing'' -the notes. -

          -The easiest way to think about swing eighths is to mentally convert -them to a triplet consisting of a quarter note and and eighth. - -

          -

          - Lost Image - -
          - -

          -In the above music the first and second bar are both played as -in the third. +MMA has a rich set of commands to adjust and vary the timing of your +song.

          -MMA can handle this musical style in a number of ways, the control -is though the SWINGMODE command and options. +

          +Tempo +

          -In default mode -MMA assumes that you don't want your song to swing. - -

          -To enable automatic conversions, simply set SWINGMODE to ``on'': +The tempo of a piece is set in Beats per Minute with the ``Tempo'' +directive.

          - - +
          + + +
          + Tempo 120 -
          SwingMode On
          +
          + +

          +sets the tempo to 120 beats/minute. You can also use the tempo command +to increase or decrease the current rate by including a leading ``+'', +``-'' or ``*'' in the rate. For example (assuming the current rate is +120): + +

          + + +
          + Tempo +10 -
          +

          -This directive accepts the value ``On'' and ``Off'' or ``1'' and -``0''. +will increase the current rate to 130 beats/minute.

          -With SWINGMODE enabled -MMA takes some extra steps when creating -patterns and processing of SOLO and MELODY parts. +The tempo can be changed series of beats, much like a rit. or acc. in +real music. Assuming that a time signature of 4/4, the current tempo +is 120, and there are 4 beats in a bar, the command: + +

          + + + +
          + Tempo 100 1 + +
          + +

          +will cause 4 tempo entries to be placed in the current bar (in the +MIDI meta track). The start of the bar will be 115, the 2nd beat will +be at 110, the 3rd at 105 and the last at 100. + +

          +You can also vary an existing rate using a ``+'', ``-'' or ``*'' in +the rate. + +

          +You can vary the tempo over more than one bar. For example: + +

          + + + +
          + Tempo +20 5.5 + +
          + +

          +tells +MMA to increase the tempo by 20 beats per minute and to step +the increase over the next five and a half bars. Assuming a start +tempo of 100 and 4 beats/bar, the meta track will have a tempo +settings of 101, 102, 103 ...120. This will occur over 22 beats +(5.5 bars * 4 beats) of music. + +

          +Using the multiplier is handy if you are switching to ``double time'': + +

          + + + +
          + Tempo *2 + +
          + +

          +and to return: + +

          + + + +
          + Temp *.5 + +
          + +

          +Note that the ``+'', ``-'' or ``*'' sign must not be separated +from the tempo value by any spaces. The value for TEMPO can be +any value, but will be converted to integer for the final setting. + +

          + +

          +
          +Time +

          + +

          + +MMA doesn't really understand time signatures. It just cares about +the number of beats in a bar. So, if you have a piece in +4/4 time you would use: + +

          + + + +
          + Time 4 + +
          + +

          +For 3/4 use: + +

          + + + +
          + Time 3 + +
          + +

          +For 6/8 you'd probably want either ``2'' or ``6''. + +

          +Changing the time also cancels all existing sequences. So, after a +time directive you'll need to set up your sequences or load a new +groove.14.1 +

          + +

          +TimeSig +

          + +

          +Even though +MMA doesn't really use Time Signatures, some MIDI +programs do recognize and use them. So, here's a command which will +let you insert a Time Signature in your MIDI output: + +

          + + + +
          + TimeSig NN DD + +
          + +

          +The NN parameter is the time signature numerator (the number of beats +per bar). In 3/4 you would set this to ``3''. + +

          +The DD parameter is the time signature denominator (the length of the +note getting a single beat). In 3/4 you would set this to +``4''. + +

          +The NN value must be an integer in the range of 1 to 126. The DD value +must be one of 1, 2, 4, 8, 16, 32 or 64. + +

          + +MMA assumes that all songs are in 4/4 and places that +MIDI event at offset 0 in the Meta track. + +

          +The TIMESIG value is remembered by GROOVEs and is +properly set when grooves are switched. You should probably have a +time signature in any groove library files you create (the supplied +files all do). + +

          +The common time signatures ``common'' and ``cut'' are supported. They +are translated by +MMA to 4/4 and 2/2. + +

          + +

          +
          +BeatAdjust +

          + +

          +Internally, +MMA tracks its position in a song according to beats. +For example, in a 4/4 piece the beat position is +incremented by 4 after each bar is processed. For the most part, this +works fine; however, there are some conditions when it would be nice +to manually adjust the beat position:

            -
          • Any eighth note in a pattern ``on the beat'' (1, 2, etc.) is converted to a - ``81'' note. +
          • Insert some extra (silent) beats at the end of bar to simulate a pause,

          • -
          • Any eighth note is a pattern ``off the beat'' (1.5, 2.5, etc.) - is converted to ``82'' note, and the offset is adjusted to the prior - beat plus the value of an ``81'' note. +
          • Delete some beats to handle a ``short'' bar.

          • -
          • Drum notes with a value of a single MIDI tick are handled in the - same way, but only the offset adjustment is needed. - -

            -

          • -
          • In SOLO and MELODY tracks any successive pairs of - eighth notes (or rests) are adjusted. +
          • Change a pattern in the middle of a bar.

          -Important: when defining patterns and sequences remember that -the adjustment is made when the pattern is compiled. With a -DEFINE command the arguments are compiled (and swing -will be applied). But a SEQUENCE command with an -already defined pattern will use the existing pattern values (the -swing adjustment may or may not have been done at define -time). Finally, if you have a dynamic define in the sequence the -adjustment will take place if needed. +Each problem will be dealt with in turn. In this + example a pause is simulated at the end of bar +10. One problem with this logic is that the inserted beat will be +silent, but certain notes (percussive things like piano) often will +continue to sound (this is related to the decay of the note, not that -

          -SWINGMODE has an additional option, SKEW. This factor -is used to create the ``81'' and ``82'' -note lengths (see here). By -default the value ``66'' is used. This simply means that the note -length ``81'' is assigned 66% of the value of an eight note, and -``82'' is assigned 34%. - -

          -You can change this setting at any point in your song or style -files. It will take effect immediately on all future patterns and solo -lines. - -

          -The setting: +MMA has not turned off the note). Frankly, this really doesn't +work too well ...which is why the FERMATA +(details here) was added.

          - -
          - -
          SwingMode Skew=60
          - -
          - -

          -will set a 60/40 setting. - -

          -If you want to experiment, find a GROOVE with note lengths of -``81'' and ``82'' (``swing'' is as good a choice as any). Now, put a -SWINGMODE SKEW=VALUE directive at the top of your song file (before -selecting any GROOVEs). Compile and play the song with different values -to hear the effects. - -

          -If you want to play with different effects you could do something like -this: - -

          - - - +
          - -
          SwingMode On Skew=40 -
          ... Set CHORD pattern/groove + + + +
          + Adding Extra Beats +
          + + + +
          + Time 4
          -SwingMode Skew=30 -
          ... Set Drum-1 pattern/groove +1 Cm / / / +
          ...
          -SwingMode Skew=whatever -
          ... Set Drum-2
          - -
          - -

          -This will give different rates for different tracks. I'll probably not -enjoy your results, but I play polkas on the accordion for fun. - -

          -The complete SWINGMODE setting is saved in the current GROOVE and can be accessed -via the $_SwingMode built-in macro. - -

          -The easy (and ugly and unintuitive) way to handle swing is to -hard-code the value right into your patterns. For example, you could -set a swing chord pattern with: - -

          - - -
          - -
          Chord Define Swing8 1 3+3 80; 1.33 3 80; 2 3+3 80; 2.33 3 80 ...
          - -
          - -

          -We really don't recommend this for the simple reason that the swing -rate is frozen as quarter/eighth triplets. - -

          -If you refer to the table of note lengths -(here) you will find the cryptic -values of ``81'' and ``82''. These notes are adjusted depending of the -SWINGSKEW value. So: - -

          - - -
          - -
          Chord Define Swing8 1 81 80; 1+81 82 80; 2 81 80; 2+81 82 80 ...
          - -
          - -

          -is a bit better. In this case we have set a chord on beat 1 as the -first of an eighth note, and a chord on the off-beat as the -second. Note how we specify the off-beats as ``1+81'', etc. - -

          -In this example the feel of the swing will vary with the -SWINGSKEW setting. - -

          -But, aren't computers supposed to make life simple? Well, here is our -recommended method: - -

          - - -
          - -
          SwingMode On +10 Am / C /
          -Chord Define Swing8 1 8 80; 1.5 8 80; 2 8 80; 2.5 8 80 ...
          +BeatAdjust 1 +
          ... -
          +

          + + +

          -Now, -MMA will convert the values for you. Magic, well ...almost.

          -There are times when you will need to be more explicit, especially in -SOLO and MELODY tracks: +In this example the problem of +the ``short bar'' is handled. In this example, the sheet music has the +majority of the song in 4/4 time, but bar 4 is in +2/4. This could be handled by setting the TIME +setting to 2 and creating some different patterns. Forcing silence on +the last 2 beats and backing up the counter is a bit easier. + +

          + + + + +
          + Short Bar Adjustment +
          + + + + +
          + 1 Cm / / / +
          ... +
          +4 Am / z! / +
          +BeatAdjust -2 +
          ...
          + +
          + + +
          + +

          + +

          +Note that the adjustment factor can be a partial beat. For example: + +

          + + + +
          + BeatAdjust .5 + +
          + +

          +will insert half of a beat between the current bars. + +

          +Finally in this example, the problem of +overlapping bars is handled. We want to change the GROOVE +in the middle of a bar. So, we create the third bar two times. The first one +has a ``z!'' (silence) for beats 3 and 4; the second has ``z!'' for beats 1 and 2. This +permits the two halves to overlap without conflict. The BEATADJUST +forces the two bars to overlap completely. + +

          + + + + +
          + Mid-Bar Groove Change +
          + + + + +
          + Groove BigBand +
          +1 C +
          +Groove BigBandFill +
          +2 Am +
          +3 / / z! +
          +BeatAdjust -4 +
          +Groove BigBand +
             z! / F +
          +5 F +
          ...
          + +
          + + +
          + +

          + +

          + +

          +
          +Fermata +

          + +

          +A ``fermata'' or ``pause'' in written music tells the musician to hold +a note for a longer period than the notation would otherwise indicate. +In standard music notation it is represented by a +`` +\rotatebox{270}{\textbf{(\raisebox{.5ex}{.}}}'' +above a note. + +

          +To indicate all this +MMA uses a command like: + +

          + + + +
          + Fermata 1 1 200 + +
          + +

          +Note that there are three parts to the command: + +

          + +

            +
          1. The beat offset from the current point in the score to apply the + ``pause''. The offset can be positive or negative and is calculated + from the current bar. Positive numbers will apply to the next bar; + negative to the previous. For offsets into the next bar you use + offsets starting at ``0''; for offsets into the previous bar an + offset of ``-1'' represents the last beat in that bar. + +

            +For example, if you were in 4/4 time and wanted the + quarter note at the end of the next bar to be paused, you would use + an offset of 3. The same effect can be achieved by putting the + FERMATA command after the bar and using an offset of -1. + +

            +

          2. +
          3. The duration of the pause in beats. For example, if you have a + quarter note to pause your duration would be 1, a half note (or 2 + quarter notes) would be 2. + +

            +

          4. +
          5. The adjustment. This represented as a percentage of the current + value. For example, to force a note to be held for twice the normal + time you would use 200 (two-hundred percent). You can use a value + smaller than 100 to force a shorter note, but this is seldom done. + +

            +

          6. +
          + +

          +This example shows how you can +place a FERMATA before or after the effected bar. + +

          + + + + +
          + Fermata +
          + + Lost Image + +

          + + + +
          + +MMA Equivalent +
          +
          +Fermata 3 1 200 +
          +C +
          +Gm7
          + +
          + +
          +

          + + + +
          + Alternate +
          +
          +C +
          +Fermata -1 1 200 +
          +Gm7
          + +
          + + +

          + +

          + +

          +Here the second example shows +the first four bars of a popular torch song. The problem with the +piece is that the first beat of bar four needs to be paused, and the +accompaniment style has to switch in the middle of the bar. The +example shows how to split the fourth bar with the first beat on one +line and the balance on a second. The ``z!''s are used to ``fill in'' +the 4 beats skipped by the BEATADJUST. + +

          + + + + +
          + Fermata with Cut +
          + +

          + Lost Image + +

          + + + +
          + C C#dim +
          +G7 +
          +C / C#dim +
          +G7 z! +
          +Fermata -4 1 200 +
          +Cut -3 +
          +BeatAdjust -3.5 +
          +Groove EasySwing +
          +z! G7 C7
          + +
          + +

          + + +

          + +

          + +

          +The following conditions will generate warning messages:

            -
          • If a bar has both swing and straight eighths. +
          • A beat offset greater than one bar,

          • -
          • If the note following an eighth is not an eight. +
          • A duration greater than one bar, + +

            +

          • +
          • An adjustment value less than 100.

          -
          + +

          +This command works by adjusting the global tempo in the MIDI meta +track at the point of the fermata. In most cases you can put more than +one FERMATA command in the same bar, but they should be in beat +order (no checks are done). If the FERMATA command has a +negative position argument, special code is invoked to remove any +note-on events in the duration specified, after the start of the +beat.14.2 This means that extra rhythm notes will +not be sounded--probably what you expect a held note to sound like. + +

          + +

          +
          +Cut +

          + +

          +This command was born of the need to simulate a ``cut'' or, more +correctly, a ``caesura''. This is indicated in music by two parallel +lines put at the top of a staff indicating the end of a musical +thought. The symbol is also referred to as ``railroad tracks''. + +

          +The idea is to stop the music on all tracks, pause briefly, and +resume.14.3 +

          + +MMA provides the CUT command to help deal with this +situation. But, before the command is described in detail, a +diversion: just how is a note or chord sustained in a MIDI file? + +

          +Assume that a +MMA input file (and the associated library) +files dictates that some notes are to be played from beat 2 to beat 4 +in an arbitrary bar. What +MMA does is: + +

          + +

            +
          • determine the position in the piece as a midi offset to the + current bar, + +

            +

          • +
          • calculate the start and end times for the notes, + +

            +

          • +
          • adjust the times (if necessary) based on adjustable features + such as STRUM, ARTICULATE, RTIME, etc., + +

            +

          • +
          • insert the required MIDI ``note on'' and ``note off'' commands + at the appropriate point in the track. + +

            +

          • +
          + +

          +You may think that a given note starts on beat 2 and ends (using +ARTICULATE 100) right on beat 3--but you would most likely be +wrong. So, if you want the note or chord to be ``cut'', what point do +you use to instruct +MMA correctly? Unfortunately, the simple answer +is ``it depends''. Again, the answers will consist of some examples. + +

          +In this first case you wish to stop the track in the middle of the last +bar. The simplest answer is: + +

          + + + +
          + 1 C +
          ... +
          +36 C / z! / +
          + +
          + +

          +Unfortunately, this will ``almost'' work. But, any chords which are +longer than one or two beats may continue to sound. This, often, gives +a ``dirty'' sound to the end of the piece. The simple solution is to +add to the end of the piece: + +

          + + + +
          + Cut -2 + +
          + +

          +Depending on the rhythm you might have to fiddle a bit with the cut +value. But, the example here puts a ``all notes off'' message in all +the active tracks at the start of beat 3. The exact same result can be +achieved by placing: + +

          + + + +
          + Cut 3 + +
          + +

          +before the final bar. + +

          +In this second example a tiny bit of silence is desired between bars 4 and +5 (this might be the end of a musical introduction). The following bit should +work: + +

          + + + +
          + 1 C +
          +2 G +
          +3 G +
          +4 C +
          +Cut +
          +BeatAdjust .2 +
          +5 G +
          ...
          + +
          + +

          +In this case the ``all notes off'' is placed at the end of bar 4 and +two-tenths of a beat is inserted at the same location. Bar 5 continues +the track. + +

          +The final example show how you might combine CUT with +FERMATA. In this case the sheet music shows a caesura after the +first quarter note and fermatas over the quarter notes on beats 2, 3 +and 4. + +

          + + + +
          + 1 C C#dim +
          +2 G7 +
          +3 C / C#dim +
          +Fermata 1 3 120 +
          +Cut 1.9 +
          +Cut 2.9 +
          +Cut 3.9 +
          +4 G7 / C7 / +
          +5 F6
          + +
          + +

          +A few tutorial notes on the above: + +

          + +

            +
          • The command + +

            + + + +
            + Fermata 1 3 120 + +
            + +

            +applies a slow-down in tempo to the second beat for the following + bar (an offset of 1), for 3 beats. These 3 beats will be played 20% + slower than the set tempo. + +

            +

          • +
          • The three CUT commands insert MIDI ``all notes off'' in + all the active tracks just before beats 2, 3 and 4. + +

            +

          • +
          + +

          +Finally, the proper syntax for the command: + +

          + + + +
          + [Voice] Cut [Offset] + +
          + +

          +If the voice is omitted, MIDI ``all notes off'' will be inserted into +each active track. + +

          +If the offset is omitted, the current bar position will be used. This +the same as using an offset value of 0. +


          Footnotes

          +
          +
          ... +groove.14.1
          +
          The time value is saved/restored with grooves so + setting a time is redundant in this case. + +
          +
          ... +beat.14.2
          +
          Technically speaking, +MMA determines an interval + starting 5% of a beat after the start of the fermata to a point 5% + of a beat before the end. Any MIDI Note-On events in this range (in + all tracks) are deleted. + +
          +
          ... +resume.14.3
          +
          The answer to the music theory question of whether + the ``pause'' takes time from the current beat or is treated + as a ``fermata'' is not clear--but as far as +MMA is concerned the + command has no effect on timing. + +
          +

          - next - up - previous
          - Next: Volume and Dynamics - Up: Next: Swing + Up: Reference Manual - Previous: Tempo and Timing + Previous: Harmony
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node15.html b/mma/docs/html/ref/node15.html index 018d835..70417a1 100644 --- a/mma/docs/html/ref/node15.html +++ b/mma/docs/html/ref/node15.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Volume and Dynamics - +Swing + @@ -26,847 +26,282 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Repeats - Up: Next: Volume and Dynamics + Up: Reference Manual - Previous: Swing + Previous: Tempo and Timing

          - -Subsections - - -
          - -

          - -
          -Volume and Dynamics +Swing

          - -MMA is very versatile when it comes to the volumes or dynamics used in your song. -15.1 -

          -Each generated note goes though several adjustments: +In jazz and swing music there is a convention to apply special timing +to eighth notes. Normally, the first of a pair of eights is lengthened +and the second is shortened. In the sheet music this can is sometimes +notated as sequences of a dotted eighth followed by a sixteenth. But, +if you were to foolish enough to play the song with this timing you'd +get a funny look from a jazz musician who will tell you to ``swing'' +the notes.

          - -

            -
          1. The initial velocity is set in the pattern definition, see - patterns,15.2 -

            -

          2. -
          3. the velocity is then adjusted by the master and - track volume settings (see here - for the discussion of ADJUSTVOLUME RATIO), - -

            -

          4. -
          5. if certain notes are to be accented, yet another adjustment is made, - -

            -

          6. -
          7. and, finally, if the random volume is set, more adjustment. - -

            -

          8. -
          - -

          -For the most part -MMA uses conventional musical score notation for -volumes. Internally, the dynamic name is converted to a percentage -value. The note volume is adjusted by the percentage. - -

          -The following table shows the available volume settings and the adjustment values. +The easiest way to think about swing eighths is to mentally convert +them to a triplet consisting of a quarter note and and eighth.

          - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          Symbolic NameRatio (Percentage) Adjustment
          off0
          pppp5
          ppp10
          pp25
          p40
          mp70
          m100
          mf110
          f130
          ff160
          fff180
          ffff200
          - - -
          + Lost Image

          -The setting OFF is useful for generating fades at the end of a -piece. For example: +In the above music the first and second bar are both played as +in the third.

          - - +
          +MMA can handle this musical style in a number of ways, the control +is though the SWINGMODE command and options. + +

          +In default mode +MMA assumes that you don't want your song to swing. + +

          +To enable automatic conversions, simply set SWINGMODE to ``on'': + +

          + + +
          + SwingMode On -
          Volume ff -
          -Decresc Off 5 -
          -G / Gm / * 5
          - -
          +

          -will cause the last 5 bars of your music to fade from a FF to -silence. +This directive accepts the value ``On'' and ``Off'' or ``1'' and +``0''.

          -The initial velocity of a note is set in the pattern definition (see -patterns). The following -commands set the master volume, track volume and random volume -adjustments. - -

          -In addition to the note velocities generated by -MMA your MIDI -device can also change the mix between channels. See the discussion -for MIDIVOLUME (here). - -

          - -

          -
          -Accent -

          - -

          -``Real musicians''15.3, in an almost -automatic manner, emphasize notes on certain beats. In popular Western -music written in 4/4 time this is usually beats one and -three. This emphasis sets the pulse or beat in a piece. - -

          -In -MMA you can set the velocities in a pattern so that this emphasis is -automatically adjusted. For example, when setting a walking bass line -pattern you could use a pattern definition like: - -

          - - -
          - -
          Define Walk W1234 1 4 100; 2 4 70; 3 4 80; 4 4 70
          - -
          - -

          -However, it is much easier to use a definition which has all the -velocities the same: - -

          - - -
          - -
          Define Walk W1234 1 1 90 * 4
          - -
          - -

          -and use the ACCENT command to increase or decrease the volume -of notes on certain beats: - -

          - - -
          - -
          Walk Accent 1 20 2 -10 4 -10
          - -
          - -

          -The above command will increase the volume for walking bass notes on -beat 1 by 20%, and decrease the volumes of notes on beats 2 and 4 by -10%. - -

          -You can use this command in all tracks. - -

          -When specifying the accents, you must have matching pairs of data. The -first item in the pair is the beat (which can be fractional), the -second is the volume adjustment. This is a percentage of the current -note volume that is added (or subtracted) to the volume. Adjustment -factors must be integers in the range -100 to 100. - -

          -The ACCENTs can apply to all bars in a track; as well, you can set -different accents for different bars. Just use a ``{}'' pair to delimit -each bar. For example: - -

          - - -
          - -
          Bass Accent {1 20} / / {1 30 3 30}
          - -
          - -

          -The above line will set an accent on beat 1 of bars 1, 2 and 3; in -bar 4 beats 1 and 3 will be accented. - -

          -You can use a ``/'' to repeat a setting. The ``/'' can be enclosed in -a ``{}'' delimiter if you want. - -

          - -

          -AdjustVolume -

          - -

          - -

          -Mnemonic Volume Ratios -

          - -

          -The ratios used to adjust the volume can be changed from the table at -the start of this chapter. For example, to change the percentage used -for the MF setting: - -

          - - -
          - -
          AdjustVolume MF=95 f=120
          - -
          - -

          -Note that you can have multiple setting on the same line. - -

          -The values used have the same format as those used for the -VOLUME command, below. For now, a few examples: - -

          - - -
          - -
          AdjustVolume Mf=mp+200
          - -
          - -

          -will set the adjustment factor for ``mf'' to that of ``mp'' plus -200%. - -

          -And, - -

          - - -
          - -
          AdjustVolume mf=+20
          - -
          - -

          -will increase the current ``mf'' setting by 20%. - -

          -You might want to do these adjustment in your MMArc file(s). - -

          - -

          - -
          -Master Volume Ratio -

          - -

          - -MMA uses both the master and track volumes -to determine the final velocity of a note. By default, the track volume -setting accounts for 60% of the adjustment and the master volume for -the remaining 40%. The simple-minded logic behind this is that if the -user goes to the effort of setting a volume for a track, then that is -probably more important than a volume set for the entire piece. - -

          -You can change the ratio used at anytime with the ADJUSTVOLUME RATIO=VALUE -directive. $<$Value$>$ is the percentage to use for the Track volume. A few examples: - -

          - - -
          - -
          AdjustVolume Ratio=60
          - -
          - -

          -This duplicates the default setting. - -

          - - -
          - -
          AdjustVolume Ratio=40
          - -
          - -

          -Volume adjustments use 40% of the track volume and 60% of the master -volume. - -

          - - -
          - -
          AdjustVolume Ratio=100
          - -
          - -

          -Volume adjustments use only the track volume (and ignore the master -volume completely). - -

          - - -
          - -
          AdjustVolume Ratio=0
          - -
          - -

          -Volume adjustments use only the master volume (and ignore the track -volumes completely). - -

          -Any value in the range 0 to 100 can be used as an argument for this -command. This setting is saved in GROOVEs. - -

          -Feel free to experiment with different ratios. - -

          - -

          -
          -Volume -

          - -

          -The volume for a track and the master volume, is set with the VOLUME -command. Volumes can be specified much like standard sheet music with -the conventional dynamic names. These volumes can be applied to a -track or to the entire song. For example: - -

          - - -
          - -
          Arpeggio-Piano Volume p
          - -
          - -

          -sets the volume for the Arpeggio-Piano track to something approximating -piano. - -

          - - -
          - -
          Volume f
          - -
          - -

          -sets the master volume to forte. - -

          -In most cases the volume for a specific track will be set within the GROOVE -definition; the master volume is used in the music file to adjust the -overall feel of the piece. - -

          -When using VOLUME for a specific track, you can use a different -value for each bar in a sequence: - -

          - - -
          - -
          Drum Volume mp ff / ppp
          - -
          - -

          -A ``/'' can be used to repeat values. - -

          -In addition to the ``musical symbols'' like FF and MP you can -also use numeric values to indicate a percentage. In this case you can -use intermediate values to those specified in the table above. For -example, to set the volume between MF and F, you could do -something like: - -

          - - -
          - -
          Volume 87
          - -
          - -

          -But, we don't recommend that you use this! - -

          -A better option is to increment or decrement an existing volume by a -percentage. A numeric value prefaced by a ``+'' or ``-'' is -interpreted as a change. So: - -

          - - -
          - -
          Drum-Snare Volume -20
          - -
          - -

          -would decrement the existing volume of the DRUM-SNARE track by -20%. - -

          -And, finally, for fine tuning you can adjust a ``musical symbol'' -volume by a percentage. The volume ``mf-10'' will generate a volume -10% less than the value of ``mf''; ``f+20'' will generate a volume -20% greater than ``f''. - -

          - -

          -Cresc and Decresc -

          - -

          -If you wish to adjust over a series of bars use the CRESC or -DECRESC commands. These commands work in both the master -context and individual tracks. - -

          -For all practical purposes, the two commands are equivalent, expect -for a possible warning message. If the new volume in less than the -current volume in a CRESC a warning will be displayed; the -converse applies to a DECRESC. In addition, a warning will -be displayed if the effect of either command results in no volume change. - -

          -The command requires two or three arguments. The first argument is an -optional initial volume followed by the new (destination) volume and -the number of bars the adjustment will take. - -

          -For example: - -

          - - -
          - -
          Cresc fff 5
          - -
          - -

          -will gradually vary the master volume from its current setting to a -``triple forte'' over the next 5 bars. Note that the very next bar -will be played at the current volume and the fifth bar at fff -with the other three bars at increasing volumes. - -

          -Similarly: - -

          - - -
          - -
          Drum-Snare Decresc mp 2
          - -
          - -

          -will decrease the ``drum-snare'' volume to ``mezzo piano'' over the next 2 bars. - -

          -Finally, consider: - -

          - - -
          - -
          Cresc pp mf 4
          - -
          - -

          -which will set the current volume to PP and then increase it to -MF over the next 4 bars. Again, note that the very next bar -will be played at pp and the fourth at mf. - -

          -You can use numeric values (not recommended!) in these directives: - -

          - - -
          - -
          Cresc 20 100 4
          - -
          - -

          -As well as increment/decrement: - -

          - - -
          - -
          Volume ff -
          ... -
          -Decresc -10 -40 4
          - -
          - -

          -The above example will first set the volume to 10% less than the -current FF setting. Then it will decrease the volume over the next -4 bars to a volume 40% less than the new setting for the first bar. - -

          -A SEQCLEAR command will reset all track volumes to the default -M. - -

          -When applying CRESC or DECRESC on a specific track the -volume for all the sequences will be the same. For this reason, a -warning is displayed if the volumes for each bar in the current -sequence are not the same. - -

          - -

          -
          -RVolume -

          - -

          -Not even the best musician can play each note at the same volume. Nor -would he or she want to--the result would be quite unmusical ... -so -MMA tries to be a bit human by randomly adjusting note volume -with the RVOLUME command. - -

          -The command can be applied to any specific track. Examples: - -

          - - -
          - -
          Chord RVolume 10 -
          -Drum-Snare RVolume 5
          - -
          - -

          -The RVOLUME argument is a percentage value by which a volume is -adjusted. A setting of 0 disables the adjustment for a track (this is -the default). - -

          -When set, the note velocity (after the track and master volume -adjustments) is randomized up or down by the value. Again, using the -above example, let us assume that a note in the current pattern gets a -MIDI velocity of 88. The random factor of 10 will adjust this by 10% -up or down--the new value can be from 78 to 98. - -

          -The idea behind this is to give the track a more human sounding -effect. You can use large values, but it's not recommended. Usually, -values in the 5 to 10 range work well. You might want slightly larger -values for drum tracks. Using a value greater than 30 will generate a -warning message. - -

          -Notes: +With SWINGMODE enabled +MMA takes some extra steps when creating +patterns and processing of SOLO and MELODY parts.

            -
          • No generated value will be out of the valid MIDI velocity range - of 1 to 127. +
          • Any eighth note in a pattern ``on the beat'' (1, 2, etc.) is converted to a + ``81'' note.

          • -
          • A different value can be used for each bar in a sequence: - -

            - - -
            - -
            Scale RVolume 10 0 / 20
            - -
            +

          • Any eighth note is a pattern ``off the beat'' (1.5, 2.5, etc.) + is converted to ``82'' note, and the offset is adjusted to the prior + beat plus the value of an ``81'' note.

          • -
          • A ``/'' can be used to repeat values. +
          • Drum notes with a value of a single MIDI tick are handled in the + same way, but only the offset adjustment is needed. + +

            +

          • +
          • In SOLO and MELODY tracks any successive pairs of + eighth notes (or rests) are adjusted.

          - -

          -Saving and Restoring Volumes -

          +Important: when defining patterns and sequences remember that +the adjustment is made when the pattern is compiled. With a +DEFINE command the arguments are compiled (and swing +will be applied). But a SEQUENCE command with an +already defined pattern will use the existing pattern values (the +swing adjustment may or may not have been done at define +time). Finally, if you have a dynamic define in the sequence the +adjustment will take place if needed.

          -Dynamics can get quite complicated, especially when you are adjusting -the volumes of a track inside a repeat or other complicated sections -of music. In this section attempts to give some general -guidelines and hints. +SWINGMODE has an additional option, SKEW. This factor +is used to create the ``81'' and ``82'' +note lengths (see here). By +default the value ``66'' is used. This simply means that the note +length ``81'' is assigned 66% of the value of an eight note, and +``82'' is assigned 34%.

          -For the most part, the supplied groove files will have balanced -volumes between the different instruments. If you find that some -instruments or drum tones are consistently too loud or soft, spend some -time with the chapter on Fine Tuning. +You can change this setting at any point in your song or style +files. It will take effect immediately on all future patterns and solo +lines.

          -Remember that GROOVEs save all the current volume settings. -This includes the master setting as well as individual track settings. -So, if you are using the mythical groove ``Wonderful'' and think that -the Chord-Piano volume should be louder in a particular song -it's easy to do something like: +The setting:

          - - +
          + + +
          + SwingMode Skew=60 -
          Groove Wonderful +
          + +

          +will set a 60/40 setting. + +

          +If you want to experiment, find a GROOVE with note lengths of +``81'' and ``82'' (``swing'' is as good a choice as any). Now, put a +SWINGMODE SKEW=VALUE directive at the top of your song file (before +selecting any GROOVEs). Compile and play the song with different values +to hear the effects. + +

          +If you want to play with different effects you could do something like +this: + +

          + + +
          + SwingMode On Skew=40 +
          ... Set CHORD pattern/groove
          -Chord-Piano Volume ff +SwingMode Skew=30 +
          ... Set Drum-1 pattern/groove
          -DefGroove Wonderful
          +SwingMode Skew=whatever +
          ... Set Drum-2 -
          +

          -Now, when you call this groove the new volume will be used. Note that -you'll have to do this for each variation of the groove that you use -in the song. +This will give different rates for different tracks. I'll probably not +enjoy your results, but I play polkas on the accordion for fun.

          -In most songs you will not need to do major changes. But, it is nice -to use the same volume each time though a section. In most cases -you'll want to do a explicit setting at the start of a section. For -example: +The complete SWINGMODE setting is saved in the current GROOVE and can be accessed +via the $_SwingMode built-in macro. + +

          +The easy (and ugly and unintuitive) way to handle swing is to +hard-code the value right into your patterns. For example, you could +set a swing chord pattern with:

          - - +
          + +
          + Chord Define Swing8 1 3+3 80; 1.33 3 80; 2 3+3 80; 2.33 3 80 ... -
          Repeat -
          -Volume mf -
          .... -
          -Cresc ff 5 -
          ... -
          -EndRepeat
          - -
          +

          -Another useful technique is the use of the $_LASTVOLUME -macro. For example: +We really don't recommend this for the simple reason that the swing +rate is frozen as quarter/eighth triplets. + +

          +If you refer to the table of note lengths +(here) you will find the cryptic +values of ``81'' and ``82''. These notes are adjusted depending of the +SWINGSKEW value. So:

          - - +
          + +
          + Chord Define Swing8 1 81 80; 1+81 82 80; 2 81 80; 2+81 82 80 ... -
          Volume pp -
          ... -
          -Cresc f 5 -
          ... -
          $_LastVolume // restores to pp
          - -
          +

          -


          Footnotes

          -
          -
          ... song.15.1
          -
          We'll try to be consistent and refer to a MIDI - ``volume'' as a ``velocity'' and internal -MMA adjustments to velocity as volumes. +is a bit better. In this case we have set a chord on beat 1 as the +first of an eighth note, and a chord on the off-beat as the +second. Note how we specify the off-beats as ``1+81'', etc. -
          -
          ...sec-pats,15.2
          -
          Solo and - Melody track notes use an initial velocity of 90. +

          +In this example the feel of the swing will vary with the +SWINGSKEW setting. -

          -
          ... musicians''15.3
          -
          as opposed to mechanical. +

          +But, aren't computers supposed to make life simple? Well, here is our +recommended method: -

          -

          +

          + + + +
          + SwingMode On +
          +Chord Define Swing8 1 8 80; 1.5 8 80; 2 8 80; 2.5 8 80 ...
          + +
          + +

          +Now, +MMA will convert the values for you. Magic, well ...almost. + +

          +There are times when you will need to be more explicit, especially in +SOLO and MELODY tracks: + +

          + +

            +
          • If a bar has both swing and straight eighths. + +

            +

          • +
          • If the note following an eighth is not an eight. + +

            +

          • +
          +
          - next - up - previous
          - Next: Repeats - Up: Next: Volume and Dynamics + Up: Reference Manual - Previous: Swing + Previous: Tempo and Timing
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node16.html b/mma/docs/html/ref/node16.html index 7fd9221..1d08b5b 100644 --- a/mma/docs/html/ref/node16.html +++ b/mma/docs/html/ref/node16.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Repeats - +Volume and Dynamics + @@ -26,258 +26,908 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Variables, Conditionals and Jumps - Up: Next: Repeats + Up: Reference Manual - Previous: Volume and Dynamics + Previous: Swing

          + +Subsections -

          + + +
          + +

          + +
          +Volume and Dynamics

          -MMA attempts to be as comfortable to use as standard sheet music. -This includes repeats and endings. - +MMA is very versatile when it comes to the volumes or dynamics used in your song. +16.1

          -More complex structures like D.S., Coda, etc. are -not directly supported. But, they are easily simulated with by -using some simple variables, conditionals and GOTOs. See -Variables for details. -Often as not, it may be easier to use your editor to cut, paste and -duplicate. Another, alternate, method of handling complicated repeats -is to set sections of code in MSET (more - here) variables and simply expand those. - -

          -A section of music to be repeated is indicated with a REPEAT -and REPEATEND or ENDREPEAT16.1 In addition, you can have REPEATENDINGS. +Each generated note goes though several adjustments:

          -
          - - +
          - Repeats -
          +
            +
          1. The initial velocity is set in the pattern definition, see + patterns,16.2 +

            +

          2. +
          3. the velocity is then adjusted by the master and + track volume settings (see here + for the discussion of ADJUSTVOLUME RATIO),

            - Lost Image -
            -
            -
            -
            -

            +

          4. +
          5. if certain notes are to be accented, yet another adjustment is made, - -
            - -
            Repeat -
            -1 Am -
            -2 C -
            -RepeatEnding 2 -
            -3 D7 -
            -RepeatEnding -
            -4 D7 / Dm -
            -RepeatEnd -
            -5 G7 -
            -6 A
            - -
            +

            +

          6. +
          7. and, finally, if the random volume is set, more adjustment. + +

            +

          8. +
          + +

          +For the most part +MMA uses conventional musical score notation for +volumes. Internally, the dynamic name is converted to a percentage +value. The note volume is adjusted by the percentage. + +

          +The following table shows the available volume settings and the adjustment values. + +

          +

          + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          Symbolic NameRatio (Percentage) Adjustment
          off0
          pppp5
          ppp10
          pp25
          p40
          mp70
          m100
          mf110
          f130
          ff160
          fff180
          ffff200
          -
          +
          + + + +

          +The setting OFF is useful for generating fades at the end of a + piece. For example:

          -

          -In this example -MMA produces -music with bars: - -

          -

          -1, 2, 3, + + +
          + Volume ff
          -1, 2, 3, +Decresc Off 5
          -1, 2, 4, -
          -1, 2, 5, 6 - - - -

          -This works just like standard sheet music. Note that both -REPEATENDING and REPEATEND can take an optional argument -indicating the number of times to use the ending or to repeat the -block. The effect of an optional count for REPEATENDING is -illustrated in the example, above. The following simple example: - -

          - - - +
          +G / Gm / * 5 -
          Repeat +
          + +

          +will cause the last 5 bars of your music to fade from a FF to + silence. + +

          +The initial velocity of a note is set in the pattern definition (see + patterns). The following + commands set the master volume, track volume and random volume + adjustments. + +

          +In addition to the note velocities generated by +MMA your MIDI + device can also change the mix between channels. See the discussion + for MIDIVOLUME (here). + +

          + +


          -1  Am -
          -2  Cm -
          -RepeatEnd 3
          +Accent +

          + +

          +``Real musicians''16.3, in an almost + automatic manner, emphasize notes on certain beats. In popular Western + music written in 4/4 time this is usually beats one and + three. This emphasis sets the pulse or beat in a piece. + +

          +In +MMA you can set the velocities in a pattern so that this emphasis is + automatically adjusted. For example, when setting a walking bass line + pattern you could use a pattern definition like: + +

          + + +
          + Define Walk W1234 1 4 100; 2 4 70; 3 4 80; 4 4 70 -
          +

          -Will expand to: -

          -1, 2, -
          -1, 2, -
          -1, 2 - -
          - -

          -Note that the optional argument ``3'' produces a total of three -copies. The default argument for REPEAT is ``2''. Using ``1'' -cancels the REPEAT and ``0'' deletes the entire section. Using -``1'' and ``0'' are useful in setting up Coda sections where you want -a different count the second time the section is played. Note that the -count argument can be a macro. Have a look at the sample file -repeats.mma for lots of examples. - -

          -Combining optional counts with both REPEATENDING and -REPEATEND is permitted. Another example: +However, it is much easier to use a definition which has all the + velocities the same:

          - - +
          + + +
          + Define Walk W1234 1 1 90 * 4 -
          Repeat -
          -1 Am -
          -2 C -
          -RepeatEnding 2 -
          -3 D7 -
          -RepeatEnd 2
          +
          + +

          +and use the ACCENT command to increase or decrease the volume + of notes on certain beats: + +

          + + +
          + Walk Accent 1 20 2 -10 4 -10 -
          +

          -Produces: -

          -1, 2, 3, -
          -1, 2, 3, -
          -1, 2, -
          -1, 2 +The above command will increase the volume for walking bass notes on + beat 1 by 20%, and decrease the volumes of notes on beats 2 and 4 by + 10%. -
          +

          +You can use this command in all tracks. + +

          +When specifying the accents, you must have matching pairs of data. The + first item in the pair is the beat (which can be fractional), the + second is the volume adjustment. This is a percentage of the current + note volume that is added (or subtracted) to the volume. Adjustment + factors must be integers in the range -100 to 100. + +

          +The ACCENTs can apply to all bars in a track; as well, you can set + different accents for different bars. Just use a ``{}'' pair to delimit + each bar. For example:

          -MMA processes repeats by reading the input file and creating -duplicates of the repeated material. This means that a directive in -the repeated material would be processed multiple times. Unless you -know what you are doing, directives should not be inserted in repeat -sections. Be especially careful if you define a pattern inside a -repeat. Using TEMPO with a ``+'' or ``-'' will be problematic -as well. - -

          -Repeats can be nested to any level. - -

          -Some count values for REPEATEND or ENDREPEAT and -REPEATENDING will generate a warning message. Using the -optional text NoWarn as the first argument will supress the -message: - -

          - - - +
          + +
          + Bass Accent {1 20} / / {1 30 3 30} -
          Repeat -
          ... -
          -RepeatEnd Nowarn 1
          - -
          +
          + +

          +The above line will set an accent on beat 1 of bars 1, 2 and 3; in + bar 4 beats 1 and 3 will be accented. + +

          +You can use a ``/'' to repeat a setting. The ``/'' can be enclosed in + a ``{}'' delimiter if you want. + +

          + +

          +AdjustVolume +

          + +

          + +

          +Mnemonic Volume Ratios +

          + +

          +The ratios used to adjust the volume can be changed from the table at + the start of this chapter. For example, to change the percentage used + for the MF setting: + +

          + + + +
          + AdjustVolume MF=95 f=120 + +
          + +

          +Note that you can have multiple setting on the same line. + +

          +The values used have the same format as those used for the + VOLUME command, below. For now, a few examples: + +

          + + + +
          + AdjustVolume Mf=mp+200 + +
          + +

          +will set the adjustment factor for ``mf'' to that of ``mp'' plus + 200%. + +

          +And, + +

          + + + +
          + AdjustVolume mf=+20 + +
          + +

          +will increase the current ``mf'' setting by 20%. + +

          +You might want to do these adjustment in your MMArc file(s). + +

          + +

          + +
          +Master Volume Ratio +

          + +

          + +MMA uses both the master and track volumes + to determine the final velocity of a note. By default, the track volume + setting accounts for 60% of the adjustment and the master volume for + the remaining 40%. The simple-minded logic behind this is that if the + user goes to the effort of setting a volume for a track, then that is + probably more important than a volume set for the entire piece. + +

          +You can change the ratio used at anytime with the ADJUSTVOLUME RATIO=VALUE + directive. $<$Value$>$ is the percentage to use for the Track volume. A few examples: + +

          + + + +
          + AdjustVolume Ratio=60 + +
          + +

          +This duplicates the default setting. + +

          + + + +
          + AdjustVolume Ratio=40 + +
          + +

          +Volume adjustments use 40% of the track volume and 60% of the master + volume. + +

          + + + +
          + AdjustVolume Ratio=100 + +
          + +

          +Volume adjustments use only the track volume (and ignore the master + volume completely). + +

          + + + +
          + AdjustVolume Ratio=0 + +
          + +

          +Volume adjustments use only the master volume (and ignore the track + volumes completely). + +

          +Any value in the range 0 to 100 can be used as an argument for this + command. This setting is saved in GROOVEs. + +

          +Feel free to experiment with different ratios. + +

          + +

          +
          +Volume +

          + +

          +The volume for a track and the master volume, is set with the VOLUME + command. Volumes can be specified much like standard sheet music with + the conventional dynamic names. These volumes can be applied to a + track or to the entire song. For example: + +

          + + + +
          + Arpeggio-Piano Volume p + +
          + +

          +sets the volume for the Arpeggio-Piano track to something approximating + piano. + +

          + + + +
          + Volume f + +
          + +

          +sets the master volume to forte. + +

          +In most cases the volume for a specific track will be set within the GROOVE + definition; the master volume is used in the music file to adjust the + overall feel of the piece. + +

          +When using VOLUME for a specific track, you can use a different + value for each bar in a sequence: + +

          + + + +
          + Drum Volume mp ff / ppp + +
          + +

          +A ``/'' can be used to repeat values. + +

          +In addition to the ``musical symbols'' like FF and MP you can + also use numeric values to indicate a percentage. In this case you can + use intermediate values to those specified in the table above. For + example, to set the volume between MF and F, you could do + something like: + +

          + + + +
          + Volume 87 + +
          + +

          +But, we don't recommend that you use this! + +

          +A better option is to increment or decrement an existing volume by a + percentage. A numeric value prefaced by a ``+'' or ``-'' is + interpreted as a change. So: + +

          + + + +
          + Drum-Snare Volume -20 + +
          + +

          +would decrement the existing volume of the DRUM-SNARE track by + 20%. + +

          +And, finally, for fine tuning you can adjust a ``musical symbol'' + volume by a percentage. The volume ``mf-10'' will generate a volume + 10% less than the value of ``mf''; ``f+20'' will generate a volume + 20% greater than ``f''. + +

          + +

          +Cresc and Decresc +

          + +

          +If you wish to adjust over a series of bars use the CRESC or + DECRESC commands. These commands work in both the master + context and individual tracks. + +

          +For all practical purposes, the two commands are equivalent, expect + for a possible warning message. If the new volume in less than the + current volume in a CRESC a warning will be displayed; the + converse applies to a DECRESC. In addition, a warning will + be displayed if the effect of either command results in no volume change. + +

          +The command requires two or three arguments. The first argument is an + optional initial volume followed by the new (destination) volume and + the number of bars the adjustment will take. + +

          +For example: + +

          + + + +
          + Cresc fff 5 + +
          + +

          +will gradually vary the master volume from its current setting to a + ``triple forte'' over the next 5 bars. Note that the very next bar + will be played at the current volume and the fifth bar at fff + with the other three bars at increasing volumes. + +

          +Similarly: + +

          + + + +
          + Drum-Snare Decresc mp 2 + +
          + +

          +will decrease the ``drum-snare'' volume to ``mezzo piano'' over the next 2 bars. + +

          +Finally, consider: + +

          + + + +
          + Cresc pp mf 4 + +
          + +

          +which will set the current volume to PP and then increase it to + MF over the next 4 bars. Again, note that the very next bar + will be played at pp and the fourth at mf. + +

          +You can use numeric values (not recommended!) in these directives: + +

          + + + +
          + Cresc 20 100 4 + +
          + +

          +As well as increment/decrement: + +

          + + + +
          + Volume ff +
          ... +
          +Decresc -10 -40 4
          + +
          + +

          +The above example will first set the volume to 10% less than the + current FF setting. Then it will decrease the volume over the next + 4 bars to a volume 40% less than the new setting for the first bar. + +

          +A SEQCLEAR command will reset all track volumes to the default + M. + +

          +When applying CRESC or DECRESC on a specific track the + volume for all the sequences will be the same. For this reason, a + warning is displayed if the volumes for each bar in the current + sequence are not the same. + +

          +You may find that certain volume adjustments don't create the volumes + you are expecting. In most cases this will be due to the fact that + +MMA uses a master and track volume to determine the final + result. So, if you want a fade at the end of a piece you might do: + +

          + + + +
          + Decresc m pppp 4 + +
          + +

          +and find that the volume on the last bar is still too loud. There are + two simple solutions: + +

          + +

            +
          • Add a command to decrease the track volumes. For example: + +

            + + + +
            + Alltracks Decresc m pppp 4 + +
            + +

            +in addition to to the master setting. + +

            +

          • +
          • Change the ratio between track and master settings: + +

            + + + +
            + AdjustVolume Ratio=0 + +
            + +

            +or some other small value. + +

            +

          • +
          + +

          +These methods will produce similar, but different results. + +

          + +

          +
          +RVolume +

          + +

          +Not even the best musician can play each note at the same volume. Nor +would he or she want to--the result would be quite unmusical ... +so +MMA tries to be a bit human by randomly adjusting note volume +with the RVOLUME command. + +

          +The command can be applied to any specific track. Examples: + +

          + + + +
          + Chord RVolume 10 +
          +Drum-Snare RVolume 5
          + +
          + +

          +The RVOLUME argument is a percentage value by which a volume is +adjusted. A setting of 0 disables the adjustment for a track (this is +the default). + +

          +When set, the note velocity (after the track and master volume +adjustments) is randomized up or down by the value. Again, using the +above example, let us assume that a note in the current pattern gets a +MIDI velocity of 88. The random factor of 10 will adjust this by 10% +up or down--the new value can be from 78 to 98. + +

          +The idea behind this is to give the track a more human sounding +effect. You can use large values, but it's not recommended. Usually, +values in the 5 to 10 range work well. You might want slightly larger +values for drum tracks. Using a value greater than 30 will generate a +warning message. + +

          +Notes: + +

          + +

            +
          • No generated value will be out of the valid MIDI velocity range + of 1 to 127. + +

            +

          • +
          • A different value can be used for each bar in a sequence: + +

            + + + +
            + Scale RVolume 10 0 / 20 + +
            + +

            +

          • +
          • A ``/'' can be used to repeat values. + +

            +

          • +
          + +

          + +

          +Saving and Restoring Volumes +

          + +

          +Dynamics can get quite complicated, especially when you are adjusting +the volumes of a track inside a repeat or other complicated sections +of music. In this section attempts to give some general +guidelines and hints. + +

          +For the most part, the supplied groove files will have balanced +volumes between the different instruments. If you find that some +instruments or drum tones are consistently too loud or soft, spend some +time with the chapter on Fine Tuning. + +

          +Remember that GROOVEs save all the current volume settings. +This includes the master setting as well as individual track settings. +So, if you are using the mythical groove ``Wonderful'' and think that +the Chord-Piano volume should be louder in a particular song +it's easy to do something like: + +

          + + + +
          + Groove Wonderful +
          +Chord-Piano Volume ff +
          +DefGroove Wonderful
          + +
          + +

          +Now, when you call this groove the new volume will be used. Note that +you'll have to do this for each variation of the groove that you use +in the song. + +

          +In most songs you will not need to do major changes. But, it is nice +to use the same volume each time though a section. In most cases +you'll want to do a explicit setting at the start of a section. For +example: + +

          + + + +
          + Repeat +
          +Volume mf +
          .... +
          +Cresc ff 5 +
          ... +
          +EndRepeat
          + +
          + +

          +Another useful technique is the use of the $_LASTVOLUME +macro. For example: + +

          + + + +
          + Volume pp +
          ... +
          +Cresc f 5 +
          ... +
          $_LastVolume // restores to pp
          + +

          -There must be one REPEATEND or ENDREPEAT for every -REPEAT. Any number of REPEATENDINGs can be included -before the REPEATEND.


          Footnotes

          -
          ...ENDREPEAT16.1
          -
          The reason for both - ENDREPEAT and REPEATEND is to match IFEND and - ENDIF. +
          ... song.16.1
          +
          We'll try to be consistent and refer to a MIDI + ``volume'' as a ``velocity'' and internal +MMA adjustments to velocity as volumes. + +
          +
          ...sec-pats,16.2
          +
          Solo and + Melody track notes use an initial velocity of 90. + +
          +
          ... musicians''16.3
          +
          as opposed to mechanical.

          - next - up - previous
          - Next: Variables, Conditionals and Jumps - Up: Next: Repeats + Up: Reference Manual - Previous: Volume and Dynamics + Previous: Swing
          -Bob -2006-10-15 +bob +2007-03-07
          diff --git a/mma/docs/html/ref/node17.html b/mma/docs/html/ref/node17.html index fef618c..25e716b 100644 --- a/mma/docs/html/ref/node17.html +++ b/mma/docs/html/ref/node17.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Variables, Conditionals and Jumps - +Repeats + @@ -26,1393 +26,259 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
          - Next: Low Level MIDI Commands - Up: Next: Variables, Conditionals and Jumps + Up: Reference Manual - Previous: Repeats + Previous: Volume and Dynamics

          - -Subsections - - -
          - -

          - -
          -Variables, Conditionals and Jumps -

          - -

          -To make the processing of your music easier, -MMA supports a very -primitive set for variable manipulations along with some conditional -testing and the oft-frowned-upon GOTO command. - -

          - -

          -Variables +Repeats

          -MMA lets you set a variable, much like in other programming -languages and to do some basic manipulations on them. Variables are -most likely to be used for two reasons: +MMA attempts to be as comfortable to use as standard sheet music. +This includes repeats and endings. + +

          +More complex structures like D.S., Coda, etc. are +not directly supported. But, they are easily simulated with by +using some simple variables, conditionals and GOTOs. See +Variables for details. +Often as not, it may be easier to use your editor to cut, paste and +duplicate. Another, alternate, method of handling complicated repeats +is to set sections of code in MSET (more + here) variables and simply expand those. + +

          +A section of music to be repeated is indicated with a REPEAT +and REPEATEND or ENDREPEAT17.1 In addition, you can have REPEATENDINGS.

          -

            -
          • For use in setting up conditional segments of your file, + + +
            + Repeats +

            - -

          • As a shortcut to entering complex chord sequences. - -

            -

          • - - -

            -To begin, the following list shows the available commands to set and manipulate variables: - -

            - - - +
            - -
            Set VariableName
            String
            + Lost Image +

            -Mset VariableName ... MsetEnd
            -UnSet VariableName
            -ShowVars +

            + + +
            + Repeat
            -Inc Variablename [value] +1 Am
            -Dec Variablename [value] +2 C
            -Vexpand ON/Off
            - -
            - -

            -All variable names are case-insensitive. Any characters can be used in -a variable name. The only exceptions are that a variable name cannot -start with a ``$'' or a ``_'' (an underscore--this is reserved for -internal variables, see below). - -

            -Variables are set and manipulated by using their names. Variables are -expanded when their name is prefaced by a space followed by single -``$'' sign. For example: - -

            - - -
            - -
            Set Silly Am / Bm / +RepeatEnding 2
            -1 $Silly
            - -
            - -

            -The first line creates the variable ``Silly''; the second creates a -bar of music with the chords ``Am / Bm /''. - -

            -Note that the ``$'' must be the first item on a line or follow a -space character. For example, the following will NOT work: - -

            - - -
            - -
            Set Silly 4a;b;c;d; +3 D7
            -1 Am {$Silly}
            - -
            - -

            -However: - -

            - - -
            - -
            1 Am { $Silly}
            - -
            - -

            -will work fine. - -

            -Following are details on all the available variable commands: - -

            - -

            -Set [string] -

            - -

            -Set or create a variable. You can skip the String if you do -want to assign an empty string to the variable. A valid example is: - -

            - - -
            - -
            Set PassCount 1
            - -
            - -

            -You can concatenate variables or constants by using a single ``+''. -For example: - -

            - - - +
            - -
            Groove Rhumba +RepeatEnding
            -Repeat -
            ... +4 D7 / Dm
            -Set a $_Groove + Sus +RepeatEnd
            -Groove $a -
            ... +5 G7
            -Groove Rhumba1 +6 A
            + +
            + + +

            + +

            + +

            +In this example +MMA produces +music with bars: + +

            +

            +1, 2, 3,
            -Repeatend
            - -
            - -

            -This can be useful in calling GROOVE variations. - -

            - -

            +1, 2, 3,
            -Mset [lines] MsetEnd/EndMset -

            - -

            -This command is quite similar to SET, but MSET expects -multiple lines. An example: - -

            - - - +
            - -
            MSet LongVar +1, 2, 4,
            -1 Cm +1, 2, 5, 6 + +
            + +

            +This works just like standard sheet music. Note that both +REPEATENDING and REPEATEND can take an optional argument +indicating the number of times to use the ending or to repeat the +block. The effect of an optional count for REPEATENDING is +illustrated in the example, above. The following simple example: + +

            + + +
            + Repeat
            -2 Gm +1  Am
            -3 G7 +2  Cm
            -MsetEnd
            +RepeatEnd 3 -
            +

            -It is quite possible to set a variable to hold an entire section of -music (perhaps a chorus) and insert this via macro expansion at -various places in your file. - -

            -Each MSET must be terminated by a ENDMSET or -MSETEND command (on its own separate line). - -

            -Be careful if you use an MSET variable in a PRINT -statement ...you'll probably get an error. The PRINT -command will print the first line of the variable and the -remainder will be reinserted into the input stream for interpretation. - -

            -Special code in -MMA will maintain the block settings from -BEGIN/END. So, you can do something like: - -

            - - -
            - -
            Mset Spam -
              Line one -
              Line 2 -
              333 +Will expand to: +
            +1, 2,
            -EndMset +1, 2,
            -Begin Print -
              $Spam +1, 2 + +
            + +

            +Note that the optional argument ``3'' produces a total of three +copies. The default argument for REPEAT is ``2''. Using ``1'' +cancels the REPEAT and ``0'' deletes the entire section. Using +``1'' and ``0'' are useful in setting up Coda sections where you want +a different count the second time the section is played. Note that the +count argument can be a macro. Have a look at the sample file +repeats.mma for lots of examples. + +

            +Combining optional counts with both REPEATENDING and +REPEATEND is permitted. Another example: + +

            + + +
            + Repeat
            -End
            - -
            - -

            - -

            -RndSet -

            - -

            -There are times when you may want a random value to use in selecting a GROOVE or -for other more creative purposes. The RNDSET command sets a variable from -a value in a list. The list can be anything; just remember that each whitespace -forms the start of a new item. So, - -

            - - -
            - -
            RndSet Var 1 2 3 4 5
            - -
            - -

            -will set $VAR to one of the values 1, 2, 3, 4 or 5. - -

            -You could use this to randomly select a GROOVE: - -

            - - -
            - -
            Groove $var Groove1 Groove2 Groove3
            - -
            - -

            -Alternately, - -

            - - -
            - -
            RndSet Grv Groove1 Groove2 Groove3
            - -
            - -

            -will set $GRV to one of ``Groove1'', ``Groove2'' or ``Groove3''. - -

            -Then you can do the same as in the earlier example with: - -

            - - -
            - -
            Groove $Grv
            - -
            - -

            -You can also have fun using random values for timing, transposition, etc. - -

            - -

            -UnSet VariableName -

            - -

            -Removes the variable. This can be useful if you have conditional tests -which simply rely on a certain variable being ``defined''. - -

            - -

            -ShowVars -

            - -

            -Mainly used for debugging, this command displays the names of the -defined variables and their contents. The display will preface each -variable name with a ``$''. Note that internal -MMA variables are not -displayed with this command. - -

            -You can call SHOWVARS with an argument list. In this case the -values of the variables names in the list will be printed. Variables -which do not exist will not cause an error. Eg: - -

            - - -
            - -
            ShowVars xXx Count foo -
               $XXX - not defined -
               $COUNT: 11 -
               $FOO: This is Foo
            - -
            - -

            - -

            -Inc and Dec -

            - -

            -These commands increment or decrement a variable. If no argument is -given, a value of 1 is used; otherwise, the value specified is used. -The value can be an integer or a floating point number. - -

            -A short example: - -

            - - - +
            - -
            Set PassCount 1 +1 Am
            -Set Foobar 4 +2 C
            -Showvars +RepeatEnding 2
            -Inc FooBar 4 +3 D7
            -Inc PassCount +RepeatEnd 2
            + +
            + +

            +Produces: +

            +1, 2, 3,
            -ShowVars
            - -
            - -

            -This command is quite useful for creating conditional tests for proper -handling of codas or groove changes in repeats. - -

            - -

            -VExpand On or Off -

            - -

            -Normally variable expansion is enabled. These two options will turn -expansion on or off. Why would you want to do this? Well, here's a -simple example: - -

            - - - +
            - -
            Set LeftC Am Em +1, 2, 3,
            -Set RightC G / +1, 2,
            -VExpand Off +1, 2 + +
            + +

            + +MMA processes repeats by reading the input file and creating +duplicates of the repeated material. This means that a directive in +the repeated material would be processed multiple times. Unless you +know what you are doing, directives should not be inserted in repeat +sections. Be especially careful if you define a pattern inside a +repeat. Using TEMPO with a ``+'' or ``-'' will be problematic +as well. + +

            +Repeats can be nested to any level. + +

            +Some count values for REPEATEND or ENDREPEAT and +REPEATENDING will generate a warning message. Using the +optional text NoWarn as the first argument will supress the +message: + +

            + + +
            + Repeat +
            ...
            -Set Full $LeftC $RightC -
            -VExpand On
            +RepeatEnd Nowarn 1 -
            +

            -In this case the actual contents of the variable ``Full'' is ``$LeftC -$RightC''. If the OFF/ON option lines had not been used, the -contents would be ``Am Em G /''. You can easily verify this with the -SHOWVARS option. - -

            -When -MMA processes a file it expands variables in a recursive -manner. This means that, in the above example, the line: - -

            - - -
            - -
            1 $Full
            - -
            - -

            -will be changed to: - -

            - - -
            - -
            1 Am Em G /
            - -
            - -

            -However, if later in the file, you change the definition of one of the -variables ...for example: - -

            - - -
            - -
            Set LeftC Am /
            - -
            - -

            -the same line will now be ``1 Am / G /''. - -

            -Most of -MMA 's internal commands can be redefined with -variables. However, you really shouldn't use this feature. -It's been left for two reasons: it might be useful, and, it's hard to -disable. - -

            -However, not all commands can be redefined. The following is short -list of things which will work (but, again, not all suggestions should -be used!): - -

            - - -
            - -
            Set Rate Tempo 120 -
            $Rate -
            -Set R Repeat -
            $R
            - -
            - -

            -But, the following will not work: - -

            - - -
            - -
            Set B Begin -
            -Set E End -
            $B Arpeggio Define -
            .... -
            $E
            - -
            - -

            -This fails since the Begin/End constructs are expanded before variable -expansion. However: - -

            - - -
            - -
            Set A Define Arpeggio -
            -Begin $a ... End
            - -
            - -

            -is quite alright. - -

            -Even though you can use a variable to substitute for the REPEAT -or IF directives, using one for REPEATEND, ENDREPEAT, -REPEATENDING, LABEL, IFEND or ENDIF will fail. - -

            -Variable expansion should usually not be a concern. In most normal -files, -MMA will expand variables as they are encountered. However, -when reading the data in a REPEAT, IF or MSET -section the expansion function is skipped--but, when the lines are -processed, after being stored in an internal queue, variables are -expanded. - -

            - -

            -StackValue -

            - -

            -Sometimes you just want to save a value for a few lines of code. The -STACKVALUE command will save its arguments. You can later -retrive them via the $_StackValue macro. For example (taken from the -stdpats.mma file): - -

            - - -
            - -
            StackValue $_SwingMode -
            -SwingMode On -
            -Begin Drum Define -
              Swing8 1 0 90 * 8 -
            -End -
              ... -
            -SwingMode $_StackValue
            - -
            - -

            -Note that the $_StackValue macro removes the last value from the -stack. If you invoke the macro when there is nothing saved an error -will occur. - -

            - -

            -Predefined Variables -

            - -

            -For your convenience -MMA tracks a number of internal settings and -you can access these values with special macros.17.1 All of these ``system'' variables are -prefaced with a single underscore. For example, the current tempo is -displayed with the variable $_TEMPO. - -

            -There are two categories of system variables. The first are the simple -values for global settings: - -

            -

            -
              $_AutoLibPath
            -
            Current AUTOLIBPATH setting. - -

            -

            -
              $_BarNum
            -
            Current bar number of song. - -

            -

            -
              $_Debug
            -
            Current debug settings. - -

            -

            -
              $_Groove
            -
            Name of the currently selected groove. May be - empty if no groove has been selected. - -

            -

            -
              $_KeySig
            -
            Key signature as defined in song file. If no - keysignature is set the somewhat cryptic 0# will be returned. - -

            -

            -
              $_LineNum
            -
            Line number in current file. - -

            -

            -
              $_IncPath
            -
            Current INCPATH setting. - -

            -

            -
              $_LastDebug
            -
            Debug settings prior to last DEBUG - command. This setting can be used to restore settings, IE: - -

            - - -
            - -
            Debug Warnings=off -
            ... stuff generating annoying warnings -
            -Debug $_LastDebug
            - -
            - -

            -

            -
              $_LastGroove
            -
            Name of the groove selected before the - currently selected groove. - -

            -

            -
              $_LastVolume
            -
            Previously set global volume setting. - -

            -

            -
              $_LibPath
            -
            Current LIBPATH setting. - -

            -

            -
              $_Lyric
            -
            Current LYRIC settings. - -

            -

            -
              $_MIDISplit
            -
            List of SPLITCHANNELS. - -

            -

            -
              $_OutPath
            -
            Current OUTPATH setting. - -

            -

            -
              $_SeqRnd
            -
            Global SEQRND setting (on, off or track list). - -

            -

            -
              $_SeqRndWeight
            -
            Global SEQRNDWEIGHT settings. - -

            -

            -
              $_SeqSize
            -
            Current SEQSIZE setting. - -

            -

            -
              $_SwingMode
            -
            Current SWINGMODE setting (On or Off) - and the Skew value. - -

            -

            -
              $_StackValue
            -
            The last value stored on the STACKVALUE - stack. - -

            -

            -
              $_Tempo
            -
            Current TEMPO. Note that if you have used - the optional bar count in setting the tempo this will be the - target tempo. - -

            -

            -
              $_Time
            -
            The current TIME (beats per bar) setting. - -

            -

            -
              $_ToneTr
            -
            List of all TONETR settings. - -

            -

            -
              $_Transpose
            -
            Current TRANSPOSE setting. - -

            -

            -
              $_VExpand
            -
            VExpand value (On/Off). Not very useful since you - can't enable VEXPAND back with a macro. - -

            -

            -
              $_VoiceTr
            -
            List of all VOICETR settings. - -

            -

            -
              $_Volume
            -
            Current global volume setting. - -

            -

            -
              $_VolumeRatio
            -
            Global volume ratio (track vrs. master) from - ADJUSTVOLUME Ratio setting. - -

            -

            -
            - -

            -The second type of system variable is for settings in a certain track. -Each of these variables is in the form $_TRACKNAME_VALUE. For -example, the current voice setting for the ``Bass-Sus'' track can be -accessed with the variable $_Bass-Sus_Voice. - -

            -If the associated command permits a value for each sequence in your -pattern, the macro will more than one value. For example (assuming a -SEQSIZE of 4): - -

            - - -
            - -
            Bass Octave 3 4 2 4 -
            -Print $_Bass_Octave -
            ... -
            -3 4 2 4
            - -
            - -

            -The following are the available ``TrackName'' macros: - -

            -

            -
              $_TRACKNAME_Accent
            -
            -
            -
              $_TRACKNAME_Articulate
            -
            -
            -
              $_TRACKNAME_Channel
            -
            Assigned MIDI channel 1-16, 0 if not assigned. -
            -
              $_TRACKNAME_Compress
            -
            -
            -
              $_TRACKNAME_Direction
            -
            -
            -
              $_TRACKNAME_DupRoot
            -
            (only permitted in Chord Tracks) -
            -
              $_TRACKNAME_Harmony
            -
            -
            -
              $_TRACKNAME_HarmonyVolume
            -
            -
            -
              $_TRACKNAME_Invert
            -
            -
            -
              $_TRACKNAME_Limit
            -
            -
            -
              $_TRACKNAME_Mallet
            -
            Rate and delay values (only valid in - Solo and Melody tracks) -
            -
              $_TRACKNAME_NoteSpan
            -
            -
            -
              $_TRACKNAME_Octave
            -
            -
            -
              $_TRACKNAME_Range
            -
            -
            -
              $_TRACKNAME_Rskip
            -
            -
            -
              $_TRACKNAME_Rtime
            -
            -
            -
              $_TRACKNAME_Rvolume
            -
            -
            -
              $_TRACKNAME_SeqRnd
            -
            -
            -
              $_TRACKNAME_SeqRndWeight
            -
            -
            -
              $_TRACKNAME_Strum
            -
            (only permitted in Chord tracks) -
            -
              $_TRACKNAME_Tone
            -
            (only permitted in Drum tracks) -
            -
              $_TRACKNAME_Unify
            -
            -
            -
              $_TRACKNAME_Voice
            -
            -
            -
              $_TRACKNAME_Voicing
            -
            (only permitted in Chord tracks) -
            -
              $_TRACKNAME_Volume
            -

            -

            -
            - -

            -The ``TrackName'' macros are useful in copying values between -non-similar tracks and CHSHARE tracks. For example: - -

            - - -
            - -
            Begin Bass -
              Voice AcousticBass -
              Octave 3 -
              ... -
            -End -
            -Begin Walk -
              ChShare Bass -
              Voice $_Bass_Voice -
              Octave $_Bass_Octave -
              ... -
            -End
            - -
            - -

            - -

            -Conditionals -

            - -

            -The most important reason to have variables in -MMA is to use them -available in conditionals. In -MMA a conditional consists of a line -starting with an IF directive, a test, a series of lines to -process (depending upon the result of the test), and a closing -ENDIF or IFEND17.2 directive. An optional ELSE statement may be included. - -

            -The first set of tests are unary (they take no arguments): - -

            -

            -
            Def VariableName
            -
            Returns true if the variable has been defined. - -

            -

            -
            Ndef VariableName
            -
            Returns true if the variable has not been - defined. - -

            -

            -
            - -

            -In the above tests you must supply the name of a variable--don't make -the mistake of including a ``$'' which will invoke expansion and -result in something you were not expecting. - -

            -A simple example: - -

            - - -
            - -
            If Def InCoda -
              5 Cm -
              6 / -
            -Endif
            - -
            - -

            -The other tests are binary (they take two arguments): - -

            -

            -
            LT Str1 Str2
            -
            Returns true if Str1 is less than - Str2. (Please see the discussion below on how the tests are - done.) - -

            -

            -
            LE Str1 Str2
            -
            Returns true if str1 is less than or equal - to Str2. - -

            -

            -
            EQ Str1 Str2
            -
            Returns true if str1 is equal to - Str2. - -

            -

            -
            NE Str1 Str2
            -
            Returns true if str1 is not equal to - Str2. - -

            -

            -
            GT Str1 Str2
            -
            Returns true if str1 is greater than - Str2. - -

            -

            -
            GE Str1 Str2
            -
            Returns true if str1 is greater than or - equal to Str2. - -

            -

            -
            - -

            -In the above tests you have several choices in specifying Str1 -and Str2. At some point, when -MMA does the actual comparison, -two strings or numeric values are expected. So, you really could do: - -

            - - -
            - -
            If EQ abc ABC
            - -
            - -

            -and get a ``true'' result. The reason that ``abc'' equals ``ABC'' is -that all the comparisons in -MMA are case-insensitive. - -

            -You can also compare a variable to a string: - -

            - - -
            - -
            If GT $foo abc
            - -
            - -

            -will evaluate to ``true'' if the contents of the variable -``foo'' evaluates to something ``greater than'' ``abc''. But, there is -a bit of a ``gotcha' here. If you have set ``foo'' to a two word -string, then -MMA will choke on the command. In the following -example: - -

            - - -
            - -
            Set Foo A B -
            -If GT $Foo abc
            - -
            - -

            -the comparison is passed the line: - -

            - - -
            - -
            If GT A B abc
            - -
            - -

            -and -MMA seeing three arguments generates an error. If you want the -comparison done on a variable which might be more than one word, use -the ``$$'' syntax. This delays the expansion of the variable until -the IF directive is entered. So: - -

            - - -
            - -
            If $$foo abc
            - -
            - -

            -would generate a comparison between ``A B'' and ``ABC''. - -

            -Delayed expansion can be applied to either variable. It only works in -an IF directive. - -

            -Strings and numeric values can be confusing in comparisons. For -example, if you have the strings ``22'' and ''3'' and compare them as -strings, ``3'' is greater than ``22''; however, if you compare them as -values then 3 is less than 22. - -

            -The rule in -MMA is quite simple: If either string in a comparison is -a numeric value, both strings are converted to values. Otherwise they -are compared as strings.17.3 -

            -This lets you do consistent comparisons in situations like: - -

            - - -
            - -
            Set Count 1 -
            -If LE $$Count 4 -
              .... -
            -IfEnd
            - -
            - -

            -Note that the above example could have used ``$Count'', but you -should probably always use the ``$$'' in tests. - -

            -Much like other programming languages, an optional ELSE -condition may be used: - -

            - - -
            - -
            If Def Coda -
              Groove Rhumba1 -
            -Else -
              Groove Rhumba -
            -Endif
            - -
            - -

            -The ELSE statement(s) are processed only if the test for the -IF test is false. - -

            -Nesting of IFs is permitted: - -

            - - -
            - -
            If ndef Foo -
              Print Foo has been defined. -
            -Else -
              If def bar -
                Print bar has been defined. Cool. -
              Else -
                Print no bar...go thirsty. -
              Endif -
            -Endif
            - -
            - -

            -works just fine. Indentation has been used in these examples to clearly -show the nesting and conditions. You should do the same. - -

            - -

            -Goto -

            - -

            -The GOTO command redirects the execution order of your script to -the point at which a LABEL or line number has been defined. There are really -two parts to this: - -

            - -

              -
            1. A command defining a label, and, - -

              -

            2. -
            3. The GOTO command. - -

              -

            4. -
            - -

            - -

            -A label is set with the LABEL directive: - -

            - - -
            - -
            Label Point1
            - -
            - -

            -The string defining the label can be any sequence of characters. -Labels are case-insensitive. - -

            -To make this look a lot more line those old BASIC progams, any lines -starting with a line number are considered to be label lines as -well. - -

            -A few considerations on labels and linenumbers: - -

            - -

              -
            • A duplicate label generated with a LABEL command will - generate an error. - -

              -

            • -
            • A line number label duplicating a LABEL is an error. - -

              -

            • -
            • A LABEL duplicating a line number is an error. - -

              -

            • -
            • Duplicate line numbers are permitted. The last one encountered - will be the one used. - -

              -

            • -
            • All label points are generated when the file is opened, not as it is - parsed. - -

              -

            • -
            • Line numbers (really, just comments) do not need to be in any - order. - -

              -

            • -
            - -

            - -

            -The command: - -

            - - -
            - -
            Goto Point1
            - -
            - -

            -causes an immediate jump to a new point in the file. If you are -currently in repeat or conditional segment of the file, the remaining -lines in that segment will be ignored. - -

            - -MMA does not check to see if you are jumping into a repeat or -conditional section of code--but doing so will usually cause an -error. Jumping out of these sections is usually safe. - -

            -The following example shows the use of both types of label. In this -example only lines 2, 3, 5 and 6 will be processed. - -

            - - -
            - -
            Goto Foo -
            -1 Cm -
            -Label Foo -
            -2 Dm -
            -3 / -
            -Goto 5 -
            -4 Am -
            -5 Cm -
            -6 Dm
            - -
            - -

            -For an example of how to use some simple labels to simulate a ``DS al -Coda'' examine the file ``lullaby-of-Broadway'' in the sample songs -directory. +There must be one REPEATEND or ENDREPEAT for every +REPEAT. Any number of REPEATENDINGs can be included +before the REPEATEND.


            Footnotes

            -
            ... macros.17.1
            -
            The values - are dynamically created and reflect the current settings, and may - not be exactly the same as the value you originally set due to - internal roundings, etc. - -
            -
            ...IFEND17.2
            -
            -MMA 's author probably suffers - from mild dyslexia and can't remember if the command is IFEND or - ENDIF, so both are permitted. Use whichever is more comfortable for - you. - -
            -
            ... strings.17.3
            -
            An attempt is made to convert each - string to a float. If conversion of both strings is successful, the - comparison is made between two floats, otherwise two strings are - used. +
            ...ENDREPEAT17.1
            +
            The reason for both + ENDREPEAT and REPEATEND is to match IFEND and + ENDIF.

            - next - up - previous
            - Next: Low Level MIDI Commands - Up: Next: Variables, Conditionals and Jumps + Up: Reference Manual - Previous: Repeats + Previous: Volume and Dynamics
            -Bob -2006-10-15 +bob +2007-03-07
            diff --git a/mma/docs/html/ref/node18.html b/mma/docs/html/ref/node18.html index b4b8bd3..b14934b 100644 --- a/mma/docs/html/ref/node18.html +++ b/mma/docs/html/ref/node18.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Low Level MIDI Commands - +Variables, Conditionals and Jumps + @@ -37,11 +37,11 @@ original version by: Nikos Drakos, CBLU, University of Leeds previous
            Next: Fine Tuning (Translations) + HREF="node19.html">Low Level MIDI Commands Up: Reference Manual Previous: Variables, Conditionals and Jumps + HREF="node17.html">Repeats

            @@ -50,1450 +50,1298 @@ original version by: Nikos Drakos, CBLU, University of Leeds

            - +
            -Low Level MIDI Commands +Variables, Conditionals and Jumps

            -The commands discussed in this chapter directly effect your MIDI -output devices. - -

            -Not all MIDI devices are equal. Many of the effects in this chapter -may be ignored by your devices. Sorry, but that's just the way MIDI -is. +To make the processing of your music easier, +MMA supports a very +primitive set for variable manipulations along with some conditional +testing and the oft-frowned-upon GOTO command.

            -

            -
            -Channel +

            +Variables

            -As noted in Tracks and Channels -MMA assigns MIDI channels -dynamically as it creates tracks. In most cases this works fine; -however, you can if you wish force the assignment of a specific MIDI -channel to a track with the CHANNEL command. -

            -You cannot assign a channel number to a track if it already defined -(well, see the section CHSHARE, below, for the inevitable -exception), nor can you change the channel assignments for any of the -DRUM tracks. - -

            -Let us assume that you want the Bass track assigned to MIDI -channel 8. Simply use: +MMA lets you set a variable, much like in other programming +languages and to do some basic manipulations on them. Variables are +most likely to be used for two reasons:

            - - +
            +
              +
            • For use in setting up conditional segments of your file, + +

              +

            • +
            • As a shortcut to entering complex chord sequences. + +

              +

            • +
            + +

            +To begin, the following list shows the available commands to set and manipulate variables: + +

            + + + +
            + Set VariableName String +
            +Mset VariableName ... MsetEnd +
            +UnSet VariableName +
            +ShowVars +
            +Inc Variablename [value] +
            +Dec Variablename [value] +
            +Vexpand ON/Off
            -
            Bass Channel 8
            +
            + +

            +All variable names are case-insensitive. Any characters can be used in +a variable name. The only exceptions are that a variable name cannot +start with a ``$'' or a ``_'' (an underscore--this is reserved for +internal variables, see below). + +

            +Variables are set and manipulated by using their names. Variables are +expanded when their name is prefaced by a space followed by single +``$'' sign. For example: + +

            + + +
            + Set Silly Am / Bm / +
            +1 $Silly
            -
            +

            -Caution: If the selected channel is already in use an error will be -generated. Due to the way -MMA allocates tracks, if you really need -to manually assign track it is recommended that you do this in a -MMARC file. +The first line creates the variable ``Silly''; the second creates a +bar of music with the chords ``Am / Bm /''.

            - -

            -You can disable a channel at any time by using a channel number of 0: +Note that the ``$'' must be the first item on a line or follow a +space character. For example, the following will NOT work:

            - - +
            + + +
            + Set Silly 4a;b;c;d; +
            +1 Am {$Silly}
            -
            Arpeggio-1 Channel 0
            +
            + +

            +However: + +

            + + +
            + 1 Am { $Silly} -
            +

            -will disable the Arpeggio-1 channel, freeing it for use by other -tracks. A warning message is generated. Disabling a track without a -valid channel is fine. When you set a channel to 0 the track is also -disabled. You can restart the track with the ON command -(here). +will work fine.

            -You don't need to have a valid MIDI channel assigned to a track to do -things like: MIDIPAN, MIDIGLIS, MIDIVOLUME or -even the assignment of any music to a track. MIDI data is created in -tracks and then sent out to the MIDI buffers. Channel assignment is -checked and allocated at this point, and an error will be generated if -no channels are available. - -

            -It's quite acceptable to do channel reassignments in the middle of a -song. Just assign channel 0 to the unneeded track first. - -

            -MIDI channel settings are not saved in GROOVEs. +Following are details on all the available variable commands:

            -MMA inserts a MIDI ``track name'' meta event when the channel -buffers are first assigned at a MIDI offset of 0. If the MIDI channel -is reassigned, a new ``track name'' is inserted at the current song -offset. +

            +Set +

            -A more general method is to use CHANNELPREF detailed below. +Set or create a variable. You can skip the String if you do +want to assign an empty string to the variable. A valid example is:

            -You can access the currently assigned channel with the $_TRACK_CHANNEL macro. + + + +
            + Set PassCount 1 + +
            + +

            +You can concatenate variables or constants by using a single ``+''. +For example: + +

            + + + +
            + Groove Rhumba +
            +Repeat +
            ... +
            +Set a $_Groove + Sus +
            +Groove $a +
            ... +
            +Groove Rhumba1 +
            +Repeatend
            + +
            + +

            +This can be useful in calling GROOVE variations. + +

            + +

            +NewSet +

            + +

            +The NEWSET command works the same as SET with the +exception that that it is completely ignored if the variable already +exists. So, + +

            + + + +
            + NewSet ChordVoice JazzGuitar + +
            + +

            +and + +

            + + + +
            + If NDef ChordVoice +
            +Set ChordVoice JazzGuitar +
            +Endif
            + +
            + +

            +have identical results. + +

            + +

            +
            +Mset +

            + +

            +This command is quite similar to SET, but MSET expects +multiple lines. An example: + +

            + + + +
            + MSet LongVar +
            +1 Cm +
            +2 Gm +
            +3 G7 +
            +MsetEnd
            + +
            + +

            +It is quite possible to set a variable to hold an entire section of +music (perhaps a chorus) and insert this via macro expansion at +various places in your file. + +

            +Each MSET must be terminated by a ENDMSET or +MSETEND command (on its own separate line). + +

            +Be careful if you use an MSET variable in a PRINT +statement ...you'll probably get an error. The PRINT +command will print the first line of the variable and the +remainder will be reinserted into the input stream for interpretation. + +

            +Special code in +MMA will maintain the block settings from +BEGIN/END. So, you can do something like: + +

            + + + +
            + Mset Spam +
              Line one +
              Line 2 +
              333 +
            +EndMset +
            +Begin Print +
              $Spam +
            +End
            + +
            + +

            + +

            +RndSet +

            + +

            +There are times when you may want a random value to use in selecting a GROOVE or +for other more creative purposes. The RNDSET command sets a variable from +a value in a list. The list can be anything; just remember that each whitespace +forms the start of a new item. So, + +

            + + + +
            + RndSet Var 1 2 3 4 5 + +
            + +

            +will set $VAR to one of the values 1, 2, 3, 4 or 5. + +

            +You could use this to randomly select a GROOVE: + +

            + + + +
            + Groove $var Groove1 Groove2 Groove3 + +
            + +

            +Alternately, + +

            + + + +
            + RndSet Grv Groove1 Groove2 Groove3 + +
            + +

            +will set $GRV to one of ``Groove1'', ``Groove2'' or ``Groove3''. + +

            +Then you can do the same as in the earlier example with: + +

            + + + +
            + Groove $Grv + +
            + +

            +You can also have fun using random values for timing, transposition, etc. + +

            + +

            +UnSet VariableName +

            + +

            +Removes the variable. This can be useful if you have conditional tests +which simply rely on a certain variable being ``defined''. + +

            + +

            +ShowVars +

            + +

            +Mainly used for debugging, this command displays the names of the +defined variables and their contents. The display will preface each +variable name with a ``$''. Note that internal +MMA variables are not +displayed with this command. + +

            +You can call SHOWVARS with an argument list. In this case the +values of the variables names in the list will be printed. Variables +which do not exist will not cause an error. Eg: + +

            + + + +
            + ShowVars xXx Count foo +
               $XXX - not defined +
               $COUNT: 11 +
               $FOO: This is Foo
            + +
            + +

            + +

            +Inc and Dec +

            + +

            +These commands increment or decrement a variable. If no argument is +given, a value of 1 is used; otherwise, the value specified is used. +The value can be an integer or a floating point number. + +

            +A short example: + +

            + + + +
            + Set PassCount 1 +
            +Set Foobar 4 +
            +Showvars +
            +Inc FooBar 4 +
            +Inc PassCount +
            +ShowVars
            + +
            + +

            +This command is quite useful for creating conditional tests for proper +handling of codas or groove changes in repeats. + +

            + +

            +VExpand On or Off +

            + +

            +Normally variable expansion is enabled. These two options will turn +expansion on or off. Why would you want to do this? Well, here's a +simple example: + +

            + + + +
            + Set LeftC Am Em +
            +Set RightC G / +
            +VExpand Off +
            +Set Full $LeftC $RightC +
            +VExpand On
            + +
            + +

            +In this case the actual contents of the variable ``Full'' is ``$LeftC +$RightC''. If the OFF/ON option lines had not been used, the +contents would be ``Am Em G /''. You can easily verify this with the +SHOWVARS option. + +

            +When +MMA processes a file it expands variables in a recursive +manner. This means that, in the above example, the line: + +

            + + + +
            + 1 $Full + +
            + +

            +will be changed to: + +

            + + + +
            + 1 Am Em G / + +
            + +

            +However, if later in the file, you change the definition of one of the +variables ...for example: + +

            + + + +
            + Set LeftC Am / + +
            + +

            +the same line will now be ``1 Am / G /''. + +

            +Most of +MMA 's internal commands can be redefined with +variables. However, you really shouldn't use this feature. +It's been left for two reasons: it might be useful, and, it's hard to +disable. + +

            +However, not all commands can be redefined. The following is short +list of things which will work (but, again, not all suggestions should +be used!): + +

            + + + +
            + Set Rate Tempo 120 +
            $Rate +
            +Set R Repeat +
            $R
            + +
            + +

            +But, the following will not work: + +

            + + + +
            + Set B Begin +
            +Set E End +
            $B Arpeggio Define +
            .... +
            $E
            + +
            + +

            +This fails since the Begin/End constructs are expanded before variable +expansion. However: + +

            + + + +
            + Set A Define Arpeggio +
            +Begin $a ... End
            + +
            + +

            +is quite alright. + +

            +Even though you can use a variable to substitute for the REPEAT +or IF directives, using one for REPEATEND, ENDREPEAT, +REPEATENDING, LABEL, IFEND or ENDIF will fail. + +

            +Variable expansion should usually not be a concern. In most normal +files, +MMA will expand variables as they are encountered. However, +when reading the data in a REPEAT, IF or MSET +section the expansion function is skipped--but, when the lines are +processed, after being stored in an internal queue, variables are +expanded. + +

            + +

            +StackValue +

            + +

            +Sometimes you just want to save a value for a few lines of code. The +STACKVALUE command will save its arguments. You can later +retrive them via the $_StackValue macro. For example (taken from the +stdpats.mma file): + +

            + + + +
            + StackValue $_SwingMode +
            +SwingMode On +
            +Begin Drum Define +
              Swing8 1 0 90 * 8 +
            +End +
              ... +
            +SwingMode $_StackValue
            + +
            + +

            +Note that the $_StackValue macro removes the last value from the +stack. If you invoke the macro when there is nothing saved an error +will occur.

            -ChannelPref +Predefined Variables

            -If you prefer to have certain tracks assigned to certain channels you -can use the CHANNELPREF command to create a custom set of -preferences. By default, -MMA assigns channels starting at 16 and -working down to 1 (with the expectation of drum tracks which are all -assigned channel 10). If, for example, you would like the Bass -track to be on channel 9, sustained bass on channel 3, and -Arpeggio on channel 5, you can have a command like: +For your convenience +MMA tracks a number of internal settings and +you can access these values with special macros.18.1 All of these ``system'' variables are +prefaced with a single underscore. For example, the current tempo is +displayed with the variable $_TEMPO. + +

            +There are two categories of system variables. The first are the simple +values for global settings: + +

            +

            +
              $_AutoLibPath
            +
            Current AUTOLIBPATH setting. + +

            +

            +
              $_BarNum
            +
            Current bar number of song. + +

            +

            +
              $_Debug
            +
            Current debug settings. + +

            +

            +
              $_Groove
            +
            Name of the currently selected groove. May be + empty if no groove has been selected. + +

            +

            +
              $_KeySig
            +
            Key signature as defined in song file. If no + keysignature is set the somewhat cryptic 0# will be returned. + +

            +

            +
              $_LineNum
            +
            Line number in current file. + +

            +

            +
              $_IncPath
            +
            Current INCPATH setting. + +

            +

            +
              $_LastDebug
            +
            Debug settings prior to last DEBUG + command. This setting can be used to restore settings, IE:

            - -
            - -
            ChannelPref Bass=9 Arpeggio=5 Bass-Sus=3
            - -
            - -

            -Most likely this will be in your MMARC file. - -

            -You can use multiple command lines, or have multiple assignments on a -single line. Just make sure that each item consists of a trackname, an -``='' and a channel number in the range 1 to 16. - -

            - -

            + + +
            + Debug Warnings=off +
            ... stuff generating annoying warnings
            -ChShare +Debug $_LastDebug
            + +
            + +

            +

            +
              $_LastGroove
            +
            Name of the groove selected before the + currently selected groove. + +

            +

            +
              $_LastVolume
            +
            Previously set global volume setting. + +

            +

            +
              $_LibPath
            +
            Current LIBPATH setting. + +

            +

            +
              $_Lyric
            +
            Current LYRIC settings. + +

            +

            +
              $_MIDISplit
            +
            List of SPLITCHANNELS. + +

            +

            +
              $_OutPath
            +
            Current OUTPATH setting. + +

            +

            +
              $_SeqRnd
            +
            Global SEQRND setting (on, off or track list). + +

            +

            +
              $_SeqRndWeight
            +
            Global SEQRNDWEIGHT settings. + +

            +

            +
              $_SeqSize
            +
            Current SEQSIZE setting. + +

            +

            +
              $_SwingMode
            +
            Current SWINGMODE setting (On or Off) + and the Skew value. + +

            +

            +
              $_StackValue
            +
            The last value stored on the STACKVALUE + stack. + +

            +

            +
              $_Tempo
            +
            Current TEMPO. Note that if you have used + the optional bar count in setting the tempo this will be the + target tempo. + +

            +

            +
              $_Time
            +
            The current TIME (beats per bar) setting. + +

            +

            +
              $_ToneTr
            +
            List of all TONETR settings. + +

            +

            +
              $_Transpose
            +
            Current TRANSPOSE setting. + +

            +

            +
              $_VExpand
            +
            VExpand value (On/Off). Not very useful since you + can't enable VEXPAND back with a macro. + +

            +

            +
              $_VoiceTr
            +
            List of all VOICETR settings. + +

            +

            +
              $_Volume
            +
            Current global volume setting. + +

            +

            +
              $_VolumeRatio
            +
            Global volume ratio (track vrs. master) from + ADJUSTVOLUME Ratio setting. + +

            +

            +
            + +

            +The second type of system variable is for settings in a certain track. +Each of these variables is in the form $_TRACKNAME_VALUE. For +example, the current voice setting for the ``Bass-Sus'' track can be +accessed with the variable $_Bass-Sus_Voice. + +

            +If the associated command permits a value for each sequence in your +pattern, the macro will more than one value. For example (assuming a +SEQSIZE of 4): + +

            + + + +
            + Bass Octave 3 4 2 4 +
            +Print $_Bass_Octave +
            ... +
            +3 4 2 4
            + +
            + +

            +The following are the available ``TrackName'' macros: + +

            +

            +
              $_TRACKNAME_Accent
            +
            +
            +
              $_TRACKNAME_Articulate
            +
            +
            +
              $_TRACKNAME_Channel
            +
            Assigned MIDI channel 1-16, 0 if not assigned. +
            +
              $_TRACKNAME_Compress
            +
            +
            +
              $_TRACKNAME_Direction
            +
            +
            +
              $_TRACKNAME_DupRoot
            +
            (only permitted in Chord Tracks) +
            +
              $_TRACKNAME_Harmony
            +
            +
            +
              $_TRACKNAME_HarmonyVolume
            +
            +
            +
              $_TRACKNAME_Invert
            +
            +
            +
              $_TRACKNAME_Limit
            +
            +
            +
              $_TRACKNAME_Mallet
            +
            Rate and delay values (only valid in + Solo and Melody tracks) +
            +
              $_TRACKNAME_NoteSpan
            +
            +
            +
              $_TRACKNAME_Octave
            +
            +
            +
              $_TRACKNAME_Range
            +
            +
            +
              $_TRACKNAME_Rskip
            +
            +
            +
              $_TRACKNAME_Rtime
            +
            +
            +
              $_TRACKNAME_Rvolume
            +
            +
            +
              $_TRACKNAME_SeqRnd
            +
            +
            +
              $_TRACKNAME_SeqRndWeight
            +
            +
            +
              $_TRACKNAME_Strum
            +
            (only permitted in Chord tracks) +
            +
              $_TRACKNAME_Tone
            +
            (only permitted in Drum tracks) +
            +
              $_TRACKNAME_Unify
            +
            +
            +
              $_TRACKNAME_Voice
            +
            +
            +
              $_TRACKNAME_Voicing
            +
            (only permitted in Chord tracks) +
            +
              $_TRACKNAME_Volume
            +

            +

            +
            + +

            +The ``TrackName'' macros are useful in copying values between +non-similar tracks and CHSHARE tracks. For example: + +

            + + + +
            + Begin Bass +
              Voice AcousticBass +
              Octave 3 +
              ... +
            +End +
            +Begin Walk +
              ChShare Bass +
              Voice $_Bass_Voice +
              Octave $_Bass_Octave +
              ... +
            +End
            + +
            + +

            + +

            +Conditionals

            - -MMA is fairly conservative in its use of MIDI tracks. ``Out of the -box'' it demands a separate MIDI channel for each of its tracks, but -only as they are actually used. In most cases, this works just fine. +The most important reason to have variables in +MMA is to use them +available in conditionals. In +MMA a conditional consists of a line +starting with an IF directive, a test, a series of lines to +process (depending upon the result of the test), and a closing +ENDIF or IFEND18.2 directive. An optional ELSE statement may be included.

            -However, there are times when you might need more tracks than the -available MIDI channels or you may want to free up some channels for -other programs. +The first set of tests are unary (they take no arguments):

            -If you have different tracks with the same voicing, it's quite simple. -For example, you might have an arpeggio and scale track: +

            +
            Def VariableName
            +
            Returns true if the variable has been defined. + +

            +

            +
            Ndef VariableName
            +
            Returns true if the variable has not been + defined. + +

            +

            +
            + +

            +In the above tests you must supply the name of a variable--don't make +the mistake of including a ``$'' which will invoke expansion and +result in something you were not expecting. + +

            +A simple example:

            - - +
            + + +
            + If Def InCoda +
              5 Cm +
              6 / +
            +Endif
            -
            Arpeggio Sequence A16 z -
            -Arpeggio Voice Piano1 -
            -Scale Sequence z S8 -
            -Scale Voice Piano1
            +
            + +

            +The other tests are binary (they take two arguments): + +

            +

            +
            LT Str1 Str2
            +
            Returns true if Str1 is less than + Str2. (Please see the discussion below on how the tests are + done.) + +

            +

            +
            LE Str1 Str2
            +
            Returns true if str1 is less than or equal + to Str2. + +

            +

            +
            EQ Str1 Str2
            +
            Returns true if str1 is equal to + Str2. + +

            +

            +
            NE Str1 Str2
            +
            Returns true if str1 is not equal to + Str2. + +

            +

            +
            GT Str1 Str2
            +
            Returns true if str1 is greater than + Str2. + +

            +

            +
            GE Str1 Str2
            +
            Returns true if str1 is greater than or + equal to Str2. + +

            +

            +
            + +

            +In the above tests you have several choices in specifying Str1 +and Str2. At some point, when +MMA does the actual comparison, +two strings or numeric values are expected. So, you really could do: + +

            + + +
            + If EQ abc ABC -
            +

            -In this example, -MMA will use different MIDI channels for the -Arpeggio and the Scale. Now, if you force channel -sharing: +and get a ``true'' result. The reason that ``abc'' equals ``ABC'' is +that all the comparisons in +MMA are case-insensitive. + +

            +You can also compare a variable to a string:

            - - +
            + + +
            + If GT $foo abc -
            Scale ChShare Arpeggio
            +
            + +

            +will evaluate to ``true'' if the contents of the variable +``foo'' evaluates to something ``greater than'' ``abc''. But, there is +a bit of a ``gotcha' here. If you have set ``foo'' to a two word +string, then +MMA will choke on the command. In the following +example: + +

            + + +
            + Set Foo A B +
            +If GT $Foo abc
            -
            +

            -both tracks will use the same MIDI channel. - -

            -This is really foolproof in the above example, especially since the -same voice is being used for both. Now, what if you wanted to use a -different voice for the tracks? +the comparison is passed the line:

            - - +
            + + +
            + If GT A B abc -
            Arpeggio Sequence A16 z -
            -Arpeggio Voice Piano1 Strings -
            -Scale Sequence z S8 -
            -Scale ChShare Arpeggio
            +
            + +

            +and +MMA seeing three arguments generates an error. If you want the +comparison done on a variable which might be more than one word, use +the ``$$'' syntax. This delays the expansion of the variable until +the IF directive is entered. So: + +

            + + +
            + If $$foo abc -
            +

            -You might think that this would work, but it doesn't. -MMA ignores -voice changes for bars which don't have a sequence, so it will set -``Piano1'' for the first bar, then ``Strings'' for the second (so far, -so good). But, when it does the third bar (an ARPEGGIO) it will -not know that the voice has been changed to ``Strings'' by the -Scale track. +would generate a comparison between ``A B'' and ``ABC''.

            -So, the general rule for track channel sharing is to use only one voice. +Delayed expansion can be applied to either variable. It only works in +an IF directive.

            -One more example which doesn't work: +Strings and numeric values can be confusing in comparisons. For +example, if you have the strings ``22'' and ''3'' and compare them as +strings, ``3'' is greater than ``22''; however, if you compare them as +values then 3 is less than 22. + +

            +The rule in +MMA is quite simple: If either string in a comparison is +a numeric value, both strings are converted to values. Otherwise they +are compared as strings.18.3 +

            +This lets you do consistent comparisons in situations like:

            - - +
            + + +
            + Set Count 1 +
            +If LE $$Count 4 +
              .... +
            +IfEnd
            -
            Arpeggio Sequence A8 +
            + +

            +Note that the above example could have used ``$Count'', but you +should probably always use the ``$$'' in tests. + +

            +Much like other programming languages, an optional ELSE +condition may be used: + +

            + + +
            + If Def Coda +
              Groove Rhumba1
            -Scale Sequence S4 +Else +
              Groove Rhumba
            -Arpeggio Voice Piano1 -
            -Scale Voice Piano1 -
            -Scale ChShare Arpeggio
            +Endif -
            +

            -This example has an active scale and arpeggio sequence in each -bar. Since both use the same voice, you may think that it will work -just fine ...but it may not. The problem here is that -MMA will -generate MIDI on and off events which may overlap each other. One or -the other will be truncated. If you are using a different octave, it -will work much better. It may sound okay, but you should probably find -a better way to do this. +The ELSE statement(s) are processed only if the test for the +IF test is false.

            -When a CHSHARE directive is parsed the ``shared'' channel is -first checked to ensure that it has been assigned. If not currently -assigned, the assignment is first done. What this means is that you -are subverting -MMA 's normal dynamic channel allocation scheme. This -may cause is a depletion of available channels. +Nesting of IFs is permitted:

            -Please note that that the use of the CHSHARE command is -probably never really needed, so it might have more problems than outlined -here. + + + +
            + If ndef Foo +
              Print Foo has been defined. +
            +Else +
              If def bar +
                Print bar has been defined. Cool. +
              Else +
                Print no bar...go thirsty. +
              Endif +
            +Endif
            + +

            -This command will always display a warning message. - -

            -For another, simpler, way of reassigning MIDI tracks and letting -MMA do most of the work for you, refer to the -DELETE command. +works just fine. Indentation has been used in these examples to clearly +show the nesting and conditions. You should do the same.

            -ForceOut +Goto

            -Under normal conditions -MMA only generates the MIDI tracks it thinks are valid or relevant. So, if you create a track but insert no note data into that track it will not be generated. An easy way to verify this is by creating file and running -MMA with the -c command line option. Lets start off by creating a file you might think will set the keyboard channel on your synth to a TenorSax voice: - -

            - - -
            - -
            Begin Solo-Keyboard -
              Channel 1 -
              Voice TenorSax -
              MIDIVolume 100 -
            -End
            - -
            - -

            -If you compile this you should get: - -

            - - -
            - -
            $ mma test -c -
               -
            -File 'test' parsed, but no MIDI file produced! -
              -
            -Tracks allocated: -
             SOLO-KEYBOARD -
              -
            -Channel assignments: -
            -1 SOLO-KEYBOARD -
            - -
            - -

            -So, a -MMA track was created, but if you compile this file and examine the resulting MIDI file you will find that the voice has not been set. - -

            -To oversome this, insert the FORCEOUT command at the end of the track setup. For example, here is a more complete file which will set the keyboard track to TenorSax with a volume of 100, play a bar of accompaniment, set a Trumpet voice with a louder volume, play another bar, and finally reset the keyboard to the default Piano voice. - -

            - - -
            - -
            Groove BossaNova -
              -
            -Begin Solo -
              Channel 1 -
              Voice TenorSax -
              MIDIVolume 100 -
              ForceOut -
            -End -
              -
            -1 C -
              -
            -Begin Solo -
              Voice Trumpet -
              MIDIVolume 120 -
              ForceOut -
            -End -
              -
            -2 G -
              -
            -Begin Solo -
              Voice Piano1 -
              MIDIVolume 127 -
              ForceOut -
            -End -
            - -
            - -

            -Note: The same or similar results could be accomplished with the MIDI command; however, it's a bit harder to use and the commands would be in the Meta track. - -

            - -

            -MIDI -

            - -

            -The complete set of MIDI commands is not limitless--but from this end -it seems that adding commands to suit every possible configuration is -never-ending. So, in an attempt to satisfy everyone, a command which -will place any arbitrary MIDI stream in your tracks has been -implemented. In most cases this will be a MIDI ``Sysex'' or ``Meta'' -event. - -

            -For example, you might want to start a song off with a MIDI reset: - -

            - - -
            - -
            MIDI 0xF0 0x05 0x7e 0x7f 0x09 0x01 0xf7
            - -
            - -

            -The values passed to the MIDI command are normal integers; however, -they must all be in the range of 0x00 to 0xff. In most cases it is -easiest to use hexadecimal numbers by using the ``0x'' prefix. But, -you can use plain decimal integers if you prefer. - -

            -In the above example: - -

            -

            -
              0xF0
            -
            Designates a SYSEX message - -

            -

            -
              0x05
            -
            The length of the message - -

            -

            -
              0x7e
            -
            ...The actual message - -

            -

            -
            - -

            -Another example places the key signature of F major (1 flat) in the -meta track:18.1 -

            - - -
            - -
            MIDI 0xff 0x59 0x02 0xff 0x00
            - -
            - -

            -Some cautions: - -

              -
            • -MMA makes no attempt to verify the validity of the data! - -

              -

            • -
            • The ``Length'' field must be manually calculated. - -

              -

            • -
            • Malformed sequences can create unplayable MIDI files. In extreme - situations, these might even damage your synth. You are on your own - with this command ...be careful. - -

              -

            • -
            • The MIDI directive always places data in the Meta - track at the current time offset into the file. This should not be a - problem. - -

              -

            • -
            - -

            -Cautions aside, includes/init.mma has been included in this -distribution. I use this without apparent problems; to use it add the -command line: - -

            - - -
            - -
            MMAstart init
            - -
            - -

            -in your MMARC file. The file is pretty well commented and it -sets a synth up to something reasonably sane. - -

            -If you need a brief delay after a raw MIDI command, it is possible to -insert a silent beat with the BEATADJUST - command. See -the file includes/reset.mma for an example. - -

            - -

            -
            -MIDIClear -

            - -

            -As noted earlier in this manual you should be very careful in -programming MIDI sequences into your song and/or library files. Doing -damage to a synthesizer is probably a remote possibility ...but -leaving it in a unexpected mode is likely. For this reason the -MIDICLEAR command has been added as a companion to the -MIDIVOICE and MIDISEQ commands. - -

            -Each time a MIDI track (not necessary the same as a -MMA track) is -ended or a new GROOVE is started, a check is done to see if any -MIDI data has been inserted in the track with a MIDIVOICE or -MIDISEQ command. If it has, a further check is done to see if -there is an ``undo'' sequence defined via a MIDICLEAR command. -That data is then sent; or, if data has not be defined for the track, -a warning message is displayed. - -

            -The MIDICLEAR command uses the same syntax as MIDIVOICE -and MIDISEQ; however, you can not specify different sequence -for different bars in the sequence: - -

            - - -
            - -
            Bass-Funky MIDIClear 1 Modulation 0; 1 ReleaseTime 0
            - -
            - -

            -As in MIDIVOICE and MIDISEQ you can include sequences -defined in a MIDIDEF. The <beat>offsets -are required, but ignored. - -

            - -

            -
            -MIDIFile -

            - -

            -This option controls some fine points of the generated MIDI file. The -command is issued with a series of parameters in the form -``MODE=VALUE''. You can have multiple settings in a single -MIDIFILE command. - -

            - -MMA can generate two types of SMF (Standard MIDI Files): -

            -
            0.
            -
            This file contains only one track into which the data for - all the different channel tracks has been merged. A number of synths - which accept SMF (Casio, Yamaha and others) only accept type 0 - files. - -

            -

            -
            1.
            -
            This file has the data for each MIDI channel in its own - track. This is the default file generated by -MMA . - -

            -

            -
            - -

            -You can set the filetype in an RC file (or, for that matter, in any -file processed by -MMA ) with the command: - -

            - - -
            - -
            MidiFile SMF=0
            - -
            - -

            -or - -

            - - -
            - -
            MidiFile SMF=1
            - -
            - -

            -You can also set it on the command line with the -M option. Using the -command line option will override the MIDISMF command if it is -in a RC file. - -

            -By default -MMA uses ``running status'' when generating MIDI files. -This can be disabled with the command: - -

            - - -
            - -
            MidiFile Running=0
            - -
            - -

            -or enabled (but this is the default) with: - -

            - - -
            - -
            MidiFile Running=1
            - -
            - -

            -Files generated without running status will be about 20 to 30% larger -than their compressed counterparts. They may be useful for use with -brain-dead sequencers and in debugging generated code. There is no -command line equivalent for this option. - -

            - -

            -MIDIGlis -

            - -

            -This sets the MIDI portamento18.2 (in case you're new to all this, -portamento is like glissando between notes--wonderful, if you like -trombones! To enable portamento: - -

            - - -
            - -
            Arpeggio MIDIGlis 30
            - -
            - -

            -The parameter can be any value between 1 and 127. To turn the sliding -off: - -

            - - -
            - -
            Arpeggio MIDIGlis 0
            - -
            - -

            -This command will work with any track (including drum tracks). -However, the results may be somewhat ``interesting'' or -``disappointing'', and many MIDI devices don't support portamento at -all. So, be cautious. The data generated is not sent into the MIDI -stream until musical data is created for the relevant MIDI channel. - -

            - -

            -MIDIInc -

            - -

            - -MMA has the ability to include a user supplied MIDI file at any -point of its generated files. These included files can be used to play -a melodic solo over a -MMA pattern or to fill a section of a song -with something like a drum solo. - -

            -When the MIDIINC command is encountered the current line is -parsed for options, the file is inserted into the stored MIDI stream, -and processing continues. The include has no effect on any song -pointers, etc. - -

            -MIDIINC has a number of options, all set in the form -OPTION=VALUE. Following are the recognized options: - -

            -

            -
            FILENAME
            -
            The filename of the file to be included. This must be - a complete filename. The filename will be expanded by the Python - os.path.expanduser() function for tilde expansion. No prefixes or - extensions are added by -MMA . Examples: FILENAME=/home/bob/midi/myfile.mid. - or FILENAME= /sounds/myfile.mid. - -

            -

            -
            VOLUME
            -
            An adjustment for the volume of all the note on events - in the included MIDI file. The adjustment is specified as a - percentage with values under 100 decreasing the volume and over 100 - increasing it. If the resultant volume (velocity) is less than 1 a - velocity of 1 will be used; if it is over 127, 127 will be - used. Example: VOLUME=80. - -

            -

            -
            OCTAVE
            -
            Octave adjustment for all notes in the file. Values in - the range -4 to 4 are permitted. Notes in drum tracks (channel 10) - will not be effected. Example: OCTAVE=2. - -

            -

            -
            TRANSPOSE
            -
            Transposition adjustment settings in the range -24 to - 24 are permitted. If you do not set a value for this the global - transpose setting will be applied (expecting channel 10, drum, - notes). Example: TRANSPOSE=-2. - -

            -

            -
            LYRIC
            -
            This option will copy any Lyric events to the - -MMA meta track. The valid settings are ``On'' or ``Off''. By - default this is set to ``Off''. Example LYRIC=On. - -

            -

            -
            TEXT
            -
            This option will copy any Text events to the - -MMA meta track. The valid settings are ``On'' or ``Off''. By - default this is set to ``Off''. Example TEXT=On. - -

            -

            -
            START
            -
            Specifies the start point of the file to be included in - beats. For example, ``Start=22'' would start the include process 22 beats - into the file. The data will be inserted at the current song position in - your MMA file. The value used must greater or equal to 0 and may be - a fractional beat value (18.456 if fine). - -

            -

            -
            END
            -
            Specifies the end point of the file to be included in - beats. For example, ``End=100'' would disard all data after 100 beats - in the file. The value used must be greater that the Start position - and can be fractional. - -

            -

            -
            TRACK
            -
            A trackname must be be set into which notes are - inserted. You can set more than one track/channel if you wish. For - example, if you had the option DRUM=10 any notes in the MIDI - file with a channel 10 setting would be inserted into the -MMA Drum track. Similarity, Solo-Tenor=1 will copy notes - from channel 1 into the Solo-Tenor track. If the track - doesn't exist, it will be created. Note: this means that the channel - assignment in your included file and the new -MMA generated file - will most likely be different. Example: SOLO=1 - -

            -

            -
            - -

            -A complete example of usage is shown in the files in the directory -egs/frankie in the distribution. A short example: - -

            - - -
            - -
            MIDIinc File=test.mid Solo-Piano=1 Drum=10 Volume=70
            - -
            - -

            -will include the MIDI file ``test.mid'' at the current position and -assign all notes in channel 1 to the Solo-Piano track and the -notes from channel 10 to the Drum track. The volumes for all -the notes will be adjusted to 70% of that in the original. - -

            -A few notes: - -

            - -

              -
            • MIDI files to be included do not have to have the same tempo. - MIDI adjusts this automatically on playback. However, the internal - setting for beat division should be the same. -MMA assumes a beat - division of 192 (this is set in bytes 12 and 13 of the MIDI file). - If the included file differs a warning is printed and -MMA will - attempt to adjust the timings. - -

              -

            • -
            • All files are parsed to find the offset of the first note-on - event; notes to be included are set with their offsets compensated - by that time. This means that any silence at the start of the - included file is skipped (this may surprise you if you have used the - optional Start setting). If you want the included file to start - somewhere besides the start of the current bar you can use a - BEATADJUST before the MIDIINC--use another to move - the pointer back right after the include to keep the song pointer - correct. - -

              -

            • -
            • Not all events in the included files are transferred: notably - all system and meta events (other than text and lyric, see above) are ignored. - -

              -

            • -
            • If you want to apply different VOLUME or other options to - different tracks, just do multiple includes of the same file (with - each include using a different track and options). - -

              -

            • -
            - -

            - -

            -MIDIMark -

            - -

            -You can insert a MIDI Marker event into the Meta track with this command. The mark can be useful -in debugging your MIDI output with a sequencer or editor which supports Mark events (most do). - -

            - - -
            - -
            MidiMark Label
            - -
            - -

            -will insert the text ``Label'' at the current position. You can add an optional negative -or positive offset in beats: - -

            - - -
            - -
            MidiMark 2 Label4
            - -
            - -

            -will insert ``Label4'' 2 beats into the next bar. - -

            - -

            -MIDIPan -

            - -

            -In MIDI-speak ``pan'' is the same as ``balance'' on a stereo. By -adjusting the MIDIPAN for a track you can direct the output to the -left, right or both speakers. Example: - -

            - - -
            - -
            Bass MIDIPan 4
            - -
            - -

            -This command is only available in track mode. The data generated is -not sent into the MIDI stream until musical data is created for the -relevant MIDI channel. - -

            -The value specified must be in the range 0 to 127, and must be an integer. - -

            -MIDIPAN is not saved or restored by GROOVE commands, nor is -it effected by SEQCLEAR. A MIDIPAN is inserted directly into -the MIDI track at the point at which it is encountered in the music -file. This means that the effect of MIDIPAN will be in use until -another MIDIPAN is encountered. - -

            -MIDIPAN can be used in MIDI compositions to emulate the sound of an -orchestra. By assigning different values to different groups of -instruments, you can get the feeling of strings, horns, etc. all -placed in the ``correct'' position on the stage. - -

            -MIDIPAN can be used for much cruder purposes. When creating accompaniment -tracks for a mythical jazz group, you might set all the bass tracks (Bass, Walk, -Bass-1, etc) set to aMIDIPAN 0. Now, when practicing at home you have a -``full band''; and the bass player can practice without the generated -bass lines simply by turning off the left speaker. - -

            -Because most MIDI keyboard do not reset between -tunes, there should be a MIDIPAN to undo the effects at the end of -the file. Example:18.3 -

            - - -
            - -
            Include swing -
            -Groove Swing -
            -Bass MIDIPan 0 -
            -Walk MIDIPan 0 -
            -1 C -
            -2 C -
            ... -
            -123 C -
            -Bass MIDIPan 64 -
            -Walk MIDIPan 64
            - -
            - -

            - -

            -MIDISeq -

            - -

            -It is possible to associate a set of MIDI controller messages with -certain beats in a sequence. For example, you might want to have the -Modulation Wheel set for the first beats in a bar, but not for the -third. The following example shows how: - -

            - - -
            - -
            Seqsize 4 -
            -Begin Bass-2 -
            -Voice NylonGuitar -
            -Octave 4 -
            -Sequence { 1 4 1 90; 2 4 3 90; 3 4 5 90; 4 4 1+ 90} -
            -MIDIDef WheelStuff 1 1 0x7f ; 2 1 0x50; 3 1 0 -
            -MidiSeq WheelStuff -
            -Articulate 90 -
            -End -
            -
            -C $*$ 4
            - -
            - -

            -The MIDISEQ command is specific to a track and is saved as part -of the GROOVE definition. This lets style file writers use -enhanced MIDI features to dress up their sounds. - -

            -The command has the following syntax: - -

            - - -
            - -
            TrackName MidiSeq <Beat> <Controller> <Datum> [ ; ...]
            - -
            - -

            -where: -

            -
            Beat
            -
            is the Beat in the bar. This can be an integer (1,2, etc.) - or a floating point value (1.2, 2.25, etc.). It must be 1 or greater - and less than the end of bar (in 4/4 it must be less than - 5). - -

            -

            -
            Controller
            -
            A valid MIDI controller. This can be a value in the - range 0x00 to 0x7f or a symbolic name. See the appendix - , here, for a list of - defined names. - -

            -

            -
            Datum
            -
            All controller messages use a single byte ``parameter'' - in the range 0x00 to 0x7f. - -

            -

            -
            - -

            -You can enter the values in either standard decimal notation or in -hexadecimal with the prefixed ``0x''. In most cases, your code will be -clearer if you use values like ``0x7f'' rather than the equivalent -``127''. - -

            -The MIDI sequences specified can take several forms: +The GOTO command redirects the execution order of your script to +the point at which a LABEL or line number has been defined. There are really +two parts to this:

              -
            1. A simple series like: +
            2. A command defining a label, and,

              - - -
              - -
              MIDISeq 1 ReleaseTime 50; 3 ReleaseTime 0
              - -
              - -

              -in this case the commands are applied to beats 1 and 3 in each bar - of the sequence. +

            3. +
            4. The GOTO command.

            -

            . - -

            - -

            -As a set of names predefined in an MIDIDEF command:

            - - +
            +

            +A label is set with the LABEL directive: + +

            + + +
            + Label Point1 -
            MIDIdef Rel1 1 ReleaseTime 50; 3 ReleaseTime 0 -
            -MIDIdef Rel2 2 ReleaseTime 50; 4 ReleaseTime 0 -
            -MIDISeq Rel1 Rel2
            - -
            +

            -Here, the commands defined in ``Rel1'' are applied to the first bar - in the sequence, ``Rel2'' to the second. And, if there are more bars - in the sequence than definitions in the line, the series will be - repeated for each bar. +The string defining the label can be any sequence of characters. +Labels are case-insensitive.

            -A set of series enclosed in { } braces. Each braced series is - applied to a different bar in the sequence. The example above could - have been does as: +To make this look a lot more line those old BASIC progams, any lines +starting with a line number are considered to be label lines as +well.

            - - -
            - -
            MIDISeq { 1 ReleaseTime 50; 3 ReleaseTime 0 } \ -
            { 2 ReleaseTime 50; 4 ReleaseTime 0 }
            - -
            - -

            -Finally, you can combine the above into different combinations. - For example: - -

            - - -
            - -
            MIDIDef Rel1 1 ReleaseTime 50 -
            -MIDIDef Rel2 2 ReleaseTime 50 -
            -MIDISeq { Rel1; 3 ReleaseTime 0 } { Rel2; 4 ReleaseTime 0 }
            - -
            - -

            - -

            -You can have specify different messages for different beats (or -different messages/controllers for the same beat) by listing them on -the same MIDISEQ line separated by ``;''s. - -

            -If you need to repeat a sequence for a measure in a sequence you can -use the special notation ``/'' to force the use of the previous line. -The special symbol ``z'' or ''-'' can be used to disable a bar (or -number of bars). For example: - -

            - - -
            - -
            Bass-Dumb MIDISeq 1 ReleaseTime 20 z / FOOBAR
            - -
            - -

            -would set the ``ReleaseTime'' sequence for the first bar of the -sequence, no MIDISeq events for the second and third, and the contents -of ``FOOBAR'' for the fourth. - -

            -To disable the sending of messages just use a single ``-'': - -

            - - -
            - -
            Bass-2 MidiSeq - // disable controllers
            - -
            - -

            - -

            -MIDISplit -

            - -

            -For certain post-processing effects it is convenient to have each different drum tone -in a separate MIDI track. This makes it easier to apply an effect to, for example, the -snare drum. Just to make this a bit more fun you can split any track -created by -MMA . - -

            -To use this feature: - -

            - - -
            - -
            MIDISplit <list of channels>
            - -
            - -

            -So, to split out just the drum channel18.4 you would have the command: - -

            - - -
            - -
            MIDISplit 10
            - -
            - -

            -somewhere in your song file. - -

            -When processing -MMA creates an internal list of MIDI note-on events for each tone or pitch -in the track. It then creates a separate MIDI track for each list. Any other events are -written to another track. - -

            - -

            -MIDITname -

            - -

            -When creating a MIDI track, -MMA inserts a MIDI Track Name event at the start of the track. -By default, this name is the same as the associated -MMA track name. You can change -this by issuing the MIDITNAME command. For example, to change the CHORD -track name you might do something like: - -

            - - -
            - -
            Chord MidiTname Piano
            - -
            - -

            -Please note that this only effects the tracks in the generated MIDI file. -You still refer to the track in your file as CHORD. - -

            - -

            -MIDIVoice -

            - -

            -Similar to the MIDISEQ command discussed in the previous -section, the MIDIVOICE command is used to insert MIDI -controller messages into your files. Instead of sending the data for -each bar as MIDISEQ does, this command just sends the listed -control events at the start of a track and then, if needed, at the -start of each bar. - -

            -Again, a short example. Let us assume that you want to use the -``Release Time'' controller to sustain notes in a bass line: - -

            - - -
            - -
            Seqsize 4 -
            -Begin Bass-2 -
            -Voice NylonGuitar -
            -MidiVoice 1 ReleaseTime 50 -
            -Octave 4 -
            -Sequence { 1 4 1 90; 2 4 3 90; 3 4 5 90; 4 4 1+ 90} -
            -Articulate 60 -
            -End -
            -
            -C $*$ 4
            - -
            - -

            -should give an interesting effect. - -

            -The syntax for the command is: - -

            - - -
            - -
            Track MIDIVoice <beat> <controller> <Datum> [; ...]
            - -
            - -

            -This syntax is identical to that discussed in the section for -MIDISEQ, above. The <beat>value is -required for the command--it determines if the data is sent before or -after the VOICE command is sent. Some controllers are reset by -a voice, others not. My experiments show that BANK should be -sent before, most others after. Using a ``beat'' of ``0'' forces the -MidiVoice data to be sent before the Voice control; any other ``beat'' -value causes the data to be sent after the Voice control. In this -silly example: - -

            - - -
            - -
            Voice Piano1 -
            -MidiVoice {0 Bank 5; 1 ReleaseTime 100}
            - -
            - -

            -the MIDI data is created in an order like: - -

            -

            -

            0 Param Ch=xx Con=00 val=05 -
            -0 ProgCh Ch=xx Prog=00 -
            -0 Param Ch=xx Con=72 val=80 - -
            - -

            -All the MIDI events occur at the same offset, but the order is (may -be) important. - -

            -By default -MMA assumes that the MIDIVoice data is to be used only -for the first bar in the sequence. But, it's possible to have a -different sequence for each bar in the sequence (just like you can -have a different VOICE for each bar). In this case, group the -different data groups with {} brackets: - -

            - - -
            - -
            Bass-1 MIDIVoice {1 ReleaseTime 50} {1 ReleaseTime 20}
            - -
            - -

            -This list is stored with other GROOVE data, so is ideal for -inclusion in a style file. - -

            -If you want to disable this command after it has been issued you can -use the form: - -

            - - -
            - -
            Track MIDIVoice - // disable
            - -
            - -

            -Some technical notes: +A few considerations on labels and linenumbers:

              -
            • -MMA tracks the events sent for each bar and will not duplicate - sequences. +
            • A duplicate label generated with a LABEL command will + generate an error.

            • -
            • Be cautious in using this command to switch voice banks. If you - don't switch the voice bank back to a sane value you'll be playing - the wrong instruments! +
            • A line number label duplicating a LABEL is an error.

            • -
            • Do use the MIDICLEAR command ((details)) to ``undo'' anything - you've done via a MIDIVOICE command. +
            • A LABEL duplicating a line number is an error. + +

              +

            • +
            • Duplicate line numbers are permitted. The last one encountered + will be the one used. + +

              +

            • +
            • All label points are generated when the file is opened, not as it is + parsed. + +

              +

            • +
            • Line numbers (really, just comments) do not need to be in any + order.

            • @@ -1501,86 +1349,87 @@ Some technical notes:

              -

              +

              +The command: + +

              + + + +
              + Goto Point1 + +
              + +

              +causes an immediate jump to a new point in the file. If you are +currently in repeat or conditional segment of the file, the remaining +lines in that segment will be ignored. + +

              + +MMA does not check to see if you are jumping into a repeat or +conditional section of code--but doing so will usually cause an +error. Jumping out of these sections is usually safe. + +

              +The following example shows the use of both types of label. In this +example only lines 2, 3, 5 and 6 will be processed. + +

              + + + +
              + Goto Foo
              -MIDIVolume - - -

              -MIDI devices equipped with mixer settings can make use of the -``Channel'' or ``Master'' volume settings.18.5 -

              - -MMA doesn't set any channel volumes without your knowledge. If you -want to use a set of reasonable defaults, look at the file -includes/init.mma which sets all channels other than ``1'' to -``100''. Channel ``1'' is assumed to be a solo/keyboard track and is -set to the maximum volume of ``127''. - -

              -You can set selected MIDIVOLUMEs: - -

              - - -
              +1 Cm +
              +Label Foo +
              +2 Dm +
              +3 / +
              +Goto 5 +
              +4 Am +
              +5 Cm +
              +6 Dm -
              Chord MIDIVolume 55
              - -
              - -

              -will set the Chord track channel. For most users, the use of this -command is not recommended since it will upset the balance of -the library grooves. If you need a track softer or louder you should -use the volume setting for the track. - -

              -The data generated is not sent into the MIDI stream until musical data -is created for the relevant MIDI channel. - -

              -Caution: If you use the command with ALLTRACKS you should note -that only existing -MMA tracks will be effected. +

              +For an example of how to use some simple labels to simulate a ``DS al +Coda'' examine the file ``lullaby-of-Broadway'' in the sample songs +directory.


              Footnotes

              -
              ... track:18.1
              -
              This is much easier to do - with the KeySig command, here +
              ... macros.18.1
              +
              The values + are dynamically created and reflect the current settings, and may + not be exactly the same as the value you originally set due to + internal roundings, etc.
              -
              ... portamento18.2
              -
              The name ``Glis'' is used because -``MIDIPortamento'' gets to be a bit long to type and ``MIDIPort'' might -be interpreted as something to do with ``ports''. +
              ...IFEND18.2
              +
              +MMA 's author probably suffers + from mild dyslexia and can't remember if the command is IFEND or + ENDIF, so both are permitted. Use whichever is more comfortable for + you.
              -
              ... Example:18.3
              -
              This is much easier to do with the - MMAStart and MMAEnd options (details). - -
              -
              ... channel18.4
              -
              In -MMA this will always be -channel 10. - -
              -
              ... settings.18.5
              -
              I discovered this - on my keyboard after many frustrating hours attempting to balance - the volumes in the library. Other programs would change the keyboard - settings, and not being aware of the changes, I'd end up scratching - my head. +
              ... strings.18.3
              +
              An attempt is made to convert each + string to a float. If conversion of both strings is successful, the + comparison is made between two floats, otherwise two strings are + used.

              @@ -1596,15 +1445,15 @@ channel 10. previous
              Next: Fine Tuning (Translations) + HREF="node19.html">Low Level MIDI Commands Up: Reference Manual Previous: Variables, Conditionals and Jumps + HREF="node17.html">Repeats
              -Bob -2006-10-15 +bob +2007-03-07
              diff --git a/mma/docs/html/ref/node19.html b/mma/docs/html/ref/node19.html index e80af14..5f92dfa 100644 --- a/mma/docs/html/ref/node19.html +++ b/mma/docs/html/ref/node19.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Fine Tuning (Translations) - +Low Level MIDI Commands + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
              - Next: Other Commands and Directives - Up: Next: Fine Tuning (Translations) + Up: Reference Manual - Previous: Low Level MIDI Commands + Previous: Variables, Conditionals and Jumps

              @@ -49,491 +49,1562 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

              - +
              -Fine Tuning (Translations) +Low Level MIDI Commands

              -A program such as -MMA which is intended to be run of various -computers and synthesizers (both hardware keyboards and software -versions) suffers from a minor deficency of the MIDI standards: mainly -that the standard says nothing about what a certain instrument should -sound like, or the relative volumes between instruments. The GM -extension helps a bit, but only a bit, by saying that certain -instruments should be assigned certain program change values. This -means that all GM synths will play a "Piano" if instrument 000 is -selected. +The commands discussed in this chapter directly effect your MIDI +output devices.

              -But, if one plays a GM file on a Casio keyboard, then on PC -soft-synth, and then on a Yahama keyboard you will get three quite -different sounds. The files supplied in this distribution have been -created to sound good on the author's setup: A Casio WK-3000 keyboard. - -

              -But, what if your hardware is different? Well, there are solutions! -Later in this chapter commands are shown which will change the -preselected voice and tone commands and the default volumes. At this -time there are no example files supplied with -MMA , but your -contributions are welcome. - -

              -The general suggestion is that: +Not all MIDI devices are equal. Many of the effects in this chapter +may be ignored by your devices. Sorry, but that's just the way MIDI +is.

              -

                -
              1. You create a file with the various translations you need. For - example, the file might be called yamaha.mma and contain - lines like: - -

                - - -
                - -
                VoiceTR Piano1=Piano2 +


                -ToneTr SnareDrum2=SnareDrum1 -
                -VoiceVolTr Piano2=120 BottleBlow=80 -
                -DrumVolTr RideBell=90 Tambourine=120

                - -
                - -

                -Place this file in the directory /usr/local/share/mma/includes. - -

                -

              2. -
              3. Include this file in your ~/.mmarc file. Following the - above example, you would have a line: - -

                - - -
                - -
                Include yamaha
                - -
                - -

                -

              4. -
              - -

              -That's it! Now, whenever you compile a -MMA file the translations -will be done. - -

              -All of the following translation settings follow a similar logic as to ``when'' -they take effect, and that is at the time the VOICE, -VOLUME, etc. command is issued. This may confuse the unwary if -GROOVES are being used. But, the following sequence: - -

              - - -
              - -
                -
              1. You set a voice with the VOICE command, -
              2. -
              3. You save that voice into a GROOVE with DEFGROOVE, -
              4. -
              5. You create a voice translation with VOICETR, -
              6. -
              7. You activate the previously defined GROOVE. -
              8. -
              - - - -
              Wrong!
              - -

              -does not have the desired effect. In the above sequence the -VOICETR will have no effect. For the desired -translations to work the VOICE (or whatever) command must come -after the translation command. - -

              - -

              -
              -VoiceTr +Channel

              -In previous section you saw how to set a voice for a track by using its -standard MIDI name. The VOICETR command sets up a translation -table that can be used in two different situations: +As noted in Tracks and Channels +MMA assigns MIDI channels +dynamically as it creates tracks. In most cases this works fine; +however, you can if you wish force the assignment of a specific MIDI +channel to a track with the CHANNEL command.

              +You cannot assign a channel number to a track if it already defined +(well, see the section CHSHARE, below, for the inevitable +exception), nor can you change the channel assignments for any of the +DRUM tracks. + +

              +Let us assume that you want the Bass track assigned to MIDI +channel 8. Simply use: + +

              + + + +
              + Bass Channel 8 + +
              + +

              +Caution: If the selected channel is already in use an error will be +generated. Due to the way +MMA allocates tracks, if you really need +to manually assign track it is recommended that you do this in a +MMARC file. + +

              + +

              +You can disable a channel at any time by using a channel number of 0: + +

              + + + +
              + Arpeggio-1 Channel 0 + +
              + +

              +will disable the Arpeggio-1 channel, freeing it for use by other +tracks. A warning message is generated. Disabling a track without a +valid channel is fine. When you set a channel to 0 the track is also +disabled. You can restart the track with the ON command +(here). + +

              +You don't need to have a valid MIDI channel assigned to a track to do +things like: MIDIPAN, MIDIGLIS, MIDIVOLUME or +even the assignment of any music to a track. MIDI data is created in +tracks and then sent out to the MIDI buffers. Channel assignment is +checked and allocated at this point, and an error will be generated if +no channels are available. + +

              +It's quite acceptable to do channel reassignments in the middle of a +song. Just assign channel 0 to the unneeded track first. + +

              +MIDI channel settings are not saved in GROOVEs. + +

              + +MMA inserts a MIDI ``track name'' meta event when the channel +buffers are first assigned at a MIDI offset of 0. If the MIDI channel +is reassigned, a new ``track name'' is inserted at the current song +offset. + +

              +A more general method is to use CHANNELPREF detailed below. + +

              +You can access the currently assigned channel with the $_TRACK_CHANNEL macro. + +

              + +

              +ChannelPref +

              + +

              +If you prefer to have certain tracks assigned to certain channels you +can use the CHANNELPREF command to create a custom set of +preferences. By default, +MMA assigns channels starting at 16 and +working down to 1 (with the expectation of drum tracks which are all +assigned channel 10). If, for example, you would like the Bass +track to be on channel 9, sustained bass on channel 3, and +Arpeggio on channel 5, you can have a command like: + +

              + + + +
              + ChannelPref Bass=9 Arpeggio=5 Bass-Sus=3 + +
              + +

              +Most likely this will be in your MMARC file. + +

              +You can use multiple command lines, or have multiple assignments on a +single line. Just make sure that each item consists of a trackname, an +``='' and a channel number in the range 1 to 16. + +

              + +

              +
              +ChShare +

              + +

              + +MMA is fairly conservative in its use of MIDI tracks. ``Out of the +box'' it demands a separate MIDI channel for each of its tracks, but +only as they are actually used. In most cases, this works just fine. + +

              +However, there are times when you might need more tracks than the +available MIDI channels or you may want to free up some channels for +other programs. + +

              +If you have different tracks with the same voicing, it's quite simple. +For example, you might have an arpeggio and scale track: + +

              + + + +
              + Arpeggio Sequence A16 z +
              +Arpeggio Voice Piano1 +
              +Scale Sequence z S8 +
              +Scale Voice Piano1
              + +
              + +

              +In this example, +MMA will use different MIDI channels for the +Arpeggio and the Scale. Now, if you force channel +sharing: + +

              + + + +
              + Scale ChShare Arpeggio + +
              + +

              +both tracks will use the same MIDI channel. + +

              +This is really foolproof in the above example, especially since the +same voice is being used for both. Now, what if you wanted to use a +different voice for the tracks? + +

              + + + +
              + Arpeggio Sequence A16 z +
              +Arpeggio Voice Piano1 Strings +
              +Scale Sequence z S8 +
              +Scale ChShare Arpeggio
              + +
              + +

              +You might think that this would work, but it doesn't. +MMA ignores +voice changes for bars which don't have a sequence, so it will set +``Piano1'' for the first bar, then ``Strings'' for the second (so far, +so good). But, when it does the third bar (an ARPEGGIO) it will +not know that the voice has been changed to ``Strings'' by the +Scale track. + +

              +So, the general rule for track channel sharing is to use only one voice. + +

              +One more example which doesn't work: + +

              + + + +
              + Arpeggio Sequence A8 +
              +Scale Sequence S4 +
              +Arpeggio Voice Piano1 +
              +Scale Voice Piano1 +
              +Scale ChShare Arpeggio
              + +
              + +

              +This example has an active scale and arpeggio sequence in each +bar. Since both use the same voice, you may think that it will work +just fine ...but it may not. The problem here is that +MMA will +generate MIDI on and off events which may overlap each other. One or +the other will be truncated. If you are using a different octave, it +will work much better. It may sound okay, but you should probably find +a better way to do this. + +

              +When a CHSHARE directive is parsed the ``shared'' channel is +first checked to ensure that it has been assigned. If not currently +assigned, the assignment is first done. What this means is that you +are subverting +MMA 's normal dynamic channel allocation scheme. This +may cause is a depletion of available channels. + +

              +Please note that that the use of the CHSHARE command is +probably never really needed, so it might have more problems than outlined +here. If you want to see how much a bother channel sharing becomes, +have a look at the standard library file frenchwaltz.mma. All +this so the accordion bass can use one channel instead of 6. If I were +to write it again I'd just let it suck up the MIDI channels. + +

              +For another, simpler, way of reassigning MIDI tracks and letting +MMA do most of the work for you, refer to the +DELETE command. + +

              + +

              +ForceOut +

              + +

              +Under normal conditions +MMA only generates the MIDI tracks it thinks are valid or relevant. So, if you create a track but insert no note data into that track it will not be generated. An easy way to verify this is by creating file and running +MMA with the -c command line option. Lets start off by creating a file you might think will set the keyboard channel on your synth to a TenorSax voice: + +

              + + + +
              + Begin Solo-Keyboard +
                Channel 1 +
                Voice TenorSax +
                MIDIVolume 100 +
              +End
              + +
              + +

              +If you compile this you should get: + +

              + + + +
              + $ mma test -c +
                 +
              +File 'test' parsed, but no MIDI file produced! +
                +
              +Tracks allocated: +
               SOLO-KEYBOARD +
                +
              +Channel assignments: +
              +1 SOLO-KEYBOARD +
              + +
              + +

              +So, a +MMA track was created, but if you compile this file and examine the resulting MIDI file you will find that the voice has not been set. + +

              +To oversome this, insert the FORCEOUT command at the end of the track setup. For example, here is a more complete file which will set the keyboard track to TenorSax with a volume of 100, play a bar of accompaniment, set a Trumpet voice with a louder volume, play another bar, and finally reset the keyboard to the default Piano voice. + +

              + + + +
              + Groove BossaNova +
                +
              +Begin Solo +
                Channel 1 +
                Voice TenorSax +
                MIDIVolume 100 +
                ForceOut +
              +End +
                +
              +1 C +
                +
              +Begin Solo +
                Voice Trumpet +
                MIDIVolume 120 +
                ForceOut +
              +End +
                +
              +2 G +
                +
              +Begin Solo +
                Voice Piano1 +
                MIDIVolume 127 +
                ForceOut +
              +End +
              + +
              + +

              +Note: The same or similar results could be accomplished with the MIDI command; however, it's a bit harder to use and the commands would be in the Meta track. + +

              + +

              +MIDI +

              + +

              +The complete set of MIDI commands is not limitless--but from this end +it seems that adding commands to suit every possible configuration is +never-ending. So, in an attempt to satisfy everyone, a command which +will place any arbitrary MIDI stream in your tracks has been +implemented. In most cases this will be a MIDI ``Sysex'' or ``Meta'' +event. + +

              +For example, you might want to start a song off with a MIDI reset: + +

              + + + +
              + MIDI 0xF0 0x05 0x7e 0x7f 0x09 0x01 0xf7 + +
              + +

              +The values passed to the MIDI command are normal integers; however, +they must all be in the range of 0x00 to 0xff. In most cases it is +easiest to use hexadecimal numbers by using the ``0x'' prefix. But, +you can use plain decimal integers if you prefer. + +

              +In the above example: + +

              +

              +
                0xF0
              +
              Designates a SYSEX message + +

              +

              +
                0x05
              +
              The length of the message + +

              +

              +
                0x7e
              +
              ...The actual message + +

              +

              +
              + +

              +Another example places the key signature of F major (1 flat) in the +meta track:19.1 +

              + + + +
              + MIDI 0xff 0x59 0x02 0xff 0x00 + +
              + +

              +Some cautions:

                -
              • It permits creation of your own names for voices (perhaps for a - foreign language), +
              • +MMA makes no attempt to verify the validity of the data!

              • -
              • It lets you override or change voices used in standard library +
              • The ``Length'' field must be manually calculated. + +

                +

              • +
              • Malformed sequences can create unplayable MIDI files. In extreme + situations, these might even damage your synth. You are on your own + with this command ...be careful. + +

                +

              • +
              • The MIDI directive always places data in the Meta + track at the current time offset into the file. This should not be a + problem. + +

                +

              • +
              + +

              +Cautions aside, includes/init.mma has been included in this +distribution. I use this without apparent problems; to use it add the +command line: + +

              + + + +
              + MMAstart init + +
              + +

              +in your MMARC file. The file is pretty well commented and it +sets a synth up to something reasonably sane. + +

              +If you need a brief delay after a raw MIDI command, it is possible to +insert a silent beat with the BEATADJUST + command. See +the file includes/reset.mma for an example. + +

              + +

              +
              +MIDIClear +

              + +

              +As noted earlier in this manual you should be very careful in +programming MIDI sequences into your song and/or library files. Doing +damage to a synthesizer is probably a remote possibility ...but +leaving it in a unexpected mode is likely. For this reason the +MIDICLEAR command has been added as a companion to the +MIDIVOICE and MIDISEQ commands. + +

              +Each time a MIDI track (not necessary the same as a +MMA track) is +ended or a new GROOVE is started, a check is done to see if any +MIDI data has been inserted in the track with a MIDIVOICE or +MIDISEQ command. If it has, a further check is done to see if +there is an ``undo'' sequence defined via a MIDICLEAR command. +That data is then sent; or, if data has not be defined for the track, +a warning message is displayed. + +

              +The MIDICLEAR command uses the same syntax as MIDIVOICE +and MIDISEQ; however, you can not specify different sequence +for different bars in the sequence: + +

              + + + +
              + Bass-Funky MIDIClear 1 Modulation 0; 1 ReleaseTime 0 + +
              + +

              +As in MIDIVOICE and MIDISEQ you can include sequences +defined in a MIDIDEF. The <beat>offsets +are required, but ignored. + +

              + +

              +
              +MIDIFile +

              + +

              +This option controls some fine points of the generated MIDI file. The +command is issued with a series of parameters in the form +``MODE=VALUE''. You can have multiple settings in a single +MIDIFILE command. + +

              + +MMA can generate two types of SMF (Standard MIDI Files): +

              +
              0.
              +
              This file contains only one track into which the data for + all the different channel tracks has been merged. A number of synths + which accept SMF (Casio, Yamaha and others) only accept type 0 files.

              - -

            + +
            1.
            +
            This file has the data for each MIDI channel in its own + track. This is the default file generated by +MMA .

            -VOICETR works by setting up a simple translation table of -``name'' and ``alias'' pairs. Whenever -MMA encounters a voice name -in a track command it first attempts to translate this name though the -alias table. +

            +

            -To set a translation (or series of translations): +You can set the filetype in an RC file (or, for that matter, in any +file processed by +MMA ) with the command:

            - - +
            + + +
            + MidiFile SMF=0 -
            VoiceTr Piano1=Clavinet Hmmm=18
            +
            + +

            +or + +

            + + +
            + MidiFile SMF=1 -
            +

            -Note that you additional VOICETR commands will add entries to -the existing table. To clear the table use the command with no -arguments: +You can also set it on the command line with the -M option. Using the +command line option will override the MIDISMF command if it is +in a RC file. + +

            +By default +MMA uses ``running status'' when generating MIDI files. +This can be disabled with the command:

            - - +
            + + +
            + MidiFile Running=0 -
            VoiceTr // Empty table
            +
            + +

            +or enabled (but this is the default) with: + +

            + + +
            + MidiFile Running=1 -
            +

            -Assuming the first command, the following will occur: +Files generated without running status will be about 20 to 30% larger +than their compressed counterparts. They may be useful for use with +brain-dead sequencers and in debugging generated code. There is no +command line equivalent for this option.

            - -
            - -
            Chord-Main Voice Hmmm
            - -
            - -

            -The VOICE for the Chord-Main track will be set to ``18'' -or ``Organ3''. - -

            - - -
            - -
            Chord-2 Voice Piano1
            - -
            - -

            -The VOICE for the Chord-2 track will be set to -``Clavinet''. - -

            -If your synth does not follow standard GM-MIDI voice naming -conventions you can create a translation table which can be included -in all your -MMA song files via an RC file. But, do note that the -resulting files will not play properly on a synth conforming to the -GM-MIDI specification. - -

            -Following is an abbreviated and untested example for using an obsolete and unnamed synth: - -

            - - -
            - -
            VoiceTr Piano1=3 \ -
            -Piano2=4 \ -
            -Piano3=5 \ -
            ... \ -
            -Strings=55 \ -
            ...
            - -
            - -

            -Notes: the translation is only done one time and no verification is -done when the table is created. - -

            -For translating drum tone values, see -DRUMTR. - -

            - -

            -
            -DrumTr +

            +MIDIGlis

            -It is possible to create a translation table which will substitute one -Drum Tone for another. This can be useful in a variety of -situations, but consider: +This sets the MIDI portamento19.2 (in case you're new to all this, +portamento is like glissando between notes--wonderful, if you like +trombones! To enable portamento: + +

            + + + +
            + Arpeggio MIDIGlis 30 + +
            + +

            +The parameter can be any value between 1 and 127. To turn the sliding +off: + +

            + + + +
            + Arpeggio MIDIGlis 0 + +
            + +

            +This command will work with any track (including drum tracks). +However, the results may be somewhat ``interesting'' or +``disappointing'', and many MIDI devices don't support portamento at +all. So, be cautious. The data generated is not sent into the MIDI +stream until musical data is created for the relevant MIDI channel. + +

            + +

            +MIDIInc +

            + +

            + +MMA has the ability to include a user supplied MIDI file at any +point of its generated files. These included files can be used to play +a melodic solo over a +MMA pattern or to fill a section of a song +with something like a drum solo. + +

            +When the MIDIINC command is encountered the current line is +parsed for options, the file is inserted into the stored MIDI stream, +and processing continues. The include has no effect on any song +pointers, etc. + +

            +MIDIINC has a number of options, all set in the form +OPTION=VALUE. Following are the recognized options: + +

            +

            +
            FILENAME
            +
            The filename of the file to be included. This must be + a complete filename. The filename will be expanded by the Python + os.path.expanduser() function for tilde expansion. No prefixes or + extensions are added by +MMA . Examples: FILENAME=/home/bob/midi/myfile.mid. + or FILENAME= /sounds/myfile.mid. + +

            +

            +
            VOLUME
            +
            An adjustment for the volume of all the note on events + in the included MIDI file. The adjustment is specified as a + percentage with values under 100 decreasing the volume and over 100 + increasing it. If the resultant volume (velocity) is less than 1 a + velocity of 1 will be used; if it is over 127, 127 will be + used. Example: VOLUME=80. + +

            +

            +
            OCTAVE
            +
            Octave adjustment for all notes in the file. Values in + the range -4 to 4 are permitted. Notes in drum tracks (channel 10) + will not be effected. Example: OCTAVE=2. + +

            +

            +
            TRANSPOSE
            +
            Transposition adjustment settings in the range -24 to + 24 are permitted. If you do not set a value for this the global + transpose setting will be applied (expecting channel 10, drum, + notes). Example: TRANSPOSE=-2. + +

            +

            +
            LYRIC
            +
            This option will copy any Lyric events to the + +MMA meta track. The valid settings are ``On'' or ``Off''. By + default this is set to ``Off''. Example LYRIC=On. + +

            +

            +
            TEXT
            +
            This option will copy any Text events to the + +MMA meta track. The valid settings are ``On'' or ``Off''. By + default this is set to ``Off''. Example TEXT=On. + +

            +

            +
            START
            +
            Specifies the start point of the file to be included in + beats. For example, ``Start=22'' would start the include process 22 beats + into the file. The data will be inserted at the current song position in + your MMA file. The value used must greater or equal to 0 and may be + a fractional beat value (18.456 if fine). + +

            +

            +
            END
            +
            Specifies the end point of the file to be included in + beats. For example, ``End=100'' would disard all data after 100 beats + in the file. The value used must be greater that the Start position + and can be fractional. + +

            +

            +
            TRACK
            +
            A trackname must be be set into which notes are + inserted. You can set more than one track/channel if you wish. For + example, if you had the option DRUM=10 any notes in the MIDI + file with a channel 10 setting would be inserted into the +MMA Drum track. Similarity, Solo-Tenor=1 will copy notes + from channel 1 into the Solo-Tenor track. If the track + doesn't exist, it will be created. Note: this means that the channel + assignment in your included file and the new +MMA generated file + will most likely be different. Example: SOLO=1 + +

            +

            +
            + +

            +A complete example of usage is shown in the files in the directory +egs/frankie in the distribution. A short example: + +

            + + + +
            + MIDIinc File=test.mid Solo-Piano=1 Drum=10 Volume=70 + +
            + +

            +will include the MIDI file ``test.mid'' at the current position and +assign all notes in channel 1 to the Solo-Piano track and the +notes from channel 10 to the Drum track. The volumes for all +the notes will be adjusted to 70% of that in the original. + +

            +A few notes:

              -
            • Your syth lacks certain drum tones--in this case you may want - to set certain DRUMTR commands in a MMARC file. +
            • MIDI files to be included do not have to have the same tempo. + MIDI adjusts this automatically on playback. However, the internal + setting for beat division should be the same. +MMA assumes a beat + division of 192 (this is set in bytes 12 and 13 of the MIDI file). + If the included file differs a warning is printed and +MMA will + attempt to adjust the timings.

            • -
            • You are using an existing GROOVE in a song, but don't - like one or more of the Drum Tones selected. Rather than - editing the library file you can set a translation right in the - song. Note, do this before any GROOVE commands. +
            • All files are parsed to find the offset of the first note-on + event; notes to be included are set with their offsets compensated + by that time. This means that any silence at the start of the + included file is skipped (this may surprise you if you have used the + optional Start setting). If you want the included file to start + somewhere besides the start of the current bar you can use a + BEATADJUST before the MIDIINC--use another to move + the pointer back right after the include to keep the song pointer + correct. + +

              +

            • +
            • Not all events in the included files are transferred: notably + all system and meta events (other than text and lyric, see above) are ignored. + +

              +

            • +
            • If you want to apply different VOLUME or other options to + different tracks, just do multiple includes of the same file (with + each include using a different track and options). + +

            -To set a translation (or set of translations) just use a list of -drumtone values or symbolic names with each pair separated by -white space. For example: -

            - - -
            - -
            ToneTR SnareDrum2=SnareDrum1 HandClap=44
            - -
            - -

            -will use a ``SnareDrum1'' instead of a ``SnareDrum2'' and the value -``44'' (actually a ``PedalHiHat'') instead of a ``HandClap''. - -

            -You can turn off all drum tone translations with an empty line: - -

            - - -
            - -
            ToneTR
            - -
            - -

            -The syntax and usage of DRUMTR is quite similar to -VOICETR. - -

            - -

            -
            -VoiceVolTr +

            +MIDIMark

            -If you find that a particular voice, i.e., Piano2, is too loud or soft -you can create an entry in the ``Voice Volume Translation Table''. The -concept is quite simple: -MMA checks the table whenever a -track-specific VOLUME command is processed. The table is -created in a similar manner to the VOICETR command: +You can insert a MIDI Marker event into the Meta track with this command. The mark can be useful +in debugging your MIDI output with a sequencer or editor which supports Mark events (most do).

            - - +
            + +
            + MidiMark Label -
            VoiceVolTr Piano2=120 105=75
            - -
            +

            -Each voice pair must contain a valid MIDI voice (or numeric value), -an ``='' and a volume adjustment factor. The factor is a percentage -value which is applied to the normal volume. In the above example two -adjustments are created: +will insert the text ``Label'' at the current position. You can add an optional negative +or positive offset in beats: + +

            + + + +
            + MidiMark 2 Label4 + +
            + +

            +will insert ``Label4'' 2 beats into the next bar. + +

            + +

            +MIDIPan +

            + +

            +In MIDI-speak ``pan'' is the same as ``balance'' on a stereo. By +adjusting the MIDIPAN for a track you can direct the output to the +left, right or both speakers. Example: + +

            + + + +
            + Bass MIDIPan 4 + +
            + +

            +This command is only available in track mode. The data generated is +not sent into the MIDI stream until musical data is created for the +relevant MIDI channel. + +

            +The value specified must be in the range 0 to 127, and must be an integer. + +

            +MIDIPAN is not saved or restored by GROOVE commands, nor is +it effected by SEQCLEAR. A MIDIPAN is inserted directly into +the MIDI track at the point at which it is encountered in the music +file. This means that the effect of MIDIPAN will be in use until +another MIDIPAN is encountered. + +

            +MIDIPAN can be used in MIDI compositions to emulate the sound of an +orchestra. By assigning different values to different groups of +instruments, you can get the feeling of strings, horns, etc. all +placed in the ``correct'' position on the stage. + +

            +MIDIPAN can be used for much cruder purposes. When creating accompaniment +tracks for a mythical jazz group, you might set all the bass tracks (Bass, Walk, +Bass-1, etc) set to aMIDIPAN 0. Now, when practicing at home you have a +``full band''; and the bass player can practice without the generated +bass lines simply by turning off the left speaker. + +

            +Because most MIDI keyboard do not reset between +tunes, there should be a MIDIPAN to undo the effects at the end of +the file. Example:19.3 +

            + + + +
            + Include swing +
            +Groove Swing +
            +Bass MIDIPan 0 +
            +Walk MIDIPan 0 +
            +1 C +
            +2 C +
            ... +
            +123 C +
            +Bass MIDIPan 64 +
            +Walk MIDIPan 64
            + +
            + +

            + +

            +MIDISeq +

            + +

            +It is possible to associate a set of MIDI controller messages with +certain beats in a sequence. For example, you might want to have the +Modulation Wheel set for the first beats in a bar, but not for the +third. The following example shows how: + +

            + + + +
            + Seqsize 4 +
            +Begin Bass-2 +
            +Voice NylonGuitar +
            +Octave 4 +
            +Sequence { 1 4 1 90; 2 4 3 90; 3 4 5 90; 4 4 1+ 90} +
            +MIDIDef WheelStuff 1 1 0x7f ; 2 1 0x50; 3 1 0 +
            +MidiSeq WheelStuff +
            +Articulate 90 +
            +End +
            +
            +C $*$ 4
            + +
            + +

            +The MIDISEQ command is specific to a track and is saved as part +of the GROOVE definition. This lets style file writers use +enhanced MIDI features to dress up their sounds. + +

            +The command has the following syntax: + +

            + + + +
            + TrackName MidiSeq <Beat> <Controller> <Datum> [ ; ...] + +
            + +

            +where: +

            +
            Beat
            +
            is the Beat in the bar. This can be an integer (1,2, etc.) + or a floating point value (1.2, 2.25, etc.). It must be 1 or greater + and less than the end of bar (in 4/4 it must be less than + 5). + +

            +

            +
            Controller
            +
            A valid MIDI controller. This can be a value in the + range 0x00 to 0x7f or a symbolic name. See the appendix + , here, for a list of + defined names. + +

            +

            +
            Datum
            +
            All controller messages use a single byte ``parameter'' + in the range 0x00 to 0x7f. + +

            +

            +
            + +

            +You can enter the values in either standard decimal notation or in +hexadecimal with the prefixed ``0x''. In most cases, your code will be +clearer if you use values like ``0x7f'' rather than the equivalent +``127''. + +

            +The MIDI sequences specified can take several forms:

              -
            1. Piano2 will be played at %120 of the normal value, - -

              -

            2. -
            3. Banjo (voice 105) will be played at %75 of the normal value. -
            4. -
            - -

            -The adjustments are made when a track VOLUME command is -encountered. For example, if the above translation has be set and - -MMA encounters the following commands: +

          • A simple series like:

            - - +
            + +
            + MIDISeq 1 ReleaseTime 50; 3 ReleaseTime 0 -
            Begin Chord -
               Voice Piano2 -
               Volume mp -
               Sequence 1 4 90 -
            -End
            - -
            +

            -the following adjustments are made: - -

            - -

              -
            1. A lookup is done in the global volume table. The volume ``mf'' - is determined to be %85 for the set MIDI velocity, - -

              -

            2. -
            3. the adjusment of %120 is applied to the %85, changing that to %102. - -

              -

            4. -
            5. Assuming that no other volume adjustments are being made - (probably there will be a global volume and, perhaps, a - RVOLUME) the MIDI velocity in the sequence will be changed - from 90 to 91. Without the translation the 90 would have been changed to 76. +in this case the commands are applied to beats 1 and 3 in each bar + of the sequence.

            +

            . + +

            -To disable all volume translations: +As a set of names predefined in an MIDIDEF command:

            - -
            - -
            VoiceVolTr // Empty table
            - -
            - -

            - -

            + + +
            + MIDIdef Rel1 1 ReleaseTime 50; 3 ReleaseTime 0
            -DrumVolTr +MIDIdef Rel2 2 ReleaseTime 50; 4 ReleaseTime 0 +
            +MIDISeq Rel1 Rel2
            + +
            + +

            +Here, the commands defined in ``Rel1'' are applied to the first bar + in the sequence, ``Rel2'' to the second. And, if there are more bars + in the sequence than definitions in the line, the series will be + repeated for each bar. + +

            +A set of series enclosed in { } braces. Each braced series is + applied to a different bar in the sequence. The example above could + have been does as: + +

            + + + +
            + MIDISeq { 1 ReleaseTime 50; 3 ReleaseTime 0 } \ +
            { 2 ReleaseTime 50; 4 ReleaseTime 0 }
            + +
            + +

            +Finally, you can combine the above into different combinations. + For example: + +

            + + + +
            + MIDIDef Rel1 1 ReleaseTime 50 +
            +MIDIDef Rel2 2 ReleaseTime 50 +
            +MIDISeq { Rel1; 3 ReleaseTime 0 } { Rel2; 4 ReleaseTime 0 }
            + +
            + +

            + +

            +You can have specify different messages for different beats (or +different messages/controllers for the same beat) by listing them on +the same MIDISEQ line separated by ``;''s. + +

            +If you need to repeat a sequence for a measure in a sequence you can +use the special notation ``/'' to force the use of the previous line. +The special symbol ``z'' or ''-'' can be used to disable a bar (or +number of bars). For example: + +

            + + + +
            + Bass-Dumb MIDISeq 1 ReleaseTime 20 z / FOOBAR + +
            + +

            +would set the ``ReleaseTime'' sequence for the first bar of the +sequence, no MIDISeq events for the second and third, and the contents +of ``FOOBAR'' for the fourth. + +

            +To disable the sending of messages just use a single ``-'': + +

            + + + +
            + Bass-2 MidiSeq - // disable controllers + +
            + +

            + +

            +MIDISplit

            -You can change the volumes of indvidual drum tones with the -DRUMVOLTR translation. This command works just like the -VOICEVOLTR command desribed above. It just uses drum tones -instead of instrument voices. +For certain post-processing effects it is convenient to have each different drum tone +in a separate MIDI track. This makes it easier to apply an effect to, for example, the +snare drum. Just to make this a bit more fun you can split any track +created by +MMA .

            -For example, if you wish to make the drum tones ``SnareDrum1'' and -``HandClap'' a bit louder: +To use this feature:

            - - +
            + +
            + MIDISplit <list of channels> -
            DrumVolTr SnareDrum1=120 HandClap=110
            - -
            +

            -The drum tone names can be symbolic constants, or MIDI values as in -the next example: +So, to split out just the drum channel19.4 you would have the command:

            - - +
            + +
            + MIDISplit 10 -
            DrumVolTr 44=90 31=55
            - -
            +

            -All drum tone translations can be disabled with: +somewhere in your song file. + +

            +When processing +MMA creates an internal list of MIDI note-on events for each tone or pitch +in the track. It then creates a separate MIDI track for each list. Any other events are +written to another track.

            - -
            - -
            DrumVolTr // Empty table
            - -
            - +

            +MIDITname +

            -


            +When creating a MIDI track, +MMA inserts a MIDI Track Name event at the start of the track. +By default, this name is the same as the associated +MMA track name. You can change +this by issuing the MIDITNAME command. For example, to change the CHORD +track name you might do something like: + +

            + + + +
            + Chord MidiTname Piano + +
            + +

            +Please note that this only effects the tracks in the generated MIDI file. +You still refer to the track in your file as CHORD. + +

            + +

            +MIDIVoice +

            + +

            +Similar to the MIDISEQ command discussed in the previous +section, the MIDIVOICE command is used to insert MIDI +controller messages into your files. Instead of sending the data for +each bar as MIDISEQ does, this command just sends the listed +control events at the start of a track and then, if needed, at the +start of each bar. + +

            +Again, a short example. Let us assume that you want to use the +``Release Time'' controller to sustain notes in a bass line: + +

            + + + +
            + Seqsize 4 +
            +Begin Bass-2 +
            +Voice NylonGuitar +
            +MidiVoice 1 ReleaseTime 50 +
            +Octave 4 +
            +Sequence { 1 4 1 90; 2 4 3 90; 3 4 5 90; 4 4 1+ 90} +
            +Articulate 60 +
            +End +
            +
            +C $*$ 4
            + +
            + +

            +should give an interesting effect. + +

            +The syntax for the command is: + +

            + + + +
            + Track MIDIVoice <beat> <controller> <Datum> [; ...] + +
            + +

            +This syntax is identical to that discussed in the section for +MIDISEQ, above. The <beat>value is +required for the command--it determines if the data is sent before or +after the VOICE command is sent. Some controllers are reset by +a voice, others not. My experiments show that BANK should be +sent before, most others after. Using a ``beat'' of ``0'' forces the +MidiVoice data to be sent before the Voice control; any other ``beat'' +value causes the data to be sent after the Voice control. In this +silly example: + +

            + + + +
            + Voice Piano1 +
            +MidiVoice {0 Bank 5; 1 ReleaseTime 100}
            + +
            + +

            +the MIDI data is created in an order like: + +

            +

            +

            0 Param Ch=xx Con=00 val=05 +
            +0 ProgCh Ch=xx Prog=00 +
            +0 Param Ch=xx Con=72 val=80 + +
            + +

            +All the MIDI events occur at the same offset, but the order is (may +be) important. + +

            +By default +MMA assumes that the MIDIVoice data is to be used only +for the first bar in the sequence. But, it's possible to have a +different sequence for each bar in the sequence (just like you can +have a different VOICE for each bar). In this case, group the +different data groups with {} brackets: + +

            + + + +
            + Bass-1 MIDIVoice {1 ReleaseTime 50} {1 ReleaseTime 20} + +
            + +

            +This list is stored with other GROOVE data, so is ideal for +inclusion in a style file. + +

            +If you want to disable this command after it has been issued you can +use the form: + +

            + + + +
            + Track MIDIVoice - // disable + +
            + +

            +Some technical notes: + +

            + +

              +
            • +MMA tracks the events sent for each bar and will not duplicate + sequences. + +

              +

            • +
            • Be cautious in using this command to switch voice banks. If you + don't switch the voice bank back to a sane value you'll be playing + the wrong instruments! + +

              +

            • +
            • Do use the MIDICLEAR command ((details)) to ``undo'' anything + you've done via a MIDIVOICE command. + +

              +

            • +
            + +

            + +

            +
            +MIDIVolume +

            + +

            +MIDI devices equipped with mixer settings can make use of the +``Channel'' or ``Master'' volume settings.19.5 +

            + +MMA doesn't set any channel volumes without your knowledge. If you +want to use a set of reasonable defaults, look at the file +includes/init.mma which sets all channels other than ``1'' to +``100''. Channel ``1'' is assumed to be a solo/keyboard track and is +set to the maximum volume of ``127''. + +

            +You can set selected MIDIVOLUMEs: + +

            + + + +
            + Chord MIDIVolume 55 + +
            + +

            +will set the Chord track channel. For most users, the use of this +command is not recommended since it will upset the balance of +the library grooves. If you need a track softer or louder you should +use the volume setting for the track. + +

            +The data generated is not sent into the MIDI stream until musical data +is created for the relevant MIDI channel. + +

            +Caution: If you use the command with ALLTRACKS you should note +that only existing +MMA tracks will be effected. + +

            +


            Footnotes

            +
            +
            ... track:19.1
            +
            This is much easier to do + with the KeySig command, here + +
            +
            ... portamento19.2
            +
            The name ``Glis'' is used because +``MIDIPortamento'' gets to be a bit long to type and ``MIDIPort'' might +be interpreted as something to do with ``ports''. + +
            +
            ... Example:19.3
            +
            This is much easier to do with the + MMAStart and MMAEnd options (details). + +
            +
            ... channel19.4
            +
            In +MMA this will always be +channel 10. + +
            +
            ... settings.19.5
            +
            I discovered this + on my keyboard after many frustrating hours attempting to balance + the volumes in the library. Other programs would change the keyboard + settings, and not being aware of the changes, I'd end up scratching + my head. + +
            +

            - next - up - previous
            - Next: Other Commands and Directives - Up: Next: Fine Tuning (Translations) + Up: Reference Manual - Previous: Low Level MIDI Commands + Previous: Variables, Conditionals and Jumps
            -Bob -2006-10-15 +bob +2007-03-07
            diff --git a/mma/docs/html/ref/node2.html b/mma/docs/html/ref/node2.html index 4bf8398..7907337 100644 --- a/mma/docs/html/ref/node2.html +++ b/mma/docs/html/ref/node2.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
            - Next: Next: Tracks and Channels - Up: Up: Reference Manual - Previous: Previous: Overview and Introduction

            @@ -49,11 +49,11 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -73,16 +73,16 @@ name followed by the required options. For example,

            - - +
            + +
            + $ mma test -
            $ mma test
            - -
            +

            processes the file test2.1 and creates + HREF="#foot753">2.1 and creates the MIDI file test.mid.

            @@ -98,16 +98,17 @@ The following command line options are available:

            - - + + @@ -116,7 +117,7 @@ The following command line options are available: + HREF="#foot757">2.2 @@ -193,13 +193,12 @@ This makes perfect sense if you remember that the same line

            -

            OptionDescription
            OptionDescription
            - - +
            - Debugging and other + +
            + Debugging and other aids to figuring out what's going on. -
            +
            -v
            -d Enable LOTS of debugging messages. This option is mainly designed for program development and may not be useful to users.2.2
            -o A debug subset. This option forces the display of complete @@ -140,27 +141,25 @@ The following command line options are available: Display running progress. The bar numbers are displayed as they are created complete with the original input line. Don't be confused by multiple listing of ``*'' lines. For example the line - - +
            -
            -33 Cm - * 2 -
            + +
            + 33 Cm + * 2 -
            +
            would be displayed as:

            - - +
            -
            -88: 33 Cm *2 + +
            + 88: 33 Cm *2
            -89: 33 Cm *2 -
            +89: 33 Cm *2 -
            +

            This makes perfect sense if you remember that the same line @@ -178,13 +177,14 @@ This makes perfect sense if you remember that the same line generated.

            - - +
            - Commands which modify + +
            + Commands which modify MMA 's behaviour. -
            +
            -S
            - +
            -
            -$ mma myfile -S tempo=120 -
            + +
            + $ mma myfile -S tempo=120 -
            +

            will process the file myfile.mma with the variable $Tempo @@ -207,13 +206,12 @@ will process the file myfile.mma with the variable $Tempo

            - - +
            -
            -$ mma myfile -S test -
            + +
            + $ mma myfile -S test -
            +

            just sets the variable $test with no value.

  • -mBARS Set the maximum number of bars which can be generated. The default setting is 500 bars (a long song!2.3). This setting is + HREF="#foot706">2.3). This setting is needed since you can create infinite loops by improper use of the GOTO command. If your song really is longer than 500 bars use this option to increase the permitted size.
    -Mx Generate type 0 or 1 MIDI files. The parameter ``x'' must be set to the single digit ``0'' or ''1''. For more details, see the - MIDISMF section here.
    -0Generate a syncronization tick at the start of every MIDI + track. This is a one tick note on/off event at offset 0. It can be + useful in multi-track syncronization.
    - - +
    - Maintaining + +
    + Maintaining MMA 's database. -
    +
    @@ -254,7 +258,7 @@ just sets the variable $test with no value.
    - - +
    - File commands. + +
    + File commands. -
    +

    -i

    Specify the RC file to use. See -details here.

    @@ -304,13 +309,14 @@ The current installation of to it. This option lets you set the output MIDI file to any filename.

    - - +
    - The following commands + +
    + The following commands are used to create the documentation. As a user you should probably never have a need for any of them. -
    +
    -Dk
    -Dxh Same as -Dxl, but generates HTML output. Used by the mklibdoc.py tool.
    -DnCreate a table of the available chord types.
    -DdaCreate a table of the MIDI drum note names, arranged alphabetically.
    -DdmCreate a table of the MIDI drum note names, arranged by MIDI value.
    -DiaCreate a table of the MIDI instrument names, arranged alphabetically.
    -DimCreate a table of the MIDI instrument names, arranged by MIDI value.

    @@ -376,7 +367,7 @@ Programming Comments MMA is designed to read and write files; it is not a filter.2.4 + HREF="#foot764">2.4

    As noted earlier in this manual, MMA has been written entirely in @@ -396,28 +387,28 @@ I've done a bit of testing with Psyco


    Footnotes

    -
    ...test...test2.1
    Actually, the file test or test.mma is processed. Please read section - file extensions. + file extensions.
    -
    ... users.... users.2.2
    A number of the debugging commands can also be set dynamically in a - song. See the debug section here + song. See the debug section here for details.
    -
    ... song!... song!2.3
    500 bars with 4 beats per bar at 200 BPM is about 10 minutes.
    -
    ... +
    ... filter.2.4
    A filter mode could be added to @@ -427,26 +418,26 @@ filter.

    - next - up - previous
    - Next: Next: Tracks and Channels - Up: Up: Reference Manual - Previous: Previous: Overview and Introduction
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node20.html b/mma/docs/html/ref/node20.html index 49c1cc2..a16232f 100644 --- a/mma/docs/html/ref/node20.html +++ b/mma/docs/html/ref/node20.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Other Commands and Directives - +Fine Tuning (Translations) + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Begin/End Blocks - Up: Next: Other Commands and Directives + Up: Reference Manual - Previous: Fine Tuning (Translations) + Previous: Low Level MIDI Commands

    @@ -49,1438 +49,491 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

    - +
    -Other Commands and Directives +Fine Tuning (Translations)

    -In addition to the ``Pattern'', ``Sequence'', ``Groove'' and -``Repeat'' and other directives discussed earlier, and chord data, - -MMA supports a number of directives which affect the flavor of your -music. +A program such as +MMA which is intended to be run of various +computers and synthesizers (both hardware keyboards and software +versions) suffers from a minor deficency of the MIDI standards: mainly +that the standard says nothing about what a certain instrument should +sound like, or the relative volumes between instruments. The GM +extension helps a bit, but only a bit, by saying that certain +instruments should be assigned certain program change values. This +means that all GM synths will play a "Piano" if instrument 000 is +selected.

    -The subjects presented in this chapter are ordered alphabetically. +But, if one plays a GM file on a Casio keyboard, then on PC +soft-synth, and then on a Yahama keyboard you will get three quite +different sounds. The files supplied in this distribution have been +created to sound good on the author's setup: A Casio WK-3000 keyboard. + +

    +But, what if your hardware is different? Well, there are solutions! +Later in this chapter commands are shown which will change the +preselected voice and tone commands and the default volumes. At this +time there are no example files supplied with +MMA , but your +contributions are welcome. + +

    +The general suggestion is that:

    -

    +
      +
    1. You create a file with the various translations you need. For + example, the file might be called yamaha.mma and contain + lines like: + +

      + + + +
      + VoiceTR Piano1=Piano2
      -AllTracks +ToneTr SnareDrum2=SnareDrum1 +
      +VoiceVolTr Piano2=120 BottleBlow=80 +
      +DrumVolTr RideBell=90 Tambourine=120
      + +
      + +

      +Place this file in the directory /usr/local/share/mma/includes. + +

      +

    2. +
    3. Include this file in your ~/.mmarc file. Following the + above example, you would have a line: + +

      + + + +
      + Include yamaha + +
      + +

      +

    4. +
    + +

    +That's it! Now, whenever you compile a +MMA file the translations +will be done. + +

    +All of the following translation settings follow a similar logic as to ``when'' +they take effect, and that is at the time the VOICE, +VOLUME, etc. command is issued. This may confuse the unwary if +GROOVES are being used. But, the following sequence: + +

    + + +
    + +
      +
    1. You set a voice with the VOICE command, +
    2. +
    3. You save that voice into a GROOVE with DEFGROOVE, +
    4. +
    5. You create a voice translation with VOICETR, +
    6. +
    7. You activate the previously defined GROOVE. +
    8. +
    + + + +
    Wrong!
    + +

    +does not have the desired effect. In the above sequence the +VOICETR will have no effect. For the desired +translations to work the VOICE (or whatever) command must come +after the translation command. + +

    + +

    +
    +VoiceTr

    -Sometimes you want to apply the same command to all the currently -defined tracks; for example, you might want to ensure that no -tracks have SEQRND set. Yes, you could go though each track -(and hope you don't miss any) and explicitly issue the command: - -

    - - -
    - -
    Bass SeqRnd Off - .... -
    -Chord SeqRnd Off
    - -
    - -

    -But, - -

    - - -
    - -
    AllTracks SeqRnd Off
    - -
    - -

    -is much simpler. Similarly, you can set the articulation for all -tracks with: - -

    - - -
    - -
    AllTracks Articulate 80
    - -
    - -

    -You can even combine this with a BEGIN/END like: - -

    - - -
    - -
    Begin AllTracks -
      Articulate 80 -
      SeqRnd Off -
      Rskip 0 -
    -End
    - -
    - -

    -This command is handy when you are changing an existing GROOVE. - -

    -Note that only currently defined tracks are effected by this command. - -

    -A further option is to limit ALLTRACKS to specific tracks -type. For example, you might want to set all the DRUM track -volumes to ``FF'': - -

    - - -
    - -
    AllTracks Drum Volume ff
    - -
    - -

    -Or to set the articulation on BASS and WALK tracks: - -

    - - -
    - -
    AllTracks Bass Walk Articulate 55
    - -
    - -

    -It is assumed that all the arguments following the initial command -which are valid track types (Bass, Chord, Arpeggio, Scale, Drum, Walk, -Melody, or Solo) are track type limiters. - -

    - -

    -
    -Articulate -

    - -

    -When -MMA processes a music file, all the note lengths specified in a -pattern are converted to MIDI lengths. - -

    -For example in: - -

    - - -
    - -
    Bass Define BB 1 4 1 100; 2 4 5 90; 3 4 1 80; 4 4 5 90
    - -
    - -

    -bass notes on beats 1, 2, 3 and 4 are define. All are quarter notes. - -MMA , being quite literal about things, will make each note exactly -192 MIDI ticks long--which means that the note on beat 2 will start -at the same time as the note on beat 1 ends. - -

    - -MMA has an articulate setting for each voice. This value is applied -to shorten or lengthen the note length. By default, the setting is 90. -Each generated note duration is taken to be a percentage of this -setting, So, a quarter note with a MIDI tick duration of 192 will -become 172 ticks long. - -

    -If articulate is applied to a short note, you are guaranteed that the -note will never be less than 1 MIDI tick in length. - -

    -To set the value, use a line like: - -

    - - -
    - -
    Chord-1 Articulate 96
    - -
    - -

    -Articulate values must be greater than 0 and less than or -equal to 200. Values over 100 will lengthen the note. Settings -greater than 120 will generate a warning. - -

    -You can specify a different ARTICULATE for each bar in a -sequence. Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Chord Articulate 50 60 / 30
    - -
    - -

    -Notes: The full values for the notes are saved with the -pattern definition. The articulation adjustment is applied at -run time. The ARTICULATE setting is saved with a -GROOVE. - -

    - -

    -
    -Copy -

    - -

    -Sometimes it is useful to duplicate the settings from one voice to -another. The COPY command does just that: - -

    - - -
    - -
    Bass-1 Copy Bass
    - -
    - -

    -will copy the settings from the Bass track to the Bass-1 track. - -

    -The COPY command only works between tracks of the same type. - -

    -The following settings are copied: +In previous section you saw how to set a voice for a track by using its +standard MIDI name. The VOICETR command sets up a translation +table that can be used in two different situations:

    +VOICETR works by setting up a simple translation table of +``name'' and ``alias'' pairs. Whenever +MMA encounters a voice name +in a track command it first attempts to translate this name though the +alias table. -

    +

    +To set a translation (or series of translations): + +

    + + + +
    + VoiceTr Piano1=Clavinet Hmmm=18 + +
    + +

    +Note that you additional VOICETR commands will add entries to +the existing table. To clear the table use the command with no +arguments: + +

    + + + +
    + VoiceTr // Empty table + +
    + +

    +Assuming the first command, the following will occur: + +

    + + + +
    + Chord-Main Voice Hmmm + +
    + +

    +The VOICE for the Chord-Main track will be set to ``18'' +or ``Organ3''. + +

    + + + +
    + Chord-2 Voice Piano1 + +
    + +

    +The VOICE for the Chord-2 track will be set to +``Clavinet''. + +

    +If your synth does not follow standard GM-MIDI voice naming +conventions you can create a translation table which can be included +in all your +MMA song files via an RC file. But, do note that the +resulting files will not play properly on a synth conforming to the +GM-MIDI specification. + +

    +Following is an abbreviated and untested example for using an obsolete and unnamed synth: + +

    + + + +
    + VoiceTr Piano1=3 \
    -Comment +Piano2=4 \ +
    +Piano3=5 \ +
    ... \ +
    +Strings=55 \ +
    ...
    + +
    + +

    +Notes: the translation is only done one time and no verification is +done when the table is created. + +

    +For translating drum tone values, see +DRUMTR. + +

    + +

    +
    +DrumTr

    -As previously discussed, a comment in -MMA is anything following a -``//'' in a line. A second way of marking a comment is with the -COMMENT directive. This is quite useful in combination the -BEGIN and END directives. For example: - -

    - - -
    - -
    Begin Comment -
        This is a description spanning -
            several lines which will be -
            ignored by MMA. -
    -End
    - -
    - -

    -You could achieve the same with: - -

    - - -
    - -
    // This is a description spanning -
    // several lines which will be -
    // ignored by MMA.
    - -
    - -

    -or even: - -

    - - -
    - -
    Comment This is a description spanning -
    -Comment several lines which will be -
    -Comment ignored by MMA.
    - -
    - -

    -One minor difference between // and -COMMENT is that the first is discarded when the -input stream is read; the more verbose version is -discarded during line processing. - -

    -Quite often it is handy to delete large sections of a song with a -BEGIN COMMENT/END on a temporary basis. - -

    - -

    -
    -Debug -

    - -

    -To enable you to find problems in your song files (and, perhaps, even -find problems with -MMA itself) various debugging messages can be -displayed. These are normally set from the command line -command line. - -

    -However, it is possible to enable various debugging messages -dynamically in a song file using the DEBUG directive. In a -debug statement you can enable or disable any of a variety of -messages. A typical directive is: - -

    - - -
    - -
    Debug Debug=On Expand=Off Patterns=On
    - -
    - -

    -Each section of the debug directive consists of a mode -and the command word ON or OFF. The two parts -must be joined by a single ``$=$''. You may use the -values ``0'' for ``Off'' and ``1'' for ``On'' if desired. - -

    -The available modes with the equivalent command line switches are: - -

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ModeCommand Line Equivalent
    Debug-ddebugging messages
    Filenames-odisplay filenames
    Patterns-ppattern creation
    Sequence-ssequence creation
    Runtime-rrunning progress
    Warnings-wwarning messages
    Expand-edisplay expanded lines
    -
    - -

    -The modes and command are case-insensitive (although the command line switches are not). - -

    -The current state of the debug flags is saved in the variable -$_Debug and the state prior to a change is saved in $_LastDebug. - -

    - -

    -
    -Delete -

    - -

    -If you are using a track in only one part of your song, especially if -it is at the start, it may be wise to free that track's resources when -you are done with it. The DELETE command does just that: - -

    - - -
    - -
    Solo Delete
    - -
    - -

    -If a MIDI channel has been assigned to that track, it is -marked as ``available'' and the track is deleted. Any data -already saved in the MIDI track will be written when -MMA is -finished processing the song file. - -

    - -

    -
    -Direction -

    - -

    -In tracks using chords or scales you can change the direction in which -they are applied: - -

    - - -
    - -
    Scale Direction UP
    - -
    - -

    -The effects differ in different track types. For SCALE and ARPEGGIO tracks: - -

    -

    - - - - - - - - - - - - - -
    UPPlays in upward direction only
    DOWNPlays in downward direction only
    BOTHPlays upward and downward (default)
    RANDOMPlays notes from the chord or scale randomly
    -
    -

    -

    When this command is encountered in a SCALE track the start -point of the scale is reset. -
    -

    - -

    -A WALK track recognizes the following option settings: - -

    -

    - - - - - - - - - - - - - -
    BOTHThe default. The bass pattern - will go up and down a partial scale. Some notes may be repeated.
    UPNotes will be chosen sequentially from an ascending, partial scale.
    DOWNNotes will be chosen sequentially from a descending, partial scale.
    RANDOMNotes will be chosen in a random direction from a partial scale.
    -
    -

    -

    All four patterns are useful and create quite different effects. - -
    - -

    -The CHORD tracks DIRECTION only has an effect when the -STRUM setting has a non-zero value. In this case the following -applies: - -

    -

    - - - - - - - - - - - - - -
    UPThe default. Notes are sounded from the lowest tone to the highest.
    DOWNNotes are sounded from the highest to the lowest.
    BOTHThe UP and DOWN values are alternated.
    RANDOMIgnored (uses UP).
    -
    - -

    -You can specify a different DIRECTION for each bar in a -sequence. Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Arpeggio Direction Up Down / Both
    - -
    - -

    -The setting is ignored by BASS, DRUM and SOLO tracks. - -

    - -

    -Mallet -

    - -

    -Some instruments (Steel-drums, banjos, marimbas, etc.) are normally -played with rapidly repeating notes. Instead of painfully inserting -long lists of these notes, you can use the MALLET directive. -The MALLET directive accepts a number of options, each an -OPTION=VALUE pair. For example: - -

    - - -
    - -
    Solo-Marimba Mallet Rate=16 Decay=-5
    - -
    - -

    -This command is also useful in creating drum rolls. For example: - -

    - - -
    - -
    Begin Drum-Snare2 -
      Tone SnareDrum1 -
      Volume F -
      Mallet Rate=32 Decay=-3 -
      Rvolume 3 -
      Sequence z z z 1 1 100 -
    -End
    - -
    - -

    -The following options are supported: - -

    - -

    -Rate -

    - -

    -The RATE must be a valid note length (i.e., 8, 16, or even -16.+8). - -

    -For example: - -

    - - -
    - -
    Solo-Marimba Mallet Rate=16
    - -
    - -

    -will set all the notes in the ``Solo-Marimba'' track to be sounded a -series of 16th notes. +It is possible to create a translation table which will substitute one +Drum Tone for another. This can be useful in a variety of +situations, but consider:

      -
    • Note duration modifiers such as articulate are applied to each - resultant note, +
    • Your syth lacks certain drum tones--in this case you may want + to set certain DRUMTR commands in a MMARC file.

    • -
    • It is guaranteed that the note will sound at least once, - -

      -

    • -
    • The use of note lengths assures a consistent sound independent - of the song tempo. - -

      +

    • You are using an existing GROOVE in a song, but don't + like one or more of the Drum Tones selected. Rather than + editing the library file you can set a translation right in the + song. Note, do this before any GROOVE commands.

    -To disable this setting use a value of ``0''. +To set a translation (or set of translations) just use a list of +drumtone values or symbolic names with each pair separated by +white space. For example:

    -

    -Decay -

    - -

    -You can adjust the volume (velocity) of the notes being repeated when -MALLET is enabled: - -

    - - - +
    + + +
    + ToneTR SnareDrum2=SnareDrum1 HandClap=44 -
    Drum-Snare Mallet Decay=-15
    +
    + +

    +will use a ``SnareDrum1'' instead of a ``SnareDrum2'' and the value +``44'' (actually a ``PedalHiHat'') instead of a ``HandClap''. + +

    +You can turn off all drum tone translations with an empty line: + +

    + + +
    + ToneTR -
    +

    -The argument is a percentage of the current value to add to the note -each time it is struck. In this example, assuming that the note length -calls for 4 ``strikes'' and the initial velocity is 100, the note will -be struck with a velocity of 100, 85, 73 and 63. - -

    -Important: a positive value will cause the notes to get louder, -negative values cause the notes to get softer. - -

    -Note velocities will never go below 1 or above 255. Note, however, -that notes with a velocity of 1 will most likely be inaudible. - -

    -The decay option value must be in the range -50 to 50; however, be -cautious using any values outside the range -5 to 5 since the volume -(velocity) of the notes will change quite quickly. The default -value is 0 (no decay). +The syntax and usage of DRUMTR is quite similar to +VOICETR.

    -

    +


    -Octave +VoiceVolTr

    -When -MMA initializes and after the SEQCLEAR command all track -octaves are set to ``4''. This will place most chord and bass notes in -the region of middle C. - -

    -You can change the octave for any voice with OCTAVE command. For example: +If you find that a particular voice, i.e., Piano2, is too loud or soft +you can create an entry in the ``Voice Volume Translation Table''. The +concept is quite simple: +MMA checks the table whenever a +track-specific VOLUME command is processed. The table is +created in a similar manner to the VOICETR command:

    - - +
    + +
    + VoiceVolTr Piano2=120 105=75 -
    Bass-1 Octave 3
    - -
    +

    -Sets the notes used in the ``Bass-1'' track one octave lower than normal. +Each voice pair must contain a valid MIDI voice (or numeric value), +an ``='' and a volume adjustment factor. The factor is a percentage +value which is applied to the normal volume. In the above example two +adjustments are created:

    -The octave specification can be any value from 0 to 10. Various -combinations of INVERT, TRANSPOSE and OCTAVE can -force notes to be out of the valid MIDI range. In this case the lowest -or highest available note will be used. -

    -You can specify a different OCTAVE for each bar in a sequence. -Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Chord Octave 4 5 / 4
    - -
    - -

    - -

    -
    -Off -

    - -

    -To disable the generation of MIDI output on a specific track: - -

    - - -
    - -
    Bass Off
    - -
    - -

    -This can be used anywhere in a file. Use it to override the effect of -a predefined groove, if you wish. This is simpler than resetting a -voice in a groove. The only way to reset this command is with a -ON directive. - -

    - -

    -
    -On -

    - -

    -To enable the generation of MIDI output on a specific track which has -been disabled with an OFF directive: - -

    - - -
    - -
    Bass On
    - -
    - -

    - -

    -Print -

    - -

    -The PRINT directive will display its argument to the screen -when it is encountered. For example, if you want to print the filename -of the input file while processing, you could insert: - -

    - - -
    - -
    Print Making beautiful music for MY SONG
    - -
    - -

    -No control characters are supported. - -

    -This can be useful in debugging input files. - -

    - -

    -PrintActive -

    - -

    -The PRINTACTIVE directive will the currently active -GROOVE and the active tracks. This can be quite useful when -writing groove files and you want to modify and existing groove. - -

    -Any parameters given are printed as single comment at the end of the header line. - -

    -This is strictly a debugging tool. No PRINTACTIVE statements -should appear in finalized grooves or song files. - -

    - -

    -RndSeed -

    - -

    -All of the random functions (RTIME, RSKIP, etc.) in -MMA depend -on the Python random module. Each time -MMA generates a track the values generated -by the random functions will be different. In most cases this is a ``good thing''; however, -you may want -MMA to use the same sequence of random values20.1 each time it generates a track. Simple: just use: - -

    - - -
    - -
    RndSeed 123.56
    - -
    - -

    -at the top of your song file. You can use any value you want: it really doesn't -make any difference, but different values will generate different sequences. - -

    -You can also use this with no value, in which case Python uses its own value (see -the Python manual for details). Essentially, using no value undoes the effect which -permits the mixing of random and not-so-random sections in the same song. - -

    -One interesting use of RNDSEED could be to ensure that a repeated section -is identical: simply start the section with something like: - -

    - - -
    - -
    Repeat -
    -RndSeed 8 -
    ... chords
    - -
    - -

    -It is highly recommended that you do not use this command in library files. - -

    - -

    -
    -RSkip -

    - -

    -To aid in creating syncopated sounding patterns, you can use the -RSKIP directive to randomly silence or skip notes. The command -takes a value in the range 0 to 99. The ``0'' argument disables -skipping. For example: - -

    - - -
    - -
    Begin Drum -
        Define D1 1 0 90 -
        Define D8 D1 * 8 -
        Sequence D8 -
        Tone OpenHiHat -
        RSkip 40 -
    -End
    - -
    - -

    -In this case a drum pattern has been defined to hit short ``OpenHiHat'' -notes 8 per bar. The RSKIP argument of ``40'' causes the -note to be NOT sounded (randomly) only 40% of the time. - -

    -Using a value of ``10'' will cause notes to be skipped 10% of the -time (they are played 90% of the time), ``90'' means to skip the -notes 90% of the time, etc. - -

    -You can specify a different RSKIP for each bar in a sequence. -Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Scale RSkip 40 90 / 40
    - -
    - -

    -If you use the RSKIP in a chord track, the entire chord -will not be silenced. The option will be applied to the -individual notes of each chord. This may or may not be what you are -after. You cannot use this option to generate entire chords randomly. -For this effect you need to create several chord patterns and select -them with SEQRND. - -

    - -

    -
    -RTime -

    - -

    -One of the biggest problem with computer generated drum and rhythm -tracks is that, unlike real musicians, the beats are precise and ``on -the beat''. The RTIME directive attempts to solve this. - -

    -The command can be applied to all tracks. - -

    - - -
    - -
    Drum-4 Rtime 4
    - -
    - -

    -The value passed to the RTime directive are the number of MIDI ticks -with which to vary the start time of the notes. For example, if you -specify ``5'' the start times will vary from -5 to +5 ticks) on each -note for the specified track. There are 192 MIDI ticks in each quarter -note. - -

    -Any value from 0 to 100 can be used; however values in the range 0 to -10 are most commonly used. Exercise caution in using large values! - -

    -You can specify a different RTIME for each bar in a sequence. -Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Chord RTime 4 10 / 4
    - -
    - -

    -RTIME is guaranteed never to start a note before the start of a bar. - -

    - -

    -
    -ScaleType -

    - -

    -This option is only used by SCALE tracks. It can be set for -other tracks, but the setting is not used. - -

    -By default, the SCALETYPE is set to AUTO. The settings -permissible are: - -

    -

    - - - - - - - -
    CHROMATICForces use of a chromatic scale
    AUTOUses scale based on the current chord (default)
    -
    - -

    -When this command is encountered in a SCALE track the start -point of the scale is reset. - -

    - -

    - -
    -Seq -

    - -

    -If your sequence, or groove, has more than one pattern (i.e., you have -set SeqSize to a value other than 1), you can use this directive to -force a particular pattern point to be used. The directive: - -

    - - -
    - -
    Seq
    - -
    - -

    -resets the sequence counter to 1. This means that the next bar -will use the first pattern in the current sequence. You can force a -specific pattern point by using an optional value after the directive. -For example: - -

    - - -
    - -
    Seq 8
    - -
    - -

    -forces the use of pattern point 8 for the next bar. This can be quite -useful if you have a multi-bar sequence and, perhaps, the eight bar is -variation which you want used every eight bars, but also for a -transition bar, or the final bar. Just put a SEQ 8 at those -points. You might also want to put a SEQ at the start of -sections to force the restart of the count. - -

    -If you have enable sequence randomization with the SEQRND ON -command, the randomization will be disabled by a SEQ -command.20.2 However, -settings of track SEQRND will not be effected. One difference -between SEQRND OFF and SEQ is that the current sequence -point is set with the latter; with SEQRND OFF it is left at a -random point. - -

    -Note: Using a value greater than the current SEQSIZE is not -permitted. - -

    -This is a very useful command! For example, look at the four bar -introduction of the song ``Exactly Like You'': - -

    - - -
    - -
    Groove BossanovaEnd -
    -seq 3 -
    -1 C -
    -seq 2 -
    -2 Am7 -
    -seq 1 -
    -3 Dm7 -
    -seq 3 -
    -4 G7 / G7#5
    - -
    - -

    -In this example the four bar ``ending groove'' has been used to create -an interesting introduction. - -

    - -

    -
    -Strum -

    - -

    -By default -MMA plays all the notes in a chord at the same time. To -make the chord more like something a guitar or banjo might play, use -the STRUM directive. For example: - -

    - - -
    - -
    Chord-1 Strum 5
    - -
    - -

    -sets the strumming factor to 5 for track Chord-1. - -

    -Setting the STRUM in any track other than a CHORD track -will generate a warning message and the command will be ignored. - -

    -The strum factor is specified in MIDI ticks. Usually values around 10 -to 15 work just fine. The valid range for STRUM is 0 to 100. - -

    -You can specify a different STRUM for each bar in a sequence. -Repeated values can be represented with a ``/'': - -

    - - -
    - -
    Chord Strum 20 5 / 10
    - -
    - -

    -Note: When chords have both a STRUM and INVERT applied, -the order of the notes played will not necessarily be root, third, -etc. The notes are sorted into ascending order, so for a C major scale -with and INVERT of 1 the notes played would be ``E G C''. That -is, unless the DIRECTION has been set to ``DOWN'' in which case -the order would be reversed (but the notes would be the same). - -

    - -

    -Transpose -

    - -

    -You can change the key of a piece with the ``Transpose'' command. For -example, if you have a piece notated in the key of ``C'' and you want -it played back in the key of ``D'': - -

    - - -
    - -
    Transpose 2
    - -
    - -

    -will raise the playback by 2 semi-tones. Since -MMA 's author plays tenor saxophone - -

    - - -
    - -
    Transpose -2
    - -
    - -

    -which puts the MIDI keyboard into the same key as the horn, is not an -uncommon directive - -

    -You can use any value between -12 and 12. All tracks (with the logical -exception of the drum tracks) are effected by this command. - -

    - -

    -Unify -

    - -

    -The UNIFY command is used to force multiple notes of the same -voice and pitch to be combined into a single, long, tone. This is very -useful when creating a sustained voice track. For example, consider -the following which might be used in real groove file: - -

    - - -
    - -
    Begin Bass-Sus -
    -Sequence 1 1 1 90 4 -
    -Articulate 100 -
    -Unify On -
    -Voice TremoloStrings -
    -End
    - -
    - -

    -Without the UNIFY ON command the strings would be sounded (or -hit) four times during each bar; with it enabled the four hits are -combined into one long tone. This tone can span several bars if the -note(s) remain the same. - -

    -The use of this command depends on a number of items: - -

    - -

      -
    • The VOICE being used. It makes sense to use enable the - setting if using a sustained tone like ``Strings"; it probably - doesn't make sense if using a tone like ``Piano1''. +
        +
      1. Piano2 will be played at %120 of the normal value,

      2. -
      3. For tones to be combined you will need to have ARTICULATE - set to a value of 100. Otherwise the on/off events will have small - gaps in them which will cancel the effects of UNIFY. - -

        +

      4. Banjo (voice 105) will be played at %75 of the normal value.
      5. -
      6. Ensure that RTIME is not set for UNIFY tracks - since the start times may cause gaps. +

      -

    • -
    • If your pattern or sequence has different volumes in different - beats (or bars) the effect of a UNIFY will be to ignore - volumes other than the first. Only the first NOTE ON and the - last NOTE OFF events will appear in the MIDI file. +The adjustments are made when a track VOLUME command is +encountered. For example, if the above translation has be set and -

      -

    • -
    - -

    -You can specify a different UNIFY for each bar in a sequence. -Repeated values can be represented with a ``/'': +MMA encounters the following commands:

    - -
    - -
    Chord Unify On / / Off
    - -
    - -

    -But, you probably don't want to use this particular feature. - -

    -Valid arguments are ``On'' or ``1'' to enable; ``Off'' or ``0'' to -disable. - -

    - -

    + + +
    + Begin Chord +
       Voice Piano2 +
       Volume mp +
       Sequence 1 4 90
    -Voice +End
    + +
    + +

    +the following adjustments are made: + +

    + +

      +
    1. A lookup is done in the global volume table. The volume ``mf'' + is determined to be %85 for the set MIDI velocity, + +

      +

    2. +
    3. the adjusment of %120 is applied to the %85, changing that to %102. + +

      +

    4. +
    5. Assuming that no other volume adjustments are being made + (probably there will be a global volume and, perhaps, a + RVOLUME) the MIDI velocity in the sequence will be changed + from 90 to 91. Without the translation the 90 would have been changed to 76. + +

      +

    6. +
    + +

    +To disable all volume translations: + +

    + + + +
    + VoiceVolTr // Empty table + +
    + +

    + +

    +
    +DrumVolTr

    -The MIDI instrument or voice used for a track is set with: +You can change the volumes of indvidual drum tones with the +DRUMVOLTR translation. This command works just like the +VOICEVOLTR command desribed above. It just uses drum tones +instead of instrument voices. + +

    +For example, if you wish to make the drum tones ``SnareDrum1'' and +``HandClap'' a bit louder:

    - - +
    + + +
    + DrumVolTr SnareDrum1=120 HandClap=110 -
    Chord-2 Voice Piano1
    +
    + +

    +The drum tone names can be symbolic constants, or MIDI values as in +the next example: + +

    + + +
    + DrumVolTr 44=90 31=55 -
    +

    -Voices apply only to the specified track. The actual instrument can be -specified via the MIDI instrument number, or with the symbolic name. -See the tables in the MIDI voicing section for lists of the recognized -names. - -

    -You can create interesting effects by varying the voice used with drum -tracks. By default ``Voice 0'' is used. However, you can change the -drum voices. The supplied library files do not change the voices since this -appears to be highly dependent on the MIDI synth you are using. - -

    -You can specify a different VOICE for each bar in a sequence. -Repeated values can be represented with a ``/'': +All drum tone translations can be disabled with:

    - - +
    + +
    + DrumVolTr // Empty table -
    Chord Voice Piano1 / / Piano2
    - -
    +
    +

    -It is possible to set up translations for the selected voice: see -VOICETR. - -

    -


    Footnotes

    -
    -
    ... values20.1
    -
    Yes, this is -a contradiction of terms. - -
    -
    ... -command.20.2
    -
    A warning message will also be displayed. - -
    -

    +
    - next - up - previous
    - Next: Begin/End Blocks - Up: Next: Other Commands and Directives + Up: Reference Manual - Previous: Fine Tuning (Translations) + Previous: Low Level MIDI Commands
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node21.html b/mma/docs/html/ref/node21.html index 7630dea..3091b9c 100644 --- a/mma/docs/html/ref/node21.html +++ b/mma/docs/html/ref/node21.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Begin/End Blocks - +Other Commands and Directives + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Documentation Strings - Up: Next: Begin/End Blocks + Up: Reference Manual - Previous: Other Commands and Directives + Previous: Fine Tuning (Translations)

    @@ -49,162 +49,1442 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

    - +
    -Begin/End Blocks +Other Commands and Directives

    -Entering a series of directives for a specific track can get quite -tedious. To make the creation of library files a bit easier, you can -create a block. For example, the following: +In addition to the ``Pattern'', ``Sequence'', ``Groove'' and +``Repeat'' and other directives discussed earlier, and chord data, + +MMA supports a number of directives which affect the flavor of your +music. + +

    +The subjects presented in this chapter are ordered alphabetically.

    - -
    - -
    Drum Define X 0 2 100; 50 2 90 +


    -Drum Define Y 0 2 100 -
    -Drum Sequence X Y

    - -
    - -

    -Can be replaced with: - -

    - - -
    - -
    Drum Begin -
        Define X 0 2 100; 50 2 90 -
        Define Y 0 2 100 - End -
    -Drum Sequence X Y
    - -
    - -

    -Or, even more simply, with: - -

    - - -
    - -
    Drum Begin Define -
        X 0 2 100; 50 2 90 -
        Y 0 2 100 -
    -End
    - -
    - -

    -If you examine some of the library files you will see that this -shortcut is used a lot. - -

    - -

    -Begin +AllTracks

    -The BEGIN command requires any number of arguments. Valid -examples include: +Sometimes you want to apply the same command to all the currently +defined tracks; for example, you might want to ensure that no +tracks have SEQRND set. Yes, you could go though each track +(and hope you don't miss any) and explicitly issue the command:

    - - +
    - -
    Begin Drum + +
    + Bass SeqRnd Off + ....
    -Begin Chord2 -
    -Begin Walk Define
    +Chord SeqRnd Off -
    +

    -Once a BEGIN block has been entered, all subsequent lines have -the words from the BEGIN command prepended to each line of -data. There is not much magic here--BEGIN/END is really -just some syntactic sugar. +But,

    -

    -End + + +
    + AllTracks SeqRnd Off + +
    + +

    +is much simpler. Similarly, you can set the articulation for all +tracks with: + +

    + + + +
    + AllTracks Articulate 80 + +
    + +

    +You can even combine this with a BEGIN/END like: + +

    + + + +
    + Begin AllTracks +
      Articulate 80 +
      SeqRnd Off +
      Rskip 0 +
    +End
    + +
    + +

    +This command is handy when you are changing an existing GROOVE. + +

    +Note that only currently defined tracks are effected by this command. + +

    +A further option is to limit ALLTRACKS to specific tracks +type. For example, you might want to set all the DRUM track +volumes to ``FF'': + +

    + + + +
    + AllTracks Drum Volume ff + +
    + +

    +Or to set the articulation on BASS and WALK tracks: + +

    + + + +
    + AllTracks Bass Walk Articulate 55 + +
    + +

    +It is assumed that all the arguments following the initial command +which are valid track types (Bass, Chord, Arpeggio, Scale, Drum, Walk, +Melody, or Solo) are track type limiters. + +

    + +

    +
    +Articulate

    -To finish off a BEGIN block, use a single END on a line -by itself. +When +MMA processes a music file, all the note lengths specified in a +pattern are converted to MIDI lengths.

    -Defining musical data, repeats, or other BEGINs inside a block -(other than COMMENT blocks) will not work. - -

    -Nesting is permitted. Eg: +For example in:

    - -
    + + +
    + Bass Define BB 1 4 1 100; 2 4 5 90; 3 4 1 80; 4 4 5 90 -
    Scale Begin -
        Begin Define -
            
    stuff
    -
        End -
        Sequence
    stuff
    +
    + +

    +bass notes on beats 1, 2, 3 and 4 are define. All are quarter notes. + +MMA , being quite literal about things, will make each note exactly +192 MIDI ticks long--which means that the note on beat 2 will start +at the same time as the note on beat 1 ends. + +

    + +MMA has an articulate setting for each voice. This value is applied +to shorten or lengthen the note length. By default, the setting is 90. +Each generated note duration is taken to be a percentage of this +setting, So, a quarter note with a MIDI tick duration of 192 will +become 172 ticks long. + +

    +If articulate is applied to a short note, you are guaranteed that the +note will never be less than 1 MIDI tick in length. + +

    +To set the value, use a line like: + +

    + + + +
    + Chord-1 Articulate 96 + +
    + +

    +Articulate values must be greater than 0 and less than or +equal to 200. Values over 100 will lengthen the note. Settings +greater than 120 will generate a warning. + +

    +You can specify a different ARTICULATE for each bar in a +sequence. Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord Articulate 50 60 / 30 + +
    + +

    +Notes: The full values for the notes are saved with the +pattern definition. The articulation adjustment is applied at +run time. The ARTICULATE setting is saved with a +GROOVE. + +

    + +


    -End - -

    +Copy +

    -A BEGIN must be competed with a END before the end of a -file, otherwise an error will be generated. The USE and -INCLUDE commands are not permitted inside a block. -


    +Sometimes it is useful to duplicate the settings from one voice to +another. The COPY command does just that: + +

    + + + +
    + Bass-1 Copy Bass + +
    + +

    +will copy the settings from the Bass track to the Bass-1 track. + +

    +The COPY command only works between tracks of the same type. + +

    +The following settings are copied: + +

    + +

    + +

    +Warning: You are probably better off to use internal macros for +this. + +

    + +

    +
    +Comment +

    + +

    +As previously discussed, a comment in +MMA is anything following a +``//'' in a line. A second way of marking a comment is with the +COMMENT directive. This is quite useful in combination the +BEGIN and END directives. For example: + +

    + + + +
    + Begin Comment +
        This is a description spanning +
            several lines which will be +
            ignored by MMA. +
    +End
    + +
    + +

    +You could achieve the same with: + +

    + + + +
    + // This is a description spanning +
    // several lines which will be +
    // ignored by MMA.
    + +
    + +

    +or even: + +

    + + + +
    + Comment This is a description spanning +
    +Comment several lines which will be +
    +Comment ignored by MMA.
    + +
    + +

    +One minor difference between // and +COMMENT is that the first is discarded when the +input stream is read; the more verbose version is +discarded during line processing. + +

    +Quite often it is handy to delete large sections of a song with a +BEGIN COMMENT/END on a temporary basis. + +

    + +

    +
    +Debug +

    + +

    +To enable you to find problems in your song files (and, perhaps, even +find problems with +MMA itself) various debugging messages can be +displayed. These are normally set from the command line +command line. + +

    +However, it is possible to enable various debugging messages +dynamically in a song file using the DEBUG directive. In a +debug statement you can enable or disable any of a variety of +messages. A typical directive is: + +

    + + + +
    + Debug Debug=On Expand=Off Patterns=On + +
    + +

    +Each section of the debug directive consists of a mode +and the command word ON or OFF. The two parts +must be joined by a single ``$=$''. You may use the +values ``0'' for ``Off'' and ``1'' for ``On'' if desired. + +

    +The available modes with the equivalent command line switches are: + +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ModeCommand Line Equivalent
    Debug-ddebugging messages
    Filenames-odisplay filenames
    Patterns-ppattern creation
    Sequence-ssequence creation
    Runtime-rrunning progress
    Warnings-wwarning messages
    Expand-edisplay expanded lines
    +
    + +

    +The modes and command are case-insensitive (although the command line switches are not). + +

    +The current state of the debug flags is saved in the variable +$_Debug and the state prior to a change is saved in $_LastDebug. + +

    + +

    +
    +Delete +

    + +

    +If you are using a track in only one part of your song, especially if +it is at the start, it may be wise to free that track's resources when +you are done with it. The DELETE command does just that: + +

    + + + +
    + Solo Delete + +
    + +

    +If a MIDI channel has been assigned to that track, it is +marked as ``available'' and the track is deleted. Any data +already saved in the MIDI track will be written when +MMA is +finished processing the song file. + +

    + +

    +
    +Direction +

    + +

    +In tracks using chords or scales you can change the direction in which +they are applied: + +

    + + + +
    + Scale Direction UP + +
    + +

    +The effects differ in different track types. For SCALE and ARPEGGIO tracks: + +

    +

    + + + + + + + + + + + + + +
    UPPlays in upward direction only
    DOWNPlays in downward direction only
    BOTHPlays upward and downward (default)
    RANDOMPlays notes from the chord or scale randomly
    +
    +

    +

    When this command is encountered in a SCALE track the start +point of the scale is reset. +
    +

    + +

    +A WALK track recognizes the following option settings: + +

    +

    + + + + + + + + + + + + + +
    BOTHThe default. The bass pattern + will go up and down a partial scale. Some notes may be repeated.
    UPNotes will be chosen sequentially from an ascending, partial scale.
    DOWNNotes will be chosen sequentially from a descending, partial scale.
    RANDOMNotes will be chosen in a random direction from a partial scale.
    +
    +

    +

    All four patterns are useful and create quite different effects. + +
    + +

    +The CHORD tracks DIRECTION only has an effect when the +STRUM setting has a non-zero value. In this case the following +applies: + +

    +

    + + + + + + + + + + + + + +
    UPThe default. Notes are sounded from the lowest tone to the highest.
    DOWNNotes are sounded from the highest to the lowest.
    BOTHThe UP and DOWN values are alternated.
    RANDOMIgnored (uses UP).
    +
    + +

    +You can specify a different DIRECTION for each bar in a +sequence. Repeated values can be represented with a ``/'': + +

    + + + +
    + Arpeggio Direction Up Down / Both + +
    + +

    +The setting is ignored by BASS, DRUM and SOLO tracks. + +

    + +

    +Mallet +

    + +

    +Some instruments (Steel-drums, banjos, marimbas, etc.) are normally +played with rapidly repeating notes. Instead of painfully inserting +long lists of these notes, you can use the MALLET directive. +The MALLET directive accepts a number of options, each an +OPTION=VALUE pair. For example: + +

    + + + +
    + Solo-Marimba Mallet Rate=16 Decay=-5 + +
    + +

    +This command is also useful in creating drum rolls. For example: + +

    + + + +
    + Begin Drum-Snare2 +
      Tone SnareDrum1 +
      Volume F +
      Mallet Rate=32 Decay=-3 +
      Rvolume 3 +
      Sequence z z z 1 1 100 +
    +End
    + +
    + +

    +The following options are supported: + +

    + +

    +Rate +

    + +

    +The RATE must be a valid note length (i.e., 8, 16, or even +16.+8). + +

    +For example: + +

    + + + +
    + Solo-Marimba Mallet Rate=16 + +
    + +

    +will set all the notes in the ``Solo-Marimba'' track to be sounded a +series of 16th notes. + +

    + +

      +
    • Note duration modifiers such as articulate are applied to each + resultant note, + +

      +

    • +
    • It is guaranteed that the note will sound at least once, + +

      +

    • +
    • The use of note lengths assures a consistent sound independent + of the song tempo. + +

      +

    • +
    + +

    +To disable this setting use a value of ``0''. + +

    + +

    +Decay +

    + +

    +You can adjust the volume (velocity) of the notes being repeated when +MALLET is enabled: + +

    + + + +
    + Drum-Snare Mallet Decay=-15 + +
    + +

    +The argument is a percentage of the current value to add to the note +each time it is struck. In this example, assuming that the note length +calls for 4 ``strikes'' and the initial velocity is 100, the note will +be struck with a velocity of 100, 85, 73 and 63. + +

    +Important: a positive value will cause the notes to get louder, +negative values cause the notes to get softer. + +

    +Note velocities will never go below 1 or above 255. Note, however, +that notes with a velocity of 1 will most likely be inaudible. + +

    +The decay option value must be in the range -50 to 50; however, be +cautious using any values outside the range -5 to 5 since the volume +(velocity) of the notes will change quite quickly. The default +value is 0 (no decay). + +

    + +

    +
    +Octave +

    + +

    +When +MMA initializes and after the SEQCLEAR command all track +octaves are set to ``4''. This will place most chord and bass notes in +the region of middle C. + +

    +You can change the octave for any voice with OCTAVE command. For example: + +

    + + + +
    + Bass-1 Octave 3 + +
    + +

    +Sets the notes used in the ``Bass-1'' track one octave lower than normal. + +

    +The octave specification can be any value from 0 to 10. Various +combinations of INVERT, TRANSPOSE and OCTAVE can +force notes to be out of the valid MIDI range. In this case the lowest +or highest available note will be used. + +

    +You can specify a different OCTAVE for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord Octave 4 5 / 4 + +
    + +

    + +

    +
    +Off +

    + +

    +To disable the generation of MIDI output on a specific track: + +

    + + + +
    + Bass Off + +
    + +

    +This can be used anywhere in a file. Use it to override the effect of +a predefined groove, if you wish. This is simpler than resetting a +voice in a groove. The only way to reset this command is with a +ON directive. + +

    + +

    +
    +On +

    + +

    +To enable the generation of MIDI output on a specific track which has +been disabled with an OFF directive: + +

    + + + +
    + Bass On + +
    + +

    + +

    +Print +

    + +

    +The PRINT directive will display its argument to the screen +when it is encountered. For example, if you want to print the filename +of the input file while processing, you could insert: + +

    + + + +
    + Print Making beautiful music for MY SONG + +
    + +

    +No control characters are supported. + +

    +This can be useful in debugging input files. + +

    + +

    +PrintActive +

    + +

    +The PRINTACTIVE directive will the currently active +GROOVE and the active tracks. This can be quite useful when +writing groove files and you want to modify and existing groove. + +

    +Any parameters given are printed as single comment at the end of the header line. + +

    +This is strictly a debugging tool. No PRINTACTIVE statements +should appear in finalized grooves or song files. + +

    + +

    +RndSeed +

    + +

    +All of the random functions (RTIME, RSKIP, etc.) in +MMA depend +on the Python random module. Each time +MMA generates a track the values generated +by the random functions will be different. In most cases this is a ``good thing''; however, +you may want +MMA to use the same sequence of random values21.1 each time it generates a track. Simple: just use: + +

    + + + +
    + RndSeed 123.56 + +
    + +

    +at the top of your song file. You can use any value you want: it really doesn't +make any difference, but different values will generate different sequences. + +

    +You can also use this with no value, in which case Python uses its own value (see +the Python manual for details). Essentially, using no value undoes the effect which +permits the mixing of random and not-so-random sections in the same song. + +

    +One interesting use of RNDSEED could be to ensure that a repeated section +is identical: simply start the section with something like: + +

    + + + +
    + Repeat +
    +RndSeed 8 +
    ... chords
    + +
    + +

    +It is highly recommended that you do not use this command in library files. + +

    + +

    +
    +RSkip +

    + +

    +To aid in creating syncopated sounding patterns, you can use the +RSKIP directive to randomly silence or skip notes. The command +takes a value in the range 0 to 99. The ``0'' argument disables +skipping. For example: + +

    + + + +
    + Begin Drum +
        Define D1 1 0 90 +
        Define D8 D1 * 8 +
        Sequence D8 +
        Tone OpenHiHat +
        RSkip 40 +
    +End
    + +
    + +

    +In this case a drum pattern has been defined to hit short ``OpenHiHat'' +notes 8 per bar. The RSKIP argument of ``40'' causes the +note to be NOT sounded (randomly) only 40% of the time. + +

    +Using a value of ``10'' will cause notes to be skipped 10% of the +time (they are played 90% of the time), ``90'' means to skip the +notes 90% of the time, etc. + +

    +You can specify a different RSKIP for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Scale RSkip 40 90 / 40 + +
    + +

    +If you use the RSKIP in a chord track, the entire chord +will not be silenced. The option will be applied to the +individual notes of each chord. This may or may not be what you are +after. You cannot use this option to generate entire chords randomly. +For this effect you need to create several chord patterns and select +them with SEQRND. + +

    + +

    +
    +RTime +

    + +

    +One of the biggest problem with computer generated drum and rhythm +tracks is that, unlike real musicians, the beats are precise and ``on +the beat''. The RTIME directive attempts to solve this. + +

    +The command can be applied to all tracks. + +

    + + + +
    + Drum-4 Rtime 4 + +
    + +

    +The value passed to the RTime directive are the number of MIDI ticks +with which to vary the start time of the notes. For example, if you +specify ``5'' the start times will vary from -5 to +5 ticks) on each +note for the specified track. There are 192 MIDI ticks in each quarter +note. + +

    +Any value from 0 to 100 can be used; however values in the range 0 to +10 are most commonly used. Exercise caution in using large values! + +

    +You can specify a different RTIME for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord RTime 4 10 / 4 + +
    + +

    +RTIME is guaranteed never to start a note before the start of a bar. + +

    + +

    +
    +ScaleType +

    + +

    +This option is only used by SCALE tracks. It can be set for +other tracks, but the setting is not used. + +

    +By default, the SCALETYPE is set to AUTO. The settings +permissible are: + +

    +

    + + + + + + + +
    CHROMATICForces use of a chromatic scale
    AUTOUses scale based on the current chord (default)
    +
    + +

    +When this command is encountered in a SCALE track the start +point of the scale is reset. + +

    + +

    + +
    +Seq +

    + +

    +If your sequence, or groove, has more than one pattern (i.e., you have +set SeqSize to a value other than 1), you can use this directive to +force a particular pattern point to be used. The directive: + +

    + + + +
    + Seq + +
    + +

    +resets the sequence counter to 1. This means that the next bar +will use the first pattern in the current sequence. You can force a +specific pattern point by using an optional value after the directive. +For example: + +

    + + + +
    + Seq 8 + +
    + +

    +forces the use of pattern point 8 for the next bar. This can be quite +useful if you have a multi-bar sequence and, perhaps, the eight bar is +variation which you want used every eight bars, but also for a +transition bar, or the final bar. Just put a SEQ 8 at those +points. You might also want to put a SEQ at the start of +sections to force the restart of the count. + +

    +If you have enable sequence randomization with the SEQRND ON +command, the randomization will be disabled by a SEQ +command.21.2 However, +settings of track SEQRND will not be effected. One difference +between SEQRND OFF and SEQ is that the current sequence +point is set with the latter; with SEQRND OFF it is left at a +random point. + +

    +Note: Using a value greater than the current SEQSIZE is not +permitted. + +

    +This is a very useful command! For example, look at the four bar +introduction of the song ``Exactly Like You'': + +

    + + + +
    + Groove BossanovaEnd +
    +seq 3 +
    +1 C +
    +seq 2 +
    +2 Am7 +
    +seq 1 +
    +3 Dm7 +
    +seq 3 +
    +4 G7 / G7#5
    + +
    + +

    +In this example the four bar ``ending groove'' has been used to create +an interesting introduction. + +

    + +

    +
    +Strum +

    + +

    +By default +MMA plays all the notes in a chord at the same time. To +make the chord more like something a guitar or banjo might play, use +the STRUM directive. For example: + +

    + + + +
    + Chord-1 Strum 5 + +
    + +

    +sets the strumming factor to 5 for track Chord-1. + +

    +Setting the STRUM in any track other than a CHORD track +will generate a warning message and the command will be ignored. + +

    +The strum factor is specified in MIDI ticks. Usually values around 10 +to 15 work just fine. The valid range for STRUM is 0 to 100. + +

    +You can specify a different STRUM for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord Strum 20 5 / 10 + +
    + +

    +Note: When chords have both a STRUM and INVERT applied, +the order of the notes played will not necessarily be root, third, +etc. The notes are sorted into ascending order, so for a C major scale +with and INVERT of 1 the notes played would be ``E G C''. That +is, unless the DIRECTION has been set to ``DOWN'' in which case +the order would be reversed (but the notes would be the same). + +

    + +

    +Transpose +

    + +

    +You can change the key of a piece with the ``Transpose'' command. For +example, if you have a piece notated in the key of ``C'' and you want +it played back in the key of ``D'': + +

    + + + +
    + Transpose 2 + +
    + +

    +will raise the playback by 2 semi-tones. Since +MMA 's author plays tenor saxophone + +

    + + + +
    + Transpose -2 + +
    + +

    +which puts the MIDI keyboard into the same key as the horn, is not an +uncommon directive + +

    +You can use any value between -12 and 12. All tracks (with the logical +exception of the drum tracks) are effected by this command. + +

    + +

    +Unify +

    + +

    +The UNIFY command is used to force multiple notes of the same +voice and pitch to be combined into a single, long, tone. This is very +useful when creating a sustained voice track. For example, consider +the following which might be used in real groove file: + +

    + + + +
    + Begin Bass-Sus +
    +Sequence 1 1 1 90 4 +
    +Articulate 100 +
    +Unify On +
    +Voice TremoloStrings +
    +End
    + +
    + +

    +Without the UNIFY ON command the strings would be sounded (or +hit) four times during each bar; with it enabled the four hits are +combined into one long tone. This tone can span several bars if the +note(s) remain the same. + +

    +The use of this command depends on a number of items: + +

    + +

      +
    • The VOICE being used. It makes sense to use enable the + setting if using a sustained tone like ``Strings"; it probably + doesn't make sense if using a tone like ``Piano1''. + +

      +

    • +
    • For tones to be combined you will need to have ARTICULATE + set to a value of 100. Otherwise the on/off events will have small + gaps in them which will cancel the effects of UNIFY. + +

      +

    • +
    • Ensure that RTIME is not set for UNIFY tracks + since the start times may cause gaps. + +

      +

    • +
    • If your pattern or sequence has different volumes in different + beats (or bars) the effect of a UNIFY will be to ignore + volumes other than the first. Only the first NOTE ON and the + last NOTE OFF events will appear in the MIDI file. + +

      +

    • +
    + +

    +You can specify a different UNIFY for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord Unify On / / Off + +
    + +

    +But, you probably don't want to use this particular feature. + +

    +Valid arguments are ``On'' or ``1'' to enable; ``Off'' or ``0'' to +disable. + +

    + +

    +
    +Voice +

    + +

    +The MIDI instrument or voice used for a track is set with: + +

    + + + +
    + Chord-2 Voice Piano1 + +
    + +

    +Voices apply only to the specified track. The actual instrument can be +specified via the MIDI instrument number, or with the symbolic name. +See the tables in the MIDI voicing section for lists of the recognized +names. + +

    +You can create interesting effects by varying the voice used with drum +tracks. By default ``Voice 0'' is used. However, you can change the +drum voices. The supplied library files do not change the voices since this +appears to be highly dependent on the MIDI synth you are using. + +

    +You can specify a different VOICE for each bar in a sequence. +Repeated values can be represented with a ``/'': + +

    + + + +
    + Chord Voice Piano1 / / Piano2 + +
    + +

    +It is possible to set up translations for the selected voice: see +VOICETR. + +

    +


    Footnotes

    +
    +
    ... values21.1
    +
    Yes, this is +a contradiction of terms. + +
    +
    ... +command.21.2
    +
    A warning message will also be displayed. + +
    +

    - next - up - previous
    - Next: Documentation Strings - Up: Next: Begin/End Blocks + Up: Reference Manual - Previous: Other Commands and Directives + Previous: Fine Tuning (Translations)
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node22.html b/mma/docs/html/ref/node22.html index a7c9e8d..b3ba144 100644 --- a/mma/docs/html/ref/node22.html +++ b/mma/docs/html/ref/node22.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Documentation Strings - +Begin/End Blocks + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Paths, Files and Libraries - Up: Next: Documentation Strings + Up: Reference Manual - Previous: Begin/End Blocks + Previous: Other Commands and Directives

    @@ -49,130 +49,162 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections
    -

    -Documentation Strings -

    - -

    -It has been mentioned a few times already the importance of clearly -documenting your files and library files. For the most part, you can -use comments in your files; but in library files you use the -DOC directive. - -

    -In addition to the commands listed in this chapter, you should also -note DEFGROOVES). - -

    -For some real-life examples of how to document your library files, -look at any of the library files supplied with this distribution. - -

    - -

    +

    +
    -Doc +Begin/End Blocks

    -A DOC command is pretty simple: +Entering a series of directives for a specific track can get quite +tedious. To make the creation of library files a bit easier, you can +create a block. For example, the following:

    - - +
    + + +
    + Drum Define X 0 2 100; 50 2 90 +
    +Drum Define Y 0 2 100 +
    +Drum Sequence X Y
    -
    Doc This is a documentation string!
    +
    + +

    +Can be replaced with: + +

    + + +
    + Drum Begin +
        Define X 0 2 100; 50 2 90 +
        Define Y 0 2 100 + End +
    +Drum Sequence X Y
    -
    +

    -In most cases, DOCs are treated as COMMENTs. However, -if the -Dx22.1 option is given -on the command line, DOCs are processed and printed to standard -output. - -

    -For producing the -MMA Standard Library Reference a trivial -Python program is used to collate the output generated with a command -like: +Or, even more simply, with:

    - - +
    + +
    + Drum Begin Define +
        X 0 2 100; 50 2 90 +
        Y 0 2 100 +
    +End
    -
    $ mma -Dx -w /usr/local/lib/mma/swing
    - -
    +

    -Note, the '-w' option has been used to suppress the printing of warning -messages. +If you examine some of the library files you will see that this +shortcut is used a lot. + +

    + +

    +Begin +

    + +

    +The BEGIN command requires any number of arguments. Valid +examples include: + +

    + + + +
    + Begin Drum +
    +Begin Chord2 +
    +Begin Walk Define
    + +
    + +

    +Once a BEGIN block has been entered, all subsequent lines have +the words from the BEGIN command prepended to each line of +data. There is not much magic here--BEGIN/END is really +just some syntactic sugar.

    -Author +End

    -As part of the documentation package, there is a AUTHOR -command: +To finish off a BEGIN block, use a single END on a line +by itself. + +

    +Defining musical data, repeats, or other BEGINs inside a block +(other than COMMENT blocks) will not work. + +

    +Nesting is permitted. Eg:

    - - +
    + +
    + Scale Begin +
        Begin Define +
            
    stuff +
        End +
        Sequence
    stuff +
    +End
    -
    Author Bob van der Poel
    - -
    +

    -Currently AUTHOR lines are processed and the data is saved, but -never used. It may be used in a future library documentation -procedures, so you should use it in any library files you write. -


    Footnotes

    -
    -
    ...-Dx22.1
    -
    See the command - summary. - -
    -

    +A BEGIN must be competed with a END before the end of a +file, otherwise an error will be generated. The USE and +INCLUDE commands are not permitted inside a block. +
    - next - up - previous
    - Next: Paths, Files and Libraries - Up: Next: Documentation Strings + Up: Reference Manual - Previous: Begin/End Blocks + Previous: Other Commands and Directives
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node23.html b/mma/docs/html/ref/node23.html index 159cca5..3a758ab 100644 --- a/mma/docs/html/ref/node23.html +++ b/mma/docs/html/ref/node23.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Paths, Files and Libraries - +Documentation Strings + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Creating Effects - Up: Next: Paths, Files and Libraries + Up: Reference Manual - Previous: Documentation Strings + Previous: Begin/End Blocks

    @@ -49,1053 +49,180 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections
    -

    - -
    -Paths, Files and Libraries +

    +Documentation Strings

    -This chapter covers -MMA filenames, extensions and a variety of -commands and/or directives which effect the way in which files are -read and processed. +It has been mentioned a few times already the importance of clearly +documenting your files and library files. For the most part, you can +use comments in your files; but in library files you use the +DOC directive.

    -But, first a few comments on the location of the -MMA Python modules. +In addition to the commands listed in this chapter, you should also +note DEFGROOVES).

    -The Python language (which was used to write -MMA ) has a very useful -feature: it can include other files and refer to functions and data -defined in these files. A large number of these files or modules are -included in every Python distribution. The program -MMA consists of a -short ``main'' program and several ``module'' files. Without these -additional modules -MMA will not work. - -

    -The only sticky problem in a program intended for a wider audience is -where to place these modules. Hopefully, it is a ``good thing'' that -they should be in one of three locations: +For some real-life examples of how to document your library files, +look at any of the library files supplied with this distribution.

    -

      -
    • /usr/local/share/mma/MMA - -

      -

    • -
    • /usr/share/mma/MMA - -

      -

    • -
    • ./MMA - -

      -

    • -
    - -

    -If, when initializing itself, -MMA cannot find one of the above -directories, it will terminate with an error message. - -

    -If you are using -MMA on a Windows platform please see the comments about -the default paths (here). - -

    - -

    +


    -File Extensions +Doc

    -For most files the use of a the filename extension ``.mma'' is -optional. However, it is suggested that most files (with the exceptions -listed below) have the extension present. It makes it much easier to -identify -MMA song and library files and to do selective processing -on these files. - -

    -In processing an input song file -MMA can encounter several different -types of input files. For all files, the initial search is done by -adding the filename extension ``.mma'' to filename (unless it is -already present), then a search for the file as given is done. - -

    -For files included with the USE directive, the directory set -with SETLIBPATH is first checked, followed by the current -directory. - -

    -For files included with the INCLUDE directive, the directory -set with SETINCPATH is first checked, followed by the current -directory. - -

    -Following is a summary of the different files supported: - -

    -

    -
    Song Files
    -
    The input file specified on the command line should - always be named with the ``.mma'' extension. When -MMA searches for - the file it will automatically add the extension if the file name - specified does not exist and doesn't have the extension. - -

    -

    -
    Library Files
    -
    Library files really should all be named - with the extension. -MMA will find non-extension names when used in - a USE or INCLUDE directive. However, it will not - process these files when creating indexes with the ``-g'' command - line option--these index files are used by the GROOVE - commands to automatically find and include libraries. - -

    -

    -
    RC Files
    -
    As noted in the RC-File discussion - (here) -MMA will - automatically include a variety of ``RC'' files. You can use the - extension on these files, but common usage suggests that these files - are probably better without. - -

    -

    -
    MMAstart and MMAend
    -
    -MMA will automatically include a file at - the beginning or end of processing (start/end - details). Typically these files are - named MMASTART and MMAEND. Common usage is to - not use the extension if the file is in the current - directory; use the file if it is in an ``includes'' directory. - -

    -

    -
    - -

    -One further point to remember is that filenames specified on the -command line are subject to wild-card expansion via the shell you are -using. +A DOC command is pretty simple:

    -

    -Tilde Expansion -

    - -

    -On Unix-like systems all filenames may be prefaced with tilde or a -tilde with a username. All file operations in -MMA honor this -convention. This includes the setting of library and include paths. - -

    -The result of this operation is system dependent. See the entry for -os.path.expanduser in the Python library reference. - -

    - -

    -Eof -

    - -

    -Normally, a file is processed until its end. However, you can -short-circuit this behavior with the EOF directive. If -MMA finds a line starting with EOF no further processing will be -done on that file ... it's just as if the real end of file was -encountered. Anything on the same line, after the EOF is also -discarded. - -

    -You may find this handy if you want to test process only a part of a -file, or if you making large edits to a library file. It is often used -to quit when using the LABEL and GOTO directives to -simulate constructs like D.C. al Coda, etc. - -

    - -

    -
    -LibPath -

    - -

    -The search for library files can be set with the LibPath variable. To -set LIBPATH: - -

    - - - +
    + +
    + Doc This is a documentation string! -
    SetLibPath PATH
    - -
    +

    -You can have only one path in the SETLIBPATH directive. +In most cases, DOCs are treated as COMMENTs. However, +if the -Dx23.1 option is given +on the command line, DOCs are processed and printed to standard +output.

    -When -MMA starts up it sets the library path to the first valid -directory in the list: - -

    - -

      -
    • /usr/local/share/mma/lib - -

      -

    • -
    • /usr/share/mma/lib - -

      -

    • -
    • ./lib - -

      -

    • -
    - -

    -The last choice lets you run -MMA directly from the distribution -directory. - -

    -You are free to change this to any other location in a -RCFile. - -

    -LIBPATH is used by the routine which auto-loads grooves from -the library, and the USE directive. The -g command line option -is used to maintain the library database). - -

    -The current setting can be accessed via the macro $_LibPath. - -

    - -

    -AutoLibPath -

    - -

    -The sub-directory containing the current library files to automatically -load is determined by the current setting of AUTOLIBPATH. -Please see the library file discussion here for details. - -

    -You can change the automatic include directory by resetting this -variable. It must be a sub-directory of LIBPATH for it to work. - -

    -The command to reset the variable is: - -

    - - -
    - -
    SetAutoLibPath mydir
    - -
    - -

    -The current setting can be accessed via the macro $_AutoLibPath. By -default the setting is ``stdlib''. - -

    -Any existing GROOVE definitions are deleted from memory when -this command is issued (this it to avoid name conflicts between libraries). - -

    - -

    -
    -OutPath -

    - -

    -MIDI file generation is to an automatically generated filename -(more details). If the -OUTPATH variable is set, that value will be prepended to the -output filename. To set the value: - -

    - - -
    - -
    SetOutPath PATH
    - -
    - -

    -Just make sure that ``PATH'' is a simple path name with no -spaces in it. The variable is case sensitive (assuming that your -operating system supports case sensitive filenames). This is a common -directive in a RC file (more details). By default, it has no value. - -

    -You can disable the OUTPATH variable quite simply: just issue -the command without an argument. - -

    -If the name set by this command begins with a ``.'', ``/'' or -`` \'' it is prepended to the complete filename specified on -the command line. For example, if you have the input filename -test.mma and the output path is -~/mids ---the output file will be /home/bob/mids/test.mid. - -

    -If the name doesn't start with the special characters noted in the -preceding paragraph the contents of the path will be inserted before -the filename portion of the input filename. Again, an example: the -input filename is mma/rock/crying and the output path is -``midi''--the output file will be mma/rock/midi/crying.mid. - -

    -The current setting can be accessed via the macro $_OutPath. - -

    -Note that this option is ignored if you use the -f - command line option or -if an absolute name for the input file (one starting with a ``/'' or - a ``~'') is used. - -

    - -

    -Include -

    - -

    -Other files with sequence, pattern or music data can be included at -any point in your input file. There is no limit to the level of -includes. - -

    - - -
    - -
    Include Filename
    - -
    - -

    -A search for the file is done in the INCPATH directory (see -below) and the current directory. The ``.mma'' filename extension is -optional (if a filename exists both with and without the ``.mma'' -extension, the file with the extension will be used). - -

    -The use of this command should be quite rare in user files; however, -it is used extensively in library files to include standard -patterns. - -

    - -

    -
    -IncPath -

    - -

    -The search for include files can be set with the INCPATH -variable. To set INCPATH: - -

    - - -
    - -
    SetIncPath PATH
    - -
    - -

    -You can have only one path in the SETINCPATH directive. - -

    -When -MMA initializes it sets the include path to first found directory in: - -

    - -

      -
    • /usr/local/share/mma/includes -
    • -
    • /usr/share/mma/includes -
    • -
    • ./includes - -

      -

    • -
    - -

    -The last location lets you run -MMA from the distribution directory. - -

    -If this value is not appropriate for your system, you are free to -change it in a RC File. - -

    -The current setting can be accessed via the macro $_IncPath. - -

    - -

    -
    -Use -

    - -

    -Similar to INCLUDE, but a bit more useful. The USE -command is used to include library files and their predefined grooves. - -

    -Compared to INCLUDE, USE has important features: - -

    - -

      -
    • The search for the file is done in the paths specified by the LibPath variable, - -

      -

    • -
    • The current state of the program is saved before the library - file is read and restored when the operation is complete. - -

      -

    • -
    - -

    -Let's examine each feature in a bit more detail. - -

    -When a USE directive is issued, eg: - -

    - - -
    - -
    use stdlib/swing
    - -
    - -

    - -MMA first attempts to locate the file ``stdlib/swing'' in the -directory specified by LIBPATH or the current directory. As -mentioned above, -MMA automatically added the ``.mma'' extension to -the file and checks for the non-extension filename if that can't be -found. - -

    -If things aren't working out quite right, check to see if the filename -is correct. Problems you can encounter include: - -

    - -

      -
    • Search order: you might be expecting the file in the current - directory to be used, but the same filename exists in the - LIBPATH, in which case that file is used. - -

      -

    • -
    • Not using extensions: Remember that files with the - extension added are first checked. - -

      -

    • -
    • Case: The filename is case sensitive. The files ``Swing'' - and ``swing'' are not the same. Since most things in -MMA are case - insensitive, this can be an easy mistake to make. - -

      -

    • -
    • The file is in a sub directory of the LIBPATH. In a - standard distribution the actual library files are in - /usr/local/share/mma/lib/stdlib, but the libpath is set to - /usr/local/share/mma/lib. In this case you must name the file - to be used as stdlib/rhumba not rhumba. - -

      -

    • -
    - -

    -As mentioned above, the current state of the compiler is saved during -a USE. -MMA accomplishes this by issuing a slightly modified -DEFGROOVE and GROOVE command before and after the -reading of the file. Please note that INCLUDE doesn't do this. -But, don't let this feature fool you--since the effects of defining -grooves are cumulative you really should have SEQCLEAR -statements at the top of all your library files. If you don't you'll -end up with unwanted tracks in the grooves you are defining. - -

    -In most cases you will not need to use the USE directive - in your music files. If you have properly installed -MMA and keep -the database up-to-date by using the command: - -

    - - -
    - -
    $ mma -g
    - -
    - -

    -grooves from library files will be automatically found and loaded. -Internally, the USE directive is used, so existing states are -saved. - -

    -If you are developing new or alternate library files you will find the -USE directive handy. - -

    - -

    -
    -MmaStart -

    - -

    -If you wish to process a certain file or files before your main input -file, set the MMASTART filename in an RCFile. For example, you -might have a number of files in a directory which you wish to use -certain PAN settings. In that directory, you just need to have -a file mmarc which contains the following command: - -

    - - -
    - -
    MmaStart setpan
    - -
    - -

    -The actual file setpan has the following directives: - -

    - - -
    - -
    Bass Pan 0 -
    -Bass1 Pan 0 -
    -Bass2 Pan 0 -
    -Walk Pan 0 -
    -Walk1 Pan 0 -
    -Walk2 Pan 0
    - -
    - -

    -So, before each file in that directory is processed, the PAN -for the bass and walking bass voices are set to the left channel. - -

    -If the file specified by a MMASTART directive does not exist a -warning message will be printed (this is not an error). - -

    -Also useful is the ability to include a generic file with all the MIDI -files you create. For example, you might like to have a MIDI reset at the -start of your files--simple, just include the following in your mmarc file: - -

    - - -
    - -
    MMAstart reset
    - -
    - -

    -This includes the file reset.mma located in the ``includes'' -directory (IncludePath). - -

    -Multiple MMASTART directives are permitted. The files are -processed in the order declared. You can have multiple filenames on a -MMASTART line. - -

    -One caution with MMASTART files: the file is processed after -the RC file, just before the actual song file. - -

    - -

    -
    -MmaEnd -

    - -

    -Just the opposite of MMASTART, this command specifies a file to -be included at the end of a main input file. See the comments above -for more details. - -

    -To continue this example, in your mmarc file you would have: - -

    - - -
    - -
    MmaEnd nopan
    - -
    - -

    -and in the file nopan have: - -

    - - -
    - -
    Bass Pan 64 -
    -Bass1 Pan 64 -
    -Bass2 Pan 64 -
    -Walk Pan 64 -
    -Walk1 Pan 64 -
    -Walk2 Pan 64
    - -
    - -

    -If the file specified by a MMAEND directive does not exist a -warning message will be printed (this is not an error). - -

    -Multiple MMAEND directives are permitted and processed in the -order declared. You can have multiple filenames on a MMAEND line. - -

    - -

    - -
    -RC Files -

    - -

    -When -MMA starts it checks for initialization files. Only the first -found file is processed. The following locations/files are checked (in order): - -

    - -

      -
    1. mmarc -- this is a normal file in the current directory. - -

      -

    2. -
    3. ~/.mmarc -- this is an ``invisible'' file in the users - home directory. - -

      -

    4. -
    5. /usr/local/etc/mmarc - -

      -

    6. -
    7. /etc/mmarc - -

      -

    8. -
    - -

    - Only the first found file will be processed. This means you can -override a ``global'' RC file with a user specific one. If you just -want to override some specific commands you might want to: - -

    - -

      -
    1. Create the file mmarc in a directory with -MMA files, - -

      -

    2. -
    3. As the first line in that file have the command: - -

      - - -
      - -
      include ~/.mmarc
      - -
      - -

      -to force the inclusion of your global stuff, - -

      -

    4. -
    5. Now, place your directory specific commands in your custom RC file. -
    6. -
    - -

    -By default, no RC files are installed. You may want to create an empty -~/.mmarc file to eliminate a warning message. - -

    -An alternate method for using a different RC file is to specify the -name of the file on the command line by using the -i option -(here). Using this option -you can have several RC files in a directory and complile your songs -differently depending on the RC file you specify. - -

    -The RC file is processed as a -MMA input file. As such, it can -contain anything a normal input file can, including music commands. -However, you should limit the contents of RC files to things +For producing the +MMA Standard Library Reference a trivial +Python program is used to collate the output generated with a command like:

    - - +
    + +
    + $ mma -Dxl -w /usr/local/lib/mma/swing -
    SetOutPath -
    -SetLibPath -
    -MMAStart -
    -MMAEnd
    - -
    +

    -A useful setup is to have your source files in one directory and MIDI -files saved into a different directory. Having the file mmarc -in the directory with the source files permits setting OUTPATH -to the MIDI path. +Note, the '-w' option has been used to suppress the printing of warning +messages.

    -

    -
    -Library Files +

    +Author

    -Included in this distribution are a number of predefined patterns, -sequences and grooves. They are in different files in the ``lib'' -directory. - -

    -The library files should be self-documenting. A list of standard file -and the grooves they define is included in the separate document, -supplied in this distribution as ``mma-lib.ps''. +As part of the documentation package, there is a AUTHOR +command:

    -

    -
    -Maintaining and Using Libraries -

    - -

    -The basic -MMA distribution comes with a set of pattern files which -are installed in the mma/lib/stdlib directory. Each one of -these files has a number of GROOVEs defined in them. For -example, the file mma/lib/stdlib/rhumba.mma contains the -grooves Rhumba, RhumbaEnd and many more. - -

    -If you are writing GROOVEs with the intention of adding them to -the standard library you should ensure that none of the names you -choose duplicate existing names already used. - -

    -If you are creating a set of alternate grooves to duplicate the -existing library you might do the following: - -

    - -

      -
    1. Create a directory with your name or other short id in the - mma/lib/ hierarchy. For example, if your name is ``Bob van - der Poel'' you might create the directory mma/lib/bvdp. - -

      -

    2. -
    3. Place all your files (or modified files) in that directory. - -

      -

    4. -
    5. Now, when your song wants to use a groove, you have two choices: - -

      - -

        -
      1. Include the file with the USE directive. For example, - if you have created the file rock.mma and want to use the - GROOVE rock8 you would: - -

        - -

          -
        1. place the directive USE BVDP/ROCK near the top of the - song file. Note: it might not be apparent from the typeface here, but the - filename here is all lowercase. In Unix/Linux case is important, so - please make sure of the case of the filenames in commands like USE. - -

          -

        2. -
        3. enable the groove with the directive GROOVE ROCK8 (and here the - case is not important since -MMA thinks that upper and lower case are the same). - -

          -

        4. -
        - -

        -

      2. -
      3. Force -MMA to use your groove directory by resetting - the auto-lib directory (again, the case for the path is important): - -

        - - - +
        + +
        + Author Bob van der Poel -
        SetAutoLibPath bvdp
        - -
        +

        -You will have to update the -MMA database with the -g or -G - command line options for this to work. If you elect this route, - please note that the files in the standard library will not be - available, but you can use both with something like this: +Currently AUTHOR lines are processed and the data is saved, but +never used. It may be used in a future library documentation +procedures, so you should use it in any library files you write.

        - -
        - -
        Groove Metronome2-4 -
        -z * 2 -
        -SetAutoLibPath bvdp -
        -Groove BossaNova // the bossa from lib/bvdp, not stdlib! -
        -chords...
        - -
        - -

        -The nice thing about this method is that you can have multiple - sets of library files all using the same GROOVE - names. To create a different version you just need to change - the SETAUTOLIBPATH variable in your song file ...or, - for a collection of songs put the variable in your MMARC - file. - -

        -

      4. -
      - -

      -

    6. -
    - -

    -For those who ``really need to know'', here are the steps that -MMA takes when it encounters a GROOVE command: - -

    - -

      -
    1. if the named groove has been loaded/created already -MMA just - switches to the internal version of that groove. - -

      -

    2. -
    3. if the groove can't be found in memory, a search of the groove - database (created with the -g command line option) is done. If no - database is in memory it is loaded from the directory pointed to by - the LIBPATH and AUTOLIBPATH variables. This database - is then searched for the needed GROOVE. The database contains - the filenames associated with each GROOVE and that file is - then read with the USE code. - -

      -

    4. -
    - -

    -The database is a file .mmaDB stored in each sub directory of -LIBPATH. This is a ``hidden'' file (due to the leading ``.'' in -the filename). You cannot change the name of this file. If there are -sub-directories the entries for them will be stored in the database -file for the main tree. - -

    -By using a USE directive or by resetting AUTOLIBDIR you -force the loading of your set of grooves. - -

    - -

    - -
    -Paths on Windows Platforms +

    +DocVar

    -To make -MMA as platform independent as possible a number of additional paths have been -defined. When starting up, in addition to the standard Linux paths discussed above, the -following are also checked: +If any variables are used to change the behavior of a library file +they should be documented with a DOCVAR command. Normally these +lines are treated as comments, but when processing with the -Dxl or +-Dxh command line options the data is parsed and written to the output +documentation files. + +

    +Assuming that you are using the +MMA variable $CHORDVOICE as +an optional voice setting in your file, you might have the following +in a library file:

    -

      -
    • Modules can be in c: + + +
      + Begin DocVar
      -mma
      , - -
    • Include files can be in c: +ChordVoice Voice used in Chord tracks (defaults to Piano2).
      -mma +End +

      -includes
      , -
    • -
    • Library files can be in c: +If NDef ChordVoice
      -mma +Set ChordVoice Piano2
      -lib
      . +Endif + +
    • -

    • -
    +All variables used in the library file should be documented. You +should list the user variables first, and then any variables internal +to the library file. To double check to see what variables are used +you can add a SHOWVARS to the end of the library file and +compile. Then document the variables and remove the SHOWVARS.

    -


    +

    Footnotes

    +
    +
    ...-Dx23.1
    +
    See the command + summary. + +
    +

    - next - up - previous
    - Next: Creating Effects - Up: Next:
    Paths, Files and Libraries + Up: Reference Manual - Previous: Documentation Strings + Previous: Begin/End Blocks
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node24.html b/mma/docs/html/ref/node24.html index fed3c8e..039828a 100644 --- a/mma/docs/html/ref/node24.html +++ b/mma/docs/html/ref/node24.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Creating Effects - +Paths, Files and Libraries + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Frequency Asked Questions - Up: Next: Creating Effects + Up: Reference Manual - Previous: Paths, Files and Libraries + Previous: Documentation Strings

    @@ -49,168 +49,1053 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

    - +
    -Creating Effects +Paths, Files and Libraries

    -It's really quite amazing how easy and effective it is to create -different patterns, sequences and special effects. As -MMA was -developed lots of silly things were tried...this chapter is an -attempt to display and preserve some of them. +This chapter covers +MMA filenames, extensions and a variety of +commands and/or directives which effect the way in which files are +read and processed.

    -The examples don't show any music to apply the patterns or sequences -to. The manual assumes that if you've read this far you'll know -that you should have something like: +But, first a few comments on the location of the +MMA Python modules. + +

    +The Python language (which was used to write +MMA ) has a very useful +feature: it can include other files and refer to functions and data +defined in these files. A large number of these files or modules are +included in every Python distribution. The program +MMA consists of a +short ``main'' program and several ``module'' files. Without these +additional modules +MMA will not work. + +

    +The only sticky problem in a program intended for a wider audience is +where to place these modules. Hopefully, it is a ``good thing'' that +they should be in one of three locations:

    - -
    - -
    1 C +
      +
    • /usr/local/share/mma/MMA + +

      +

    • +
    • /usr/share/mma/MMA + +

      +

    • +
    • ./MMA + +

      +

    • +
    + +

    +If, when initializing itself, +MMA cannot find one of the above +directories, it will terminate with an error message. + +

    +If you are using +MMA on a Windows platform please see the comments about +the default paths (here). + +

    + +


    -2 G -
    -3 G -
    -4 C

    - -
    - -

    -as a simple test piece to apply tests to. - -

    - -

    -Overlapping Notes +File Extensions

    -As a general rule, you should not create patterns in which notes -overlap. However, here's an interesting effect which relies on -ignoring that rule: +For most files the use of a the filename extension ``.mma'' is +optional. However, it is suggested that most files (with the exceptions +listed below) have the extension present. It makes it much easier to +identify +MMA song and library files and to do selective processing +on these files.

    - - -
    - -
    Begin Scale -
        define S1 1 1+1+1+1 90 -
        define S32 S1 * 32 -
        Sequence S32 -
        ScaleType -
        Direction Both -
        Voice Accordion -
        Octave 5 -
    -End
    - -
    +In processing an input song file +MMA can encounter several different +types of input files. For all files, the initial search is done by +adding the filename extension ``.mma'' to filename (unless it is +already present), then a search for the file as given is done.

    -``S1'' is defined with a note length of 4 whole notes (1+1+1+1) so that -when it is multiplied for S32 a pattern of 32 8th notes is created. -Of course, the notes overlap. Running this up and down a chromatic -scale is ``interesting.'' You might want to play with this a bit and -try changing ``S1'' to: +For files included with the USE directive, the directory set +with SETLIBPATH is first checked, followed by the current +directory.

    - - -
    - -
    define S1 1 1 90
    - -
    +For files included with the INCLUDE directive, the directory +set with SETINCPATH is first checked, followed by the current +directory.

    -to see what the effect is of the notes overlapping. +Following is a summary of the different files supported: + +

    +

    +
    Song Files
    +
    The input file specified on the command line should + always be named with the ``.mma'' extension. When +MMA searches for + the file it will automatically add the extension if the file name + specified does not exist and doesn't have the extension. + +

    +

    +
    Library Files
    +
    Library files really should all be named + with the extension. +MMA will find non-extension names when used in + a USE or INCLUDE directive. However, it will not + process these files when creating indexes with the ``-g'' command + line option--these index files are used by the GROOVE + commands to automatically find and include libraries. + +

    +

    +
    RC Files
    +
    As noted in the RC-File discussion + (here) +MMA will + automatically include a variety of ``RC'' files. You can use the + extension on these files, but common usage suggests that these files + are probably better without. + +

    +

    +
    MMAstart and MMAend
    +
    +MMA will automatically include a file at + the beginning or end of processing (start/end + details). Typically these files are + named MMASTART and MMAEND. Common usage is to + not use the extension if the file is in the current + directory; use the file if it is in an ``includes'' directory. + +

    +

    +
    + +

    +One further point to remember is that filenames specified on the +command line are subject to wild-card expansion via the shell you are +using.

    -Jungle Birds +Tilde Expansion

    -Here's another use for SCALEs. Someone (certainly not the -author) decided that some jungle sounds would be perfect as an -introduction to ``Yellow Bird''. +On Unix-like systems all filenames may be prefaced with tilde or a +tilde with a username. All file operations in +MMA honor this +convention. This includes the setting of library and include paths. + +

    +The result of this operation is system dependent. See the entry for +os.path.expanduser in the Python library reference.

    - - +
    +

    +Eof +

    + +

    +Normally, a file is processed until its end. However, you can +short-circuit this behavior with the EOF directive. If +MMA finds a line starting with EOF no further processing will be +done on that file ... it's just as if the real end of file was +encountered. Anything on the same line, after the EOF is also +discarded. + +

    +You may find this handy if you want to test process only a part of a +file, or if you making large edits to a library file. It is often used +to quit when using the LABEL and GOTO directives to +simulate constructs like D.C. al Coda, etc. + +

    + +

    +
    +LibPath +

    + +

    +The search for library files can be set with the LibPath variable. To +set LIBPATH: + +

    + + + +
    + SetLibPath PATH -
    groove Rhumba -
    -Begin Scale -
        define S1 1 1 90 -
        define S32 S1 * 32 -
        Sequence S32 -
        ScaleType Chromatic -
        Direction Random -
        Voice BirdTweet -
        Octave 5 6 4 5 -
        RVolume 30 -
        Rtime 2 3 4 5 -
        Volume pp pp ppp ppp -
    -End -
    -DefGroove BirdRhumba
    +
    + +

    +You can have only one path in the SETLIBPATH directive. + +

    +When +MMA starts up it sets the library path to the first valid +directory in the list: + +

    + +

      +
    • /usr/local/share/mma/lib + +

      +

    • +
    • /usr/share/mma/lib + +

      +

    • +
    • ./lib + +

      +

    • +
    + +

    +The last choice lets you run +MMA directly from the distribution +directory. + +

    +You are free to change this to any other location in a +RCFile. + +

    +LIBPATH is used by the routine which auto-loads grooves from +the library, and the USE directive. The -g command line option +is used to maintain the library database). + +

    +The current setting can be accessed via the macro $_LibPath. + +

    + +

    +AutoLibPath +

    + +

    +The sub-directory containing the current library files to automatically +load is determined by the current setting of AUTOLIBPATH. +Please see the library file discussion here for details. + +

    +You can change the automatic include directory by resetting this +variable. It must be a sub-directory of LIBPATH for it to work. + +

    +The command to reset the variable is: + +

    + + +
    + SetAutoLibPath mydir -
    +

    -The above is an extract from the -MMA score. The entire song is -included in the ``songs'' directory of this distribution. +The current setting can be accessed via the macro $_AutoLibPath. By +default the setting is ``stdlib''.

    -A neat trick is to create the bird sound track and then add it to the -existing Rhumba groove. Then define a new groove. Now one can select -either the library ``rhumba'' or the enhanced ``BirdRhumba'' with a -simple GROOVE directive. +Any existing GROOVE definitions are deleted from memory when +this command is issued (this it to avoid name conflicts between libraries). + +

    + +

    +
    +OutPath +

    + +

    +MIDI file generation is to an automatically generated filename +(more details). If the +OUTPATH variable is set, that value will be prepended to the +output filename. To set the value: + +

    + + + +
    + SetOutPath PATH + +
    + +

    +Just make sure that ``PATH'' is a simple path name with no +spaces in it. The variable is case sensitive (assuming that your +operating system supports case sensitive filenames). This is a common +directive in a RC file (more details). By default, it has no value. + +

    +You can disable the OUTPATH variable quite simply: just issue +the command without an argument. + +

    +If the name set by this command begins with a ``.'', ``/'' or +`` \'' it is prepended to the complete filename specified on +the command line. For example, if you have the input filename +test.mma and the output path is +~/mids +--the output file will be /home/bob/mids/test.mid. + +

    +If the name doesn't start with the special characters noted in the +preceding paragraph the contents of the path will be inserted before +the filename portion of the input filename. Again, an example: the +input filename is mma/rock/crying and the output path is +``midi''--the output file will be mma/rock/midi/crying.mid. + +

    +The current setting can be accessed via the macro $_OutPath. + +

    +Note that this option is ignored if you use the -f + command line option or +if an absolute name for the input file (one starting with a ``/'' or + a ``~'') is used. + +

    + +

    +Include +

    + +

    +Other files with sequence, pattern or music data can be included at +any point in your input file. There is no limit to the level of +includes. + +

    + + + +
    + Include Filename + +
    + +

    +A search for the file is done in the INCPATH directory (see +below) and the current directory. The ``.mma'' filename extension is +optional (if a filename exists both with and without the ``.mma'' +extension, the file with the extension will be used). + +

    +The use of this command should be quite rare in user files; however, +it is used extensively in library files to include standard +patterns. + +

    + +

    +
    +IncPath +

    + +

    +The search for include files can be set with the INCPATH +variable. To set INCPATH: + +

    + + + +
    + SetIncPath PATH + +
    + +

    +You can have only one path in the SETINCPATH directive. + +

    +When +MMA initializes it sets the include path to first found directory in: + +

    + +

      +
    • /usr/local/share/mma/includes +
    • +
    • /usr/share/mma/includes +
    • +
    • ./includes + +

      +

    • +
    + +

    +The last location lets you run +MMA from the distribution directory. + +

    +If this value is not appropriate for your system, you are free to +change it in a RC File. + +

    +The current setting can be accessed via the macro $_IncPath. + +

    + +

    +
    +Use +

    + +

    +Similar to INCLUDE, but a bit more useful. The USE +command is used to include library files and their predefined grooves. + +

    +Compared to INCLUDE, USE has important features: + +

    + +

      +
    • The search for the file is done in the paths specified by the LibPath variable, + +

      +

    • +
    • The current state of the program is saved before the library + file is read and restored when the operation is complete. + +

      +

    • +
    + +

    +Let's examine each feature in a bit more detail. + +

    +When a USE directive is issued, eg: + +

    + + + +
    + use stdlib/swing + +
    + +

    + +MMA first attempts to locate the file ``stdlib/swing'' in the +directory specified by LIBPATH or the current directory. As +mentioned above, +MMA automatically added the ``.mma'' extension to +the file and checks for the non-extension filename if that can't be +found. + +

    +If things aren't working out quite right, check to see if the filename +is correct. Problems you can encounter include: + +

    + +

      +
    • Search order: you might be expecting the file in the current + directory to be used, but the same filename exists in the + LIBPATH, in which case that file is used. + +

      +

    • +
    • Not using extensions: Remember that files with the + extension added are first checked. + +

      +

    • +
    • Case: The filename is case sensitive. The files ``Swing'' + and ``swing'' are not the same. Since most things in +MMA are case + insensitive, this can be an easy mistake to make. + +

      +

    • +
    • The file is in a sub directory of the LIBPATH. In a + standard distribution the actual library files are in + /usr/local/share/mma/lib/stdlib, but the libpath is set to + /usr/local/share/mma/lib. In this case you must name the file + to be used as stdlib/rhumba not rhumba. + +

      +

    • +
    + +

    +As mentioned above, the current state of the compiler is saved during +a USE. +MMA accomplishes this by issuing a slightly modified +DEFGROOVE and GROOVE command before and after the +reading of the file. Please note that INCLUDE doesn't do this. +But, don't let this feature fool you--since the effects of defining +grooves are cumulative you really should have SEQCLEAR +statements at the top of all your library files. If you don't you'll +end up with unwanted tracks in the grooves you are defining. + +

    +In most cases you will not need to use the USE directive + in your music files. If you have properly installed +MMA and keep +the database up-to-date by using the command: + +

    + + + +
    + $ mma -g + +
    + +

    +grooves from library files will be automatically found and loaded. +Internally, the USE directive is used, so existing states are +saved. + +

    +If you are developing new or alternate library files you will find the +USE directive handy. + +

    + +

    +
    +MmaStart +

    + +

    +If you wish to process a certain file or files before your main input +file, set the MMASTART filename in an RCFile. For example, you +might have a number of files in a directory which you wish to use +certain PAN settings. In that directory, you just need to have +a file mmarc which contains the following command: + +

    + + + +
    + MmaStart setpan + +
    + +

    +The actual file setpan has the following directives: + +

    + + + +
    + Bass Pan 0 +
    +Bass1 Pan 0 +
    +Bass2 Pan 0 +
    +Walk Pan 0 +
    +Walk1 Pan 0 +
    +Walk2 Pan 0
    + +
    + +

    +So, before each file in that directory is processed, the PAN +for the bass and walking bass voices are set to the left channel. + +

    +If the file specified by a MMASTART directive does not exist a +warning message will be printed (this is not an error). + +

    +Also useful is the ability to include a generic file with all the MIDI +files you create. For example, you might like to have a MIDI reset at the +start of your files--simple, just include the following in your mmarc file: + +

    + + + +
    + MMAstart reset + +
    + +

    +This includes the file reset.mma located in the ``includes'' +directory (IncludePath). + +

    +Multiple MMASTART directives are permitted. The files are +processed in the order declared. You can have multiple filenames on a +MMASTART line. + +

    +One caution with MMASTART files: the file is processed after +the RC file, just before the actual song file. + +

    + +

    +
    +MmaEnd +

    + +

    +Just the opposite of MMASTART, this command specifies a file to +be included at the end of a main input file. See the comments above +for more details. + +

    +To continue this example, in your mmarc file you would have: + +

    + + + +
    + MmaEnd nopan + +
    + +

    +and in the file nopan have: + +

    + + + +
    + Bass Pan 64 +
    +Bass1 Pan 64 +
    +Bass2 Pan 64 +
    +Walk Pan 64 +
    +Walk1 Pan 64 +
    +Walk2 Pan 64
    + +
    + +

    +If the file specified by a MMAEND directive does not exist a +warning message will be printed (this is not an error). + +

    +Multiple MMAEND directives are permitted and processed in the +order declared. You can have multiple filenames on a MMAEND line. + +

    + +

    + +
    +RC Files +

    + +

    +When +MMA starts it checks for initialization files. Only the first +found file is processed. The following locations/files are checked (in order): + +

    + +

      +
    1. mmarc -- this is a normal file in the current directory. + +

      +

    2. +
    3. ~/.mmarc -- this is an ``invisible'' file in the users + home directory. + +

      +

    4. +
    5. /usr/local/etc/mmarc + +

      +

    6. +
    7. /etc/mmarc + +

      +

    8. +
    + +

    + Only the first found file will be processed. This means you can +override a ``global'' RC file with a user specific one. If you just +want to override some specific commands you might want to: + +

    + +

      +
    1. Create the file mmarc in a directory with +MMA files, + +

      +

    2. +
    3. As the first line in that file have the command: + +

      + + + +
      + include ~/.mmarc + +
      + +

      +to force the inclusion of your global stuff, + +

      +

    4. +
    5. Now, place your directory specific commands in your custom RC file. +
    6. +
    + +

    +By default, no RC files are installed. You may want to create an empty +~/.mmarc file to eliminate a warning message. + +

    +An alternate method for using a different RC file is to specify the +name of the file on the command line by using the -i option +(here). Using this option +you can have several RC files in a directory and complile your songs +differently depending on the RC file you specify. + +

    +The RC file is processed as a +MMA input file. As such, it can +contain anything a normal input file can, including music commands. +However, you should limit the contents of RC files to things +like: + +

    + + + +
    + SetOutPath +
    +SetLibPath +
    +MMAStart +
    +MMAEnd
    + +
    + +

    +A useful setup is to have your source files in one directory and MIDI +files saved into a different directory. Having the file mmarc +in the directory with the source files permits setting OUTPATH +to the MIDI path. + +

    + +

    +
    +Library Files +

    + +

    +Included in this distribution are a number of predefined patterns, +sequences and grooves. They are in different files in the ``lib'' +directory. + +

    +The library files should be self-documenting. A list of standard file +and the grooves they define is included in the separate document, +supplied in this distribution as ``mma-lib.ps''. + +

    + +

    +
    +Maintaining and Using Libraries +

    + +

    +The basic +MMA distribution comes with a set of pattern files which +are installed in the mma/lib/stdlib directory. Each one of +these files has a number of GROOVEs defined in them. For +example, the file mma/lib/stdlib/rhumba.mma contains the +grooves Rhumba, RhumbaEnd and many more. + +

    +If you are writing GROOVEs with the intention of adding them to +the standard library you should ensure that none of the names you +choose duplicate existing names already used. + +

    +If you are creating a set of alternate grooves to duplicate the +existing library you might do the following: + +

    + +

      +
    1. Create a directory with your name or other short id in the + mma/lib/ hierarchy. For example, if your name is ``Bob van + der Poel'' you might create the directory mma/lib/bvdp. + +

      +

    2. +
    3. Place all your files (or modified files) in that directory. + +

      +

    4. +
    5. Now, when your song wants to use a groove, you have two choices: + +

      + +

        +
      1. Include the file with the USE directive. For example, + if you have created the file rock.mma and want to use the + GROOVE rock8 you would: + +

        + +

          +
        1. place the directive USE BVDP/ROCK near the top of the + song file. Note: it might not be apparent from the typeface here, but the + filename here is all lowercase. In Unix/Linux case is important, so + please make sure of the case of the filenames in commands like USE. + +

          +

        2. +
        3. enable the groove with the directive GROOVE ROCK8 (and here the + case is not important since +MMA thinks that upper and lower case are the same). + +

          +

        4. +
        + +

        +

      2. +
      3. Force +MMA to use your groove directory by resetting + the auto-lib directory (again, the case for the path is important): + +

        + + + +
        + SetAutoLibPath bvdp + +
        + +

        +You will have to update the +MMA database with the -g or -G + command line options for this to work. If you elect this route, + please note that the files in the standard library will not be + available, but you can use both with something like this: + +

        + + + +
        + Groove Metronome2-4 +
        +z * 2 +
        +SetAutoLibPath bvdp +
        +Groove BossaNova // the bossa from lib/bvdp, not stdlib! +
        +chords...
        + +
        + +

        +The nice thing about this method is that you can have multiple + sets of library files all using the same GROOVE + names. To create a different version you just need to change + the SETAUTOLIBPATH variable in your song file ...or, + for a collection of songs put the variable in your MMARC + file. + +

        +

      4. +
      + +

      +

    6. +
    + +

    +For those who ``really need to know'', here are the steps that +MMA takes when it encounters a GROOVE command: + +

    + +

      +
    1. if the named groove has been loaded/created already +MMA just + switches to the internal version of that groove. + +

      +

    2. +
    3. if the groove can't be found in memory, a search of the groove + database (created with the -g command line option) is done. If no + database is in memory it is loaded from the directory pointed to by + the LIBPATH and AUTOLIBPATH variables. This database + is then searched for the needed GROOVE. The database contains + the filenames associated with each GROOVE and that file is + then read with the USE code. + +

      +

    4. +
    + +

    +The database is a file .mmaDB stored in each sub directory of +LIBPATH. This is a ``hidden'' file (due to the leading ``.'' in +the filename). You cannot change the name of this file. If there are +sub-directories the entries for them will be stored in the database +file for the main tree. + +

    +By using a USE directive or by resetting AUTOLIBDIR you +force the loading of your set of grooves. + +

    + +

    + +
    +Paths on Windows Platforms +

    + +

    +To make +MMA as platform independent as possible a number of additional paths have been +defined. When starting up, in addition to the standard Linux paths discussed above, the +following are also checked: + +

    + +

      +
    • Modules can be in c: +
      +mma
      , +
    • +
    • Include files can be in c: +
      +mma +
      +includes
      , +
    • +
    • Library files can be in c: +
      +mma +
      +lib
      . + +

      +

    • +


    - next - up - previous
    - Next: Frequency Asked Questions - Up: Next: Creating Effects + Up: Reference Manual - Previous: Paths, Files and Libraries + Previous: Documentation Strings
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node25.html b/mma/docs/html/ref/node25.html index f3651ea..49d1062 100644 --- a/mma/docs/html/ref/node25.html +++ b/mma/docs/html/ref/node25.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Frequency Asked Questions - +Creating Effects + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Symbols and Constants - Up: Next: Frequency Asked Questions + Up: Reference Manual - Previous: Creating Effects + Previous: Paths, Files and Libraries

    @@ -49,223 +49,168 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections

    - +
    -Frequency Asked Questions +Creating Effects

    -This chapter will serve as a container for questions asked by -some enthusiastic -MMA users. It may make some sense in the future to -distribute this information as a separate file. +It's really quite amazing how easy and effective it is to create +different patterns, sequences and special effects. As +MMA was +developed lots of silly things were tried...this chapter is an +attempt to display and preserve some of them. + +

    +The examples don't show any music to apply the patterns or sequences +to. The manual assumes that if you've read this far you'll know +that you should have something like: + +

    + + + +
    + 1 C +
    +2 G +
    +3 G +
    +4 C
    + +
    + +

    +as a simple test piece to apply tests to.

    -Chord Octaves +Overlapping Notes

    -I've keyed in a song but some of the chords sound way too high - (or low). +As a general rule, you should not create patterns in which notes +overlap. However, here's an interesting effect which relies on +ignoring that rule:

    -When a real player plays chords he or she adjusts the position of the -chords so that they don't ``bounce'' around between octaves. One way -MMA tries to do the same is with the ``Voicing Mode=Optimal'' -setting. However, sometimes the chord range of a piece is too large -for this to work properly. In this case you'll have to use the octave -adjustments in chords. For more details go here. + + +
    + Begin Scale +
        define S1 1 1+1+1+1 90 +
        define S32 S1 * 32 +
        Sequence S32 +
        ScaleType +
        Direction Both +
        Voice Accordion +
        Octave 5 +
    +End
    + +
    + +

    +``S1'' is defined with a note length of 4 whole notes (1+1+1+1) so that +when it is multiplied for S32 a pattern of 32 8th notes is created. +Of course, the notes overlap. Running this up and down a chromatic +scale is ``interesting.'' You might want to play with this a bit and +try changing ``S1'' to: + +

    + + + +
    + define S1 1 1 90 + +
    + +

    +to see what the effect is of the notes overlapping.

    -AABA Song Forms +Jungle Birds

    -How can one define parts as part "A", part "B" ...and - arrange them at the end of the file? An option to repeat a ``solo'' - section a number of times would be nice as well. - -

    -Using -MMA variables and some simple looping, one might try something like: +Here's another use for SCALEs. Someone (certainly not the +author) decided that some jungle sounds would be perfect as an +introduction to ``Yellow Bird''.

    - - +
    + +
    + groove Rhumba +
    +Begin Scale +
        define S1 1 1 90 +
        define S32 S1 * 32 +
        Sequence S32 +
        ScaleType Chromatic +
        Direction Random +
        Voice BirdTweet +
        Octave 5 6 4 5 +
        RVolume 30 +
        Rtime 2 3 4 5 +
        Volume pp pp ppp ppp +
    +End +
    +DefGroove BirdRhumba
    -
    Groove Swing -
    // Set the music into a -
    // series of macros -
    -mset A -
      Print Section A -
      C -
      G -
    -endmset -
    -mset B -
      print Section B -
      Dm -
      Em -
    -endmset -
    -mset Solo -
      Print Solo Section $Count -
      Am / B7 Cdim -
    -endmset -
    // Use the macros for an -
    // "A, A, B, Solo * 8, A" -
    // form -
    $A -
    $A -
    $B -
    -set Count 1 -
    -label a -
      $solo -
      inc COUNT -
      if le $count 8 -
        goto A -
      endif -
    $A -
    - -
    +

    -Note that the ``Print'' lines are used for debugging purposes. The case -of the variable names has been mixed to illustrate the fact that -``Solo'' is the same as ``SOLO'' which is the same as ``solo''. - -

    -Now, if you don't like things that look like old BASIC program code, -you could just as easily duplicate the above with: - -

    - - -
    - -
    Groove Swing -
    -repeat -
      repeat -
        Print Section A -
        C -
        G -
        If Def count -
          eof -
        Endif -
        Endrepeat -
        Print Section B -
        Dm -
        Em -
        Set Count 1 -
        Repeat -
          Print Solo $Count -
          Am -
          Inc Count -
        Repeatending 7 -
      Repeatend -
    -Repeatend
    - -
    - -

    -The choice is up to you. - -

    - -

    -Where's the GUI? -

    - -

    -I really think that -MMA is a cool program. But, it needs a - GUI. Are you planning on writing one? Will you help me if I - start to write one? - -

    -Thanks for the kind comments! The author likes -MMA too. A lot! - -

    -Some attempts have been made to write a number of GUIs for - -MMA . But, nothing seemed to be much more useful than the existing -text interface. So, why waste too much time? There is nothing wrong with -graphical programming interfaces, but perhaps not in this case. - -

    -But, I may well be wrong. If you think it'd be better with a -GUI ...well, this is open source and you are more than -welcome to write one. If you do, I'd suggest that you make your -program a front-end which lets a user compile standard -MMA files. If -you find that more error reporting, etc. is required to interact -properly with your code, let me know and I'll probably be quite -willing to make those kind of changes. - -

    - -

    -Where's the manual index? -

    - -

    -Yes,this manual needs an index. I just don't have the time -to go though and do all the necessary work. Is there a volunteer? +The above is an extract from the +MMA score. The entire song is +included in the ``songs'' directory of this distribution.

    +A neat trick is to create the bird sound track and then add it to the +existing Rhumba groove. Then define a new groove. Now one can select +either the library ``rhumba'' or the enhanced ``BirdRhumba'' with a +simple GROOVE directive.


    - next - up - previous
    - Next: Symbols and Constants - Up: Next: Frequency Asked Questions + Up: Reference Manual - Previous: Creating Effects + Previous: Paths, Files and Libraries
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node26.html b/mma/docs/html/ref/node26.html index 9334355..93d44de 100644 --- a/mma/docs/html/ref/node26.html +++ b/mma/docs/html/ref/node26.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Symbols and Constants - +Frequency Asked Questions + @@ -26,22 +26,22 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Bibliography and Thanks - Up: Next: Symbols and Constants + Up: Reference Manual - Previous: Frequency Asked Questions + Previous: Creating Effects

    @@ -49,3132 +49,223 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections + HREF="node26.html#SECTION002640000000000000000">Where's the manual index? +

    - +
    -Symbols and Constants +Frequency Asked Questions

    -This appendix is a reference to the chords that -MMA recognizes and -name/value tables for drum and instrument names. The tables have been -auto-generated by -MMA using the -D options. +This chapter will serve as a container for questions asked by +some enthusiastic +MMA users. It may make some sense in the future to +distribute this information as a separate file.

    -Chord Names +Chord Octaves

    - -MMA recognizes standard chord names as listed below. The names are -case sensitive and must be entered in uppercase letters as shown: +I've keyed in a song but some of the chords sound way too high + (or low).

    -A - A$\sharp$ - A$\flat$ - B - B$\sharp$ - B$\flat$ - C - C$\sharp$ - C$\flat$ - D - D$\sharp$ - D$\flat$ - E - E$\sharp$ - E$\flat$ - F - F$\sharp$ - F$\flat$ - G - G$\sharp$ - G$\flat$ +When a real player plays chords he or she adjusts the position of the +chords so that they don't ``bounce'' around between octaves. One way -

    -Please note that in your input files you must use a lowercase ``b'' or -an ``&'' to represent a $\flat$ and a ``#'' for a $\sharp$. - -

    -The following types of chords are recognized (these are case sensitive -and must be in the mixed upper and lowercase shown): +MMA tries to do the same is with the ``Voicing Mode=Optimal'' +setting. However, sometimes the chord range of a piece is too large +for this to work properly. In this case you'll have to use the octave +adjustments in chords. For more details go here.

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    $\sharp$5Augmented triad.
    +Augmented triad.
    +7An augmented chord (raised 5th) with a dominant 7th.
    119th chord plus 11th.
    11$\flat$99th chord plus flat 11th.
    13Dominant 7th (including 5th) plus 13th.
    5Altered Fifth or Power Chord; root and 5th only.
    6Major tiad with added 6th.
    6(add9)6th with added 9th. This is sometimes notated as a slash chord in the form ``6/9''.
    696th with added 9th. This is sometimes notated as a slash chord in the form ``6/9''.
    7Dominant 7th.
    7$\sharp$11Dominant 7th plus 9th and sharp 11th.
    7$\sharp$57th, sharp 5.
    7$\sharp$5$\sharp$9Dominant 7th with sharp 5th and sharp 9th.
    7$\sharp$5$\flat$9Dominant 7th with sharp 5th and flat 9th.
    7$\sharp$9Dominant 7th with sharp 9th.
    7$\sharp$9$\sharp$11Dominant 7th plus sharp 9th and sharp 11th.
    7+An augmented chord (raised 5th) with a dominant 7th.
    7+57th, sharp 5.
    7+9Dominant 7th with sharp 9th.
    7-57th, flat 5.
    7-9Dominant 7th with flat 9th.
    7altDominant 7th with flat 5th and flat 9th.
    7$\flat$57th, flat 5.
    7$\flat$5$\sharp$9Dominant 7th with flat 5th and sharp 9th.
    7$\flat$5$\flat$9Dominant 7th with flat 5th and flat 9th.
    7$\flat$9Dominant 7th with flat 9th.
    7sus7th with suspended 4th, dominant 7th with 3rd raised half tone.
    7sus2A sus2 with dominant 7th added.
    7sus47th with suspended 4th, dominant 7th with 3rd raised half tone.
    9Dominant 7th plus 9th.
    9$\sharp$11Dominant 7th plus 9th and sharp 11th.
    9$\sharp$5Dominant 7th plus 9th with sharp 5th.
    9+5Dominant 7th plus 9th with sharp 5th.
    9-5Dominant 7th plus 9th with flat 5th.
    9$\flat$5Dominant 7th plus 9th with flat 5th.
    9susDominant 7th plus 9th, omit 7th.
    MMajor triad. This is the default and is used in the absense of any other chord type specification.
    M13Major 7th (including 5th) plus 13th.
    M6Major tiad with added 6th.
    M7Major 7th.
    M7$\sharp$11Major 7th plus 9th and sharp 11th.
    M7$\sharp$5Major 7th with sharp 5th.
    M7+5Major 7th with sharp 5th.
    M7-5Major 7th with a flat 5th.
    M7$\flat$5Major 7th with a flat 5th.
    M9Major 7th plus 9th.
    augAugmented triad.
    aug7An augmented chord (raised 5th) with a dominant 7th.
    aug7$\flat$9Augmented 7th with flat 5th and sharp 9th.
    aug9Dominant 7th plus 9th with sharp 5th.
    dimA dim7, not a triad!
    dim3Diminished triad (non-standard notation).
    dim7Diminished seventh.
    mMinor triad.
    m$\sharp$5Major triad with augmented 5th.
    m$\sharp$7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m(maj7)Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m(sus9)Minor triad plus 9th (no 7th).
    m+5Major triad with augmented 5th.
    m+7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m119th with minor 3rd, plus 11th.
    m6Minor 6th.
    m6(add9)Minor 6th with added 9th. This is sometimes notated as a slash chord in the form ``m6/9''.
    m69Minor 6th with added 9th. This is sometimes notated as a slash chord in the form ``m6/9''.
    m7Minor 7th.
    m7-5Minor 7th, flat 5 (aka 1/2 diminished).
    m7$\flat$5Minor 7th, flat 5 (aka 1/2 diminished).
    m7$\flat$9Minor 7th with added flat 9th.
    m9Minor triad plus 7th and 9th.
    m9$\flat$5Minor triad, flat 5, plus 7th and 9th.
    mM7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    maj7Major 7th.
    m$\flat$5Minor triad with flat 5th.
    min$\sharp$7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    min(maj7)Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which -MMA accepts); as well as the -MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    susSuspended 4th, major triad with 3rd raised half tone.
    sus2Suspended 2nd, major triad with major 2nd above root substituted for 3rd.
    sus4Suspended 4th, major triad with 3rd raised half tone.
    sus9Dominant 7th plus 9th, omit 7th.
     
    -In modern pop charts the ``M'' in a major 7th chord (and other major -chords) is often represented by a ``$\Delta$''. When entering these -chords, just replace the ``$\Delta$'' with an ``M''. For example, -change ``G$\Delta$7'' to ``GM7''. +

    +AABA Song Forms +

    -A chord name without a type is interpreted as a major chord (or -triad). For example, the chord ``C'' is identical to ``CM''. +How can one define parts as part "A", part "B" ...and + arrange them at the end of the file? An option to repeat a ``solo'' + section a number of times would be nice as well. + +

    +Using +MMA variables and some simple looping, one might try something like:

    -MMA has an large set of defined chords. However, you can add your -own with the DEFCHORD command, details - here. - -

    - -

    + + +
    + Groove Swing +
    // Set the music into a +
    // series of macros
    -Octave Adjustment - - -

    -Depending on the key and chord sequence, a chord may end up in the -wrong octave. This is caused by -MMA 's internal routines which -create a chord: all of the tables are maintained for a ``C'' chord and -the others are derived from that point by subtracting or adding a -constant. To compensate you can add a leading ``-'' or ``+'' to the -chordname to force the movement of that chord and scale up or down an -octave. - -

    -For example, the following line will move the chord up and down for -the third and fourth beats: - -

    - - - +
    +mset A +
      Print Section A +
      C +
      G +
    +endmset +
    +mset B +
      print Section B +
      Dm +
      Em +
    +endmset +
    +mset Solo +
      Print Solo Section $Count +
      Am / B7 Cdim +
    +endmset +
    // Use the macros for an +
    // "A, A, B, Solo * 8, A" +
    // form +
    $A +
    $A +
    $B +
    +set Count 1 +
    +label a +
      $solo +
      inc COUNT +
      if le $count 8 +
        goto A +
      endif +
    $A +
    -
    Cm Fm -Gm +D7
    +
    + +

    +Note that the ``Print'' lines are used for debugging purposes. The case +of the variable names has been mixed to illustrate the fact that +``Solo'' is the same as ``SOLO'' which is the same as ``solo''. + +

    +Now, if you don't like things that look like old BASIC program code, +you could just as easily duplicate the above with: + +

    + + +
    + Groove Swing +
    +repeat +
      repeat +
        Print Section A +
        C +
        G +
        If Def count +
          eof +
        Endif +
        Endrepeat +
        Print Section B +
        Dm +
        Em +
        Set Count 1 +
        Repeat +
          Print Solo $Count +
          Am +
          Inc Count +
        Repeatending 7 +
      Repeatend +
    +Repeatend
    -
    +

    -The effect of octave shifting is also highly dependent on the voicing -options in effect for the track. - -

    -You'll have to listen to the -MMA output to detemine when -and where to use this adjustment. Hopefully, it won't be needed all -that much. - -

    -If you have a large number of chords to adjust, use the CHORDADJUST -command , here. +The choice is up to you.

    -

    -Diminished Chords -

    - -

    -In most pop and jazz charts it is assumed that a diminished chord is -always a diminished 7th ...a diminished triad is never played. - -MMA continues this, sometimes, erroneous assumption. You can change -the behaviour in several ways: change the chord notes and scale for a -``dim'' from a dim7 to a triad by following the instructions -here; use the slightly oddball -notation of ``m$\flat$5'' which generates a ``diminished tirad''; or -use the more-oddball notation ``dim3''. - -

    -Notational notes: In printed music a ``diminished'' chord is sometimes -represented with a small circle symbol (eg. -``FO'') and a ``half-diminished'' as a -small slashed circle (e.g., ``CØ''). - -

    -A half-diminished chord in -MMA is specified with the notation -``m7$\flat$5''. - -

    - -

    -Slash Chords -

    - -

    -Charts sometimes use slash chords in the form ``Am/E''. This -notation is used, mainly, to indicate chord inversions. For example, -the chord notes in ``Am/E'' become ``E'', ``A'' and ''C'' with the -``E'' taking the root position. -MMA will accept chords of this type. -However, you may not notice any difference in the generated tracks due -to the inversions used by the current pattern. - -

    -You may also encounter slash chords where the slash-part of the chord -is not a note in the chord. Consider the ambiguous notation -``Dm/C''. The composer (or copyist) might mean to add a ``C'' bass -note to a ``Dm'' chord, or she might mean ``Dm7'', or even an inverted -``Dm7''. -MMA will handle these ...almost perfectly. When the -``slash'' part of the chord indicates a note which is not a -note in the chord, -MMA assumes that the indicated note should be -used in the bass line. Since each chord generated by -MMA also has a -``scale'' associated with it for use by bass and scale patterns this -works. For example, a C Major chord will have the scale ``c, d, e, f, -g, a, b''; a C Minor chord has the same scale, but with an e$\flat$. -If the slash note is contained in the scale, the scale will be rotated -so that the note becomes the ``root'' note. - -

    -A warning message will be printed if the note is not in both the chord -and the scale. - -

    -Another notation you may see is something like ``Dm/9''. Again, -the meaning is not clear. It probably means a ``Dm9'', or ``Dm9/E'' -... but since -MMA isn't sure this notation will generate an -error. - -

    -Please note that for fairly obvious reasons you cannot have both slash -notation and an inversion (see the next section). - -

    -For more details on ``slash chords'' your favorite -music theory book or teacher is highly recommended! - -

    - -

    -Chord Inversions -

    - -

    -Instead of using a slash chord you can specify an inversion to use with a chord. -The notation is simply an ``>'' and a number between -5 and 5 immediately following -the chord name. - -

    -The chord will be ``rotated'' as specified by the value after the ``>''. - -

    -For example, the chord ``C>2'' will generate the notes G, C and E; ``F>-1'' -gives C, F and A. - -

    -There is an important difference between this option and a slash chord: in inversions neither -the root note nor the associated scale are modified. - -

    - -

    - -
    -MIDI Voices +

    +Where's the GUI?

    -When setting a voice for a track (IE Bass Voice NN), you can specify -the patch to use with a symbolic constant. Any combination of upper -and lower case is permitted. The following are the names with the -equivalent voice numbers: +I really think that +MMA is a cool program. But, it needs a + GUI. Are you planning on writing one? Will you help me if I + start to write one? + +

    +Thanks for the kind comments! The author likes +MMA too. A lot! + +

    +Some attempts have been made to write a number of GUIs for + +MMA . But, nothing seemed to be much more useful than the existing +text interface. So, why waste too much time? There is nothing wrong with +graphical programming interfaces, but perhaps not in this case. + +

    +But, I may well be wrong. If you think it'd be better with a +GUI ...well, this is open source and you are more than +welcome to write one. If you do, I'd suggest that you make your +program a front-end which lets a user compile standard +MMA files. If +you find that more error reporting, etc. is required to interact +properly with your code, let me know and I'll probably be quite +willing to make those kind of changes.

    -

    - -

    -Voices, Alphabetically -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    5thSawWave86
    Accordion21
    AcousticBass32
    AgogoBells113
    AltoSax65
    Applause/Noise126
    Atmosphere99
    BagPipe109
    Bandoneon23
    Banjo105
    BaritoneSax67
    Bass&Lead87
    Bassoon70
    BirdTweet123
    BottleBlow76
    BowedGlass92
    BrassSection61
    BreathNoise121
    Brightness100
    Celesta8
    Cello42
    Charang84
    ChifferLead83
    ChoirAahs52
    ChurchOrgan19
    Clarinet71
    Clavinet7
    CleanGuitar27
    ContraBass43
    Crystal98
    DistortonGuitar30
    EPiano5
    EchoDrops102
    EnglishHorn69
    Fantasia88
    Fiddle110
    FingeredBass33
    Flute73
    FrenchHorn60
    FretlessBass35
    Glockenspiel9
    Goblins101
    GuitarFretNoise120
    GuitarHarmonics31
    GunShot127
    HaloPad94
    Harmonica22
    HarpsiChord6
    HelicopterBlade125
    Honky-TonkPiano3
    IceRain96
    JazzGuitar26
    Kalimba108
    Koto107
    Marimba12
    MelodicTom1117
    MetalPad93
    MusicBox10
    MutedGuitar28
    MutedTrumpet59
    NylonGuitar24
    Oboe68
    Ocarina79
    OrchestraHit55
    OrchestralHarp46
    Organ116
    Organ217
    Organ318
    OverDriveGuitar29
    PanFlute75
    Piano10
    Piano21
    Piano32
    Piccolo72
    PickedBass34
    PizzicatoString45
    PolySynth90
    Recorder74
    ReedOrgan20
    ReverseCymbal119
    RhodesPiano4
    Santur15
    SawWave81
    SeaShore122
    Shakuhachi77
    Shamisen106
    Shanai111
    Sitar104
    SlapBass136
    SlapBass237
    SlowStrings49
    SoloVoice85
    SopranoSax64
    SoundTrack97
    SpaceVoice91
    SquareWave80
    StarTheme103
    SteelDrums114
    SteelGuitar25
    Strings48
    SweepPad95
    SynCalliope82
    SynthBass138
    SynthBass239
    SynthBrass162
    SynthBrass263
    SynthDrum118
    SynthStrings150
    SynthStrings251
    SynthVox54
    TaikoDrum116
    TelephoneRing124
    TenorSax66
    Timpani47
    TinkleBell112
    TremoloStrings44
    Trombone57
    Trumpet56
    Tuba58
    TubularBells14
    Vibraphone11
    Viola41
    Violin40
    VoiceOohs53
    WarmPad89
    Whistle78
    WoodBlock115
    Xylophone13
     
    -

    - -

    -Voices, By MIDI Value -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    0Piano1
    1Piano2
    2Piano3
    3Honky-TonkPiano
    4RhodesPiano
    5EPiano
    6HarpsiChord
    7Clavinet
    8Celesta
    9Glockenspiel
    10MusicBox
    11Vibraphone
    12Marimba
    13Xylophone
    14TubularBells
    15Santur
    16Organ1
    17Organ2
    18Organ3
    19ChurchOrgan
    20ReedOrgan
    21Accordion
    22Harmonica
    23Bandoneon
    24NylonGuitar
    25SteelGuitar
    26JazzGuitar
    27CleanGuitar
    28MutedGuitar
    29OverDriveGuitar
    30DistortonGuitar
    31GuitarHarmonics
    32AcousticBass
    33FingeredBass
    34PickedBass
    35FretlessBass
    36SlapBass1
    37SlapBass2
    38SynthBass1
    39SynthBass2
    40Violin
    41Viola
    42Cello
    43ContraBass
    44TremoloStrings
    45PizzicatoString
    46OrchestralHarp
    47Timpani
    48Strings
    49SlowStrings
    50SynthStrings1
    51SynthStrings2
    52ChoirAahs
    53VoiceOohs
    54SynthVox
    55OrchestraHit
    56Trumpet
    57Trombone
    58Tuba
    59MutedTrumpet
    60FrenchHorn
    61BrassSection
    62SynthBrass1
    63SynthBrass2
    64SopranoSax
    65AltoSax
    66TenorSax
    67BaritoneSax
    68Oboe
    69EnglishHorn
    70Bassoon
    71Clarinet
    72Piccolo
    73Flute
    74Recorder
    75PanFlute
    76BottleBlow
    77Shakuhachi
    78Whistle
    79Ocarina
    80SquareWave
    81SawWave
    82SynCalliope
    83ChifferLead
    84Charang
    85SoloVoice
    865thSawWave
    87Bass&Lead
    88Fantasia
    89WarmPad
    90PolySynth
    91SpaceVoice
    92BowedGlass
    93MetalPad
    94HaloPad
    95SweepPad
    96IceRain
    97SoundTrack
    98Crystal
    99Atmosphere
    100Brightness
    101Goblins
    102EchoDrops
    103StarTheme
    104Sitar
    105Banjo
    106Shamisen
    107Koto
    108Kalimba
    109BagPipe
    110Fiddle
    111Shanai
    112TinkleBell
    113AgogoBells
    114SteelDrums
    115WoodBlock
    116TaikoDrum
    117MelodicTom1
    118SynthDrum
    119ReverseCymbal
    120GuitarFretNoise
    121BreathNoise
    122SeaShore
    123BirdTweet
    124TelephoneRing
    125HelicopterBlade
    126Applause/Noise
    127GunShot
     
    -

    - -

    - -
    -Drum Notes +

    +Where's the manual index?

    -When defining a drum tone, you can specify the patch to use with a -symbolic constant. Any combination of upper and lower case is -permitted. In addition to the drum tone name and the MIDI value, the -equivalent ``name'' in -$^{superscript}$ is included. The ``names'' may help you -find the tones on your keyboard. +Yes,this manual needs an index. I just don't have the time +to go though and do all the necessary work. Is there a volunteer?

    -

    -Drum Notes, Alphabetically -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Cabasa69$^{A}$
    Castanets84$^{C}$
    ChineseCymbal52$^{E}$
    Claves75$^{E\flat}$
    ClosedHiHat42$^{G\flat}$
    CowBell56$^{A\flat}$
    CrashCymbal149$^{D\flat}$
    CrashCymbal257$^{A}$
    HandClap39$^{E\flat}$
    HighAgogo67$^{G}$
    HighBongo60$^{C}$
    HighQ27$^{E\flat}$
    HighTimbale65$^{F}$
    HighTom150$^{D}$
    HighTom248$^{C}$
    HighWoodBlock76$^{E}$
    JingleBell83$^{B}$
    KickDrum136$^{C}$
    KickDrum235$^{B}$
    LongGuiro74$^{D}$
    LongLowWhistle72$^{C}$
    LowAgogo68$^{A\flat}$
    LowBongo61$^{D\flat}$
    LowConga64$^{E}$
    LowTimbale66$^{G\flat}$
    LowTom143$^{G}$
    LowTom241$^{F}$
    LowWoodBlock77$^{F}$
    Maracas70$^{B\flat}$
    MetronomeBell34$^{B\flat}$
    MetronomeClick33$^{A}$
    MidTom147$^{B}$
    MidTom245$^{A}$
    MuteCuica78$^{G\flat}$
    MuteHighConga62$^{D}$
    MuteSudro85$^{D\flat}$
    MuteTriangle80$^{A\flat}$
    OpenCuica79$^{G}$
    OpenHiHat46$^{B\flat}$
    OpenHighConga63$^{E\flat}$
    OpenSudro86$^{D}$
    OpenTriangle81$^{A}$
    PedalHiHat44$^{A\flat}$
    RideBell53$^{F}$
    RideCymbal151$^{E\flat}$
    RideCymbal259$^{B}$
    ScratchPull30$^{G\flat}$
    ScratchPush29$^{F}$
    Shaker82$^{B\flat}$
    ShortGuiro73$^{D\flat}$
    ShortHiWhistle71$^{B}$
    SideKick37$^{D\flat}$
    Slap28$^{E}$
    SnareDrum138$^{D}$
    SnareDrum240$^{E}$
    SplashCymbal55$^{G}$
    SquareClick32$^{A\flat}$
    Sticks31$^{G}$
    Tambourine54$^{G\flat}$
    VibraSlap58$^{B\flat}$
     
    -

    - -

    -Drum Notes, by MIDI Value -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    27HighQ$^{E\flat}$
    28Slap$^{E}$
    29ScratchPush$^{F}$
    30ScratchPull$^{G\flat}$
    31Sticks$^{G}$
    32SquareClick$^{A\flat}$
    33MetronomeClick$^{A}$
    34MetronomeBell$^{B\flat}$
    35KickDrum2$^{B}$
    36KickDrum1$^{C}$
    37SideKick$^{D\flat}$
    38SnareDrum1$^{D}$
    39HandClap$^{E\flat}$
    40SnareDrum2$^{E}$
    41LowTom2$^{F}$
    42ClosedHiHat$^{G\flat}$
    43LowTom1$^{G}$
    44PedalHiHat$^{A\flat}$
    45MidTom2$^{A}$
    46OpenHiHat$^{B\flat}$
    47MidTom1$^{B}$
    48HighTom2$^{C}$
    49CrashCymbal1$^{D\flat}$
    50HighTom1$^{D}$
    51RideCymbal1$^{E\flat}$
    52ChineseCymbal$^{E}$
    53RideBell$^{F}$
    54Tambourine$^{G\flat}$
    55SplashCymbal$^{G}$
    56CowBell$^{A\flat}$
    57CrashCymbal2$^{A}$
    58VibraSlap$^{B\flat}$
    59RideCymbal2$^{B}$
    60HighBongo$^{C}$
    61LowBongo$^{D\flat}$
    62MuteHighConga$^{D}$
    63OpenHighConga$^{E\flat}$
    64LowConga$^{E}$
    65HighTimbale$^{F}$
    66LowTimbale$^{G\flat}$
    67HighAgogo$^{G}$
    68LowAgogo$^{A\flat}$
    69Cabasa$^{A}$
    70Maracas$^{B\flat}$
    71ShortHiWhistle$^{B}$
    72LongLowWhistle$^{C}$
    73ShortGuiro$^{D\flat}$
    74LongGuiro$^{D}$
    75Claves$^{E\flat}$
    76HighWoodBlock$^{E}$
    77LowWoodBlock$^{F}$
    78MuteCuica$^{G\flat}$
    79OpenCuica$^{G}$
    80MuteTriangle$^{A\flat}$
    81OpenTriangle$^{A}$
    82Shaker$^{B\flat}$
    83JingleBell$^{B}$
    84Castanets$^{C}$
    85MuteSudro$^{D\flat}$
    86OpenSudro$^{D}$
     
    -

    - -

    - -
    -MIDI Controllers -

    - -

    -When specifying a MIDI Controller in a MIDISEQ or -MIDIVOICE command you can use the absolute value in (either as -a decimal number or in hexadecimal by prefixing the value with a -``0x''), or the symbolic name in the following tables. The tables have -been extracted from information at -http://www.midi.org/about-midi/table3.shtml. Note that all the -values in these tables are in hexadecimal notation. - -

    -Complete reference for this is not a part of -MMA . Please refer to a -detailed text on MIDI or the manual for your synthesizer. - -

    - -

    -Controllers, Alphabetically -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    AllNotesOff7b
    AllSoundsOff78
    AttackTime49
    Balance08
    BalanceLSB28
    Bank00
    BankLSB20
    Breath02
    BreathLSB22
    Brightness4a
    Chorus5d
    Ctrl10266
    Ctrl10367
    Ctrl10468
    Ctrl10569
    Ctrl1066a
    Ctrl1076b
    Ctrl1086c
    Ctrl1096d
    Ctrl1106e
    Ctrl1116f
    Ctrl11270
    Ctrl11371
    Ctrl11472
    Ctrl11573
    Ctrl11674
    Ctrl11775
    Ctrl11876
    Ctrl11977
    Ctrl140e
    Ctrl150f
    Ctrl2014
    Ctrl2115
    Ctrl2216
    Ctrl2317
    Ctrl2418
    Ctrl2519
    Ctrl261a
    Ctrl271b
    Ctrl281c
    Ctrl291d
    Ctrl303
    Ctrl301e
    Ctrl311f
    Ctrl3523
    Ctrl4129
    Ctrl462e
    Ctrl472f
    Ctrl5234
    Ctrl5335
    Ctrl5436
    Ctrl5537
    Ctrl5638
    Ctrl5739
    Ctrl583a
    Ctrl593b
    Ctrl603c
    Ctrl613d
    Ctrl623e
    Ctrl633f
    Ctrl794f
    Ctrl8555
    Ctrl8656
    Ctrl8757
    Ctrl8858
    Ctrl8959
    Ctrl909
    Ctrl905a
    Data06
    DataDec61
    DataInc60
    DataLSB26
    DecayTime4b
    Detune5e
    Effect10c
    Effect1LSB2c
    Effect20d
    Effect2LSB2d
    Expression0b
    ExpressionLSB2b
    Foot04
    FootLSB24
    General110
    General1LSB30
    General211
    General2LSB31
    General312
    General3LSB32
    General413
    General4LSB33
    General550
    General651
    General752
    General853
    Hold245
    Legato44
    LocalCtrl7a
    Modulation01
    ModulationLSB21
    NonRegLSB62
    NonRegMSB63
    OmniOff7c
    OmniOn7d
    Pan0a
    PanLSB2a
    Phaser5f
    PolyOff7e
    PolyOn7f
    Portamento05
    Portamento41
    PortamentoCtrl54
    PortamentoLSB25
    RegParLSB64
    RegParMSB65
    ReleaseTime48
    ResetAll79
    Resonance47
    Reverb5b
    SoftPedal43
    Sostenuto42
    Sustain40
    Tremolo5c
    Variation46
    VibratoDelay4e
    VibratoDepth4d
    VibratoRate4c
    Volume07
    VolumeLSB27
     
    -

    - -

    -Controllers, by Value -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    00Bank
    01Modulation
    02Breath
    03Ctrl3
    04Foot
    05Portamento
    06Data
    07Volume
    08Balance
    09Ctrl9
    0aPan
    0bExpression
    0cEffect1
    0dEffect2
    0eCtrl14
    0fCtrl15
    10General1
    11General2
    12General3
    13General4
    14Ctrl20
    15Ctrl21
    16Ctrl22
    17Ctrl23
    18Ctrl24
    19Ctrl25
    1aCtrl26
    1bCtrl27
    1cCtrl28
    1dCtrl29
    1eCtrl30
    1fCtrl31
    20BankLSB
    21ModulationLSB
    22BreathLSB
    23Ctrl35
    24FootLSB
    25PortamentoLSB
    26DataLSB
    27VolumeLSB
    28BalanceLSB
    29Ctrl41
    2aPanLSB
    2bExpressionLSB
    2cEffect1LSB
    2dEffect2LSB
    2eCtrl46
    2fCtrl47
    30General1LSB
    31General2LSB
    32General3LSB
    33General4LSB
    34Ctrl52
    35Ctrl53
    36Ctrl54
    37Ctrl55
    38Ctrl56
    39Ctrl57
    3aCtrl58
    3bCtrl59
    3cCtrl60
    3dCtrl61
    3eCtrl62
    3fCtrl63
    40Sustain
    41Portamento
    42Sostenuto
    43SoftPedal
    44Legato
    45Hold2
    46Variation
    47Resonance
    48ReleaseTime
    49AttackTime
    4aBrightness
    4bDecayTime
    4cVibratoRate
    4dVibratoDepth
    4eVibratoDelay
    4fCtrl79
    50General5
    51General6
    52General7
    53General8
    54PortamentoCtrl
    55Ctrl85
    56Ctrl86
    57Ctrl87
    58Ctrl88
    59Ctrl89
    5aCtrl90
    5bReverb
    5cTremolo
    5dChorus
    5eDetune
    5fPhaser
    60DataInc
    61DataDec
    62NonRegLSB
    63NonRegMSB
    64RegParLSB
    65RegParMSB
    66Ctrl102
    67Ctrl103
    68Ctrl104
    69Ctrl105
    6aCtrl106
    6bCtrl107
    6cCtrl108
    6dCtrl109
    6eCtrl110
    6fCtrl111
    70Ctrl112
    71Ctrl113
    72Ctrl114
    73Ctrl115
    74Ctrl116
    75Ctrl117
    76Ctrl118
    77Ctrl119
    78AllSoundsOff
    79ResetAll
    7aLocalCtrl
    7bAllNotesOff
    7cOmniOff
    7dOmniOn
    7ePolyOff
    7fPolyOn
     
    -

    -


    - next - up - previous
    - Next: Bibliography and Thanks - Up: Next: Symbols and Constants + Up: Reference Manual - Previous: Frequency Asked Questions + Previous: Creating Effects
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node27.html b/mma/docs/html/ref/node27.html index 7c5c62c..8798e66 100644 --- a/mma/docs/html/ref/node27.html +++ b/mma/docs/html/ref/node27.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Bibliography and Thanks - +Symbols and Constants + @@ -37,83 +37,3408 @@ original version by: Nikos Drakos, CBLU, University of Leeds previous
    Next: Command Summary + HREF="node28.html">Bibliography and Thanks Up: Reference Manual Previous: Symbols and Constants + HREF="node26.html">Frequency Asked Questions

    + +Subsections -

    -Bibliography and Thanks + + +
    + +

    + +
    +Symbols and Constants

    -I've had help from a lot of different people and sources in developing -this program. If I have missed listing you in the CONTRIB -file shipped with the -MMA distribution, please let me know and I'll -add it right away. I really want to do this! +This appendix is a reference to the chords that +MMA recognizes and +name/value tables for drum and instrument names. The tables have been +auto-generated by +MMA using the -D options.

    -I've also had the use of a number of reference materials: -

    -
    -
    Craig Anderson. MIDI for Musicians. Amsco Publishing, New -York, NY. + +

    +Chord Names +

    + +MMA recognizes standard chord names as listed below. The names are +case sensitive and must be entered in uppercase letters as shown: + +

    +A + A$\sharp$ + A$\flat$ + B + B$\sharp$ + B$\flat$ + C + C$\sharp$ + C$\flat$ + D + D$\sharp$ + D$\flat$ + E + E$\sharp$ + E$\flat$ + F + F$\sharp$ + F$\flat$ + G + G$\sharp$ + G$\flat$ + +

    +Please note that in your input files you must use a lowercase ``b'' or +an ``&'' to represent a $\flat$ and a ``#'' for a $\sharp$. + +

    +All ``7th'' chords are ``dominante 7th'' unless specifically noted as +``major''. A dominant 7th has a flattened 7th note (in a C7 chord this +is a b$\flat$; a C Major 7th chord has a b$\natural$). + +

    +For a more detailed listing of the chords, notes and scales you should +download the document www.mellowood.ca/mma/chords.pdf.gz. + +

    +The following types of chords are recognized (these are case sensitive +and must be in the mixed upper and lowercase shown): + +

    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    $\sharp$5Augmented triad.
    ($\flat$5)Major triad with flat 5th.
    +Augmented triad.
    +7An augmented chord (raised 5th) with a dominant 7th.
    +7$\flat$9$\sharp$11Augmented 7th with flat 9th and sharp 11th.
    +97th plus 9th with sharp 5th (same as aug9).
    +9M7An augmented chord (raised 5th) with a major 7th and 9th.
    +M7Major 7th with sharp 5th.
    119th chord plus 11th (3rd not voiced).
    11$\flat$97th chord plus flat 9th and 11th.
    137th (including 5th) plus 13th (the 9th and 11th are not voiced).
    13$\sharp$117th plus sharp 11th and 13th (9th not voiced).
    13$\sharp$97th (including 5th) plus 13th and sharp 9th (11th not voiced).
    13$\flat$57th with flat 5th, plus 13th (the 9th and 11th are not voiced).
    13$\flat$97th (including 5th) plus 13th and flat 9th (11th not voiced).
    13sus7sus, plus 9th and 13th
    13sus$\flat$97sus, plus flat 9th and 13th
    5Altered Fifth or Power Chord; root and 5th only.
    6Major tiad with added 6th.
    6(add9)6th with added 9th. This is sometimes notated as a slash chord in the form ``6/9''.
    696th with added 9th. This is sometimes notated as a slash chord in the form ``6/9''.
    77th.
    7$\sharp$117th plus sharp 11th (9th omitted).
    7$\sharp$5An augmented chord (raised 5th) with a dominant 7th.
    7$\sharp$5$\sharp$97th with sharp 5th and sharp 9th.
    7$\sharp$5$\flat$9An augmented chord (raised 5th) with a dominant 7th and flat 9th.
    7$\sharp$97th with sharp 9th.
    7$\sharp$9$\sharp$117th plus sharp 9th and sharp 11th.
    7$\sharp$9$\flat$137th with sharp 9th and flat 13th.
    7(omit3)7th with unvoiced 3rd.
    7+An augmented chord (raised 5th) with a dominant 7th.
    7+5An augmented chord (raised 5th) with a dominant 7th.
    7+97th with sharp 9th.
    7-57th, flat 5.
    7-97th with flat 9th.
    7alt7th with flat 5th and flat 9th.
    7$\flat$57th, flat 5.
    7$\flat$5$\sharp$97th with flat 5th and sharp 9th.
    7$\flat$5$\flat$97th with flat 5th and flat 9th.
    7$\flat$97th with flat 9th.
    7$\flat$9$\sharp$117th plus flat 9th and sharp 11th.
    7omit37th with unvoiced 3rd.
    7sus7th with suspended 4th, dominant 7th with 3rd raised half tone.
    7sus2A sus2 with dominant 7th added.
    7sus47th with suspended 4th, dominant 7th with 3rd raised half tone.
    7sus$\flat$97th with suspended 4th and flat 9th.
    97th plus 9th.
    9$\sharp$117th plus 9th and sharp 11th.
    9$\sharp$57th plus 9th with sharp 5th (same as aug9).
    9+57th plus 9th with sharp 5th (same as aug9).
    9-57th plus 9th with flat 5th.
    9$\flat$57th plus 9th with flat 5th.
    9sus7sus plus 9th.
    MMajor triad. This is the default and is used in the absense of any other chord type specification.
    M13Major 7th (including 5th) plus 13th (9th and 11th not voiced).
    M13$\sharp$11Major 7th plus sharp 11th and 13th (9th not voiced).
    M6Major tiad with added 6th.
    M7Major 7th.
    M7$\sharp$11Major 7th plus sharp 11th (9th omitted).
    M7$\sharp$5Major 7th with sharp 5th.
    M7(add13)7th (including 5th) plus 13th and flat 9th (11th not voiced).
    M7+5Major 7th with sharp 5th.
    M7-5Major 7th with a flat 5th.
    M7$\flat$5Major 7th with a flat 5th.
    M9Major 7th plus 9th.
    M9$\sharp$11Major 9th plus sharp 11th.
    add9Major chord plus 9th (no 7th.)
    augAugmented triad.
    aug7An augmented chord (raised 5th) with a dominant 7th.
    aug7$\sharp$9An augmented chord (raised 5th) with a dominant 7th and sharp 9th.
    aug7$\flat$9An augmented chord (raised 5th) with a dominant 7th and flat 9th.
    aug97th plus 9th with sharp 5th (same as aug9).
    aug9M7An augmented chord (raised 5th) with a major 7th and 9th.
    dimA dim7, not a triad!
    dim3Diminished triad (non-standard notation).
    dim7Diminished seventh.
    dim7(addM7)Diminished tirad with added Major 7th.
    mMinor triad.
    m$\sharp$5Minor triad with augmented 5th.
    m$\sharp$7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m(add9)Minor triad plus 9th (no 7th).
    m($\flat$5)Minor triad with flat 5th (aka dim).
    m(maj7)Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m(sus9)Minor triad plus 9th (no 7th).
    m+5Minor triad with augmented 5th.
    m+7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    m+7$\sharp$9Augmented minor 7 plus sharp 9th.
    m+7$\flat$9Augmented minor 7 plus flat 9th.
    m+7$\flat$9$\sharp$11Augmented minor 7th with flat 9th and sharp 11th.
    m119th with minor 3rd, plus 11th.
    m11$\flat$5Minor 7th with flat 5th plus 11th.
    m13Minor 7th (including 5th) plus 13th (9th and 11th not voiced).
    m6Minor 6th (flat 3rd plus a 6th).
    m6(add9)Minor 6th with added 9th. This is sometimes notated as a slash chord in the form ``m6/9''.
    m69Minor 6th with added 9th. This is sometimes notated as a slash chord in the form ``m6/9''.
    m7Minor 7th (flat 3rd plus dominant 7th).
    m7$\sharp$9Minor 7th with added sharp 9th.
    m7($\sharp$9)Minor 7th with added sharp 9th.
    m7(add11)Minor 7th plus 11th.
    m7(add13)Minor 7th plus 13th.
    m7($\flat$9)Minor 7th with added flat 9th.
    m7(omit5)Minor 7th with unvoiced 5th.
    m7-5Minor 7th, flat 5 (aka 1/2 diminished).
    m7$\flat$5Minor 7th, flat 5 (aka 1/2 diminished).
    m7$\flat$5$\flat$9Minor 7th with flat 5th and flat 9th.
    m7$\flat$9Minor 7th with added flat 9th.
    m7$\flat$9$\sharp$11Minor 7th plus flat 9th and sharp 11th.
    m7omit5Minor 7th with unvoiced 5th.
    m9Minor triad plus 7th and 9th.
    m9$\sharp$11Minor 7th plus 9th and sharp 11th.
    m9$\flat$5Minor triad, flat 5, plus 7th and 9th.
    mM7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    mM7(add9)Minor Triad plus Major 7th and 9th.
    maj13Major 7th (including 5th) plus 13th (9th and 11th not voiced).
    maj7Major 7th.
    maj9Major 7th plus 9th.
    m$\flat$5Minor triad with flat 5th (aka dim).
    min$\sharp$7Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    min(maj7)Minor Triad plus Major 7th. You will also see this printed as ``m(maj7)'', ``m+7'', ``min(maj7)'' and ``min$\sharp$7'' (which +MMA accepts); as well as the +MMA invalid forms: ``-($\Delta$7)'', and ``min$\natural$7''.
    omit3(add9)Triad: root, 5th and 9th.
    omit3add9Triad: root, 5th and 9th.
    susSuspended 4th, major triad with the 3rd raised half tone.
    sus2Suspended 2nd, major triad with the major 2nd above the root substituted for 3rd.
    sus4Suspended 4th, major triad with the 3rd raised half tone.
    sus97sus plus 9th.
     
    +In modern pop charts the ``M'' in a major 7th chord (and other major +chords) is often represented by a ``$\Delta$''. When entering these +chords, just replace the ``$\Delta$'' with an ``M''. For example, +change ``G$\Delta$7'' to ``GM7''. + +

    +A chord name without a type is interpreted as a major chord (or +triad). For example, the chord ``C'' is identical to ``CM''. + +

    + +MMA has an large set of defined chords. However, you can add your +own with the DEFCHORD command, details + here. + +

    + +

    +
    +Octave Adjustment +

    + +

    +Depending on the key and chord sequence, a chord may end up in the +wrong octave. This is caused by +MMA 's internal routines which +create a chord: all of the tables are maintained for a ``C'' chord and +the others are derived from that point by subtracting or adding a +constant. To compensate you can add a leading ``-'' or ``+'' to the +chordname to force the movement of that chord and scale up or down an +octave. + +

    +For example, the following line will move the chord up and down for +the third and fourth beats: + +

    + + + +
    + Cm Fm -Gm +D7 + +
    + +

    +The effect of octave shifting is also highly dependent on the voicing +options in effect for the track. + +

    +You'll have to listen to the +MMA output to detemine when +and where to use this adjustment. Hopefully, it won't be needed all +that much. + +

    +If you have a large number of chords to adjust, use the CHORDADJUST +command , here. + +

    + +

    +Altered Chords +

    + +

    +According to Standardized Chord Symbol Notation altered +chords should be written in the form +Cmi +$^{7}(^{\flat{}9}_{\sharp{}5})$. However, this is pretty hard to type +(and parse). So, we've used the convention that the altered +intervals should be written in numerical order: +Cm$\sharp$5$\flat$9. Also, note that we use ``m'' for ``minor'' which +appears to be more the conventional method than ``mi''. + +

    + +

    +Diminished Chords +

    + +

    +In most pop and jazz charts it is assumed that a diminished chord is +always a diminished 7th ...a diminished triad is never played. + +MMA continues this, sometimes erroneous +assumption.A.1You can change the behaviour in several ways: change the chord notes and scale for a +``dim'' from a dim7 to a triad by following the instructions +here; use the slightly oddball +notation of ``m$\flat$5'' which generates a ``diminished tirad''; or +use the more-oddball notation ``dim3''. + +

    +Notational notes: In printed music a ``diminished'' chord is sometimes +represented with a small circle symbol (eg. +``FO'') and a ``half-diminished'' as a +small slashed circle (e.g., ``CØ''). + +

    +A half-diminished chord in +MMA is specified with the notation +``m7$\flat$5''. + +

    + +

    +Slash Chords +

    + +

    +Charts sometimes use slash chords in the form ``Am/E''. This +notation is used, mainly, to indicate chord inversions. For example, +the chord notes in ``Am/E'' become ``E'', ``A'' and ''C'' with the +``E'' taking the root position. +MMA will accept chords of this type. +However, you may not notice any difference in the generated tracks due +to the inversions used by the current pattern. + +

    +You may also encounter slash chords where the slash-part of the chord +is not a note in the chord. Consider the ambiguous notation +``Dm/C''. The composer (or copyist) might mean to add a ``C'' bass +note to a ``Dm'' chord, or she might mean ``Dm7'', or even an inverted +``Dm7''. +MMA will handle these ...almost perfectly. When the +``slash'' part of the chord indicates a note which is not a +note in the chord, +MMA assumes that the indicated note should be +used in the bass line. Since each chord generated by +MMA also has a +``scale'' associated with it for use by bass and scale patterns this +works. For example, a C Major chord will have the scale ``c, d, e, f, +g, a, b''; a C Minor chord has the same scale, but with an e$\flat$. +If the slash note is contained in the scale, the scale will be rotated +so that the note becomes the ``root'' note. + +

    +A warning message will be printed if the note is not in both the chord +and the scale. + +

    +Another notation you may see is something like ``Dm/9''. Again, +the meaning is not clear. It probably means a ``Dm9'', or ``Dm9/E'' +... but since +MMA isn't sure this notation will generate an +error. + +

    +Please note that for fairly obvious reasons you cannot have both slash +notation and an inversion (see the next section). + +

    +For more details on ``slash chords'' your favorite +music theory book or teacher is highly recommended! + +

    + +

    +Chord Inversions +

    + +

    +Instead of using a slash chord you can specify an inversion to use with a chord. +The notation is simply an ``>'' and a number between -5 and 5 immediately following +the chord name. + +

    +The chord will be ``rotated'' as specified by the value after the ``>''. + +

    +For example, the chord ``C>2'' will generate the notes G, C and E; ``F>-1'' +gives C, F and A. + +

    +There is an important difference between this option and a slash chord: in inversions neither +the root note nor the associated scale are modified. + +

    + +

    + +
    +MIDI Voices +

    + +

    +When setting a voice for a track (IE Bass Voice NN), you can specify +the patch to use with a symbolic constant. Any combination of upper +and lower case is permitted. The following are the names with the +equivalent voice numbers: + +

    + +

    + +

    +Voices, Alphabetically +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    5thSawWave86
    Accordion21
    AcousticBass32
    AgogoBells113
    AltoSax65
    Applause/Noise126
    Atmosphere99
    BagPipe109
    Bandoneon23
    Banjo105
    BaritoneSax67
    Bass&Lead87
    Bassoon70
    BirdTweet123
    BottleBlow76
    BowedGlass92
    BrassSection61
    BreathNoise121
    Brightness100
    Celesta8
    Cello42
    Charang84
    ChifferLead83
    ChoirAahs52
    ChurchOrgan19
    Clarinet71
    Clavinet7
    CleanGuitar27
    ContraBass43
    Crystal98
    DistortonGuitar30
    EPiano5
    EchoDrops102
    EnglishHorn69
    Fantasia88
    Fiddle110
    FingeredBass33
    Flute73
    FrenchHorn60
    FretlessBass35
    Glockenspiel9
    Goblins101
    GuitarFretNoise120
    GuitarHarmonics31
    GunShot127
    HaloPad94
    Harmonica22
    HarpsiChord6
    HelicopterBlade125
    Honky-TonkPiano3
    IceRain96
    JazzGuitar26
    Kalimba108
    Koto107
    Marimba12
    MelodicTom1117
    MetalPad93
    MusicBox10
    MutedGuitar28
    MutedTrumpet59
    NylonGuitar24
    Oboe68
    Ocarina79
    OrchestraHit55
    OrchestralHarp46
    Organ116
    Organ217
    Organ318
    OverDriveGuitar29
    PanFlute75
    Piano10
    Piano21
    Piano32
    Piccolo72
    PickedBass34
    PizzicatoString45
    PolySynth90
    Recorder74
    ReedOrgan20
    ReverseCymbal119
    RhodesPiano4
    Santur15
    SawWave81
    SeaShore122
    Shakuhachi77
    Shamisen106
    Shanai111
    Sitar104
    SlapBass136
    SlapBass237
    SlowStrings49
    SoloVoice85
    SopranoSax64
    SoundTrack97
    SpaceVoice91
    SquareWave80
    StarTheme103
    SteelDrums114
    SteelGuitar25
    Strings48
    SweepPad95
    SynCalliope82
    SynthBass138
    SynthBass239
    SynthBrass162
    SynthBrass263
    SynthDrum118
    SynthStrings150
    SynthStrings251
    SynthVox54
    TaikoDrum116
    TelephoneRing124
    TenorSax66
    Timpani47
    TinkleBell112
    TremoloStrings44
    Trombone57
    Trumpet56
    Tuba58
    TubularBells14
    Vibraphone11
    Viola41
    Violin40
    VoiceOohs53
    WarmPad89
    Whistle78
    WoodBlock115
    Xylophone13
     
    +

    + +

    +Voices, By MIDI Value +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    0Piano1
    1Piano2
    2Piano3
    3Honky-TonkPiano
    4RhodesPiano
    5EPiano
    6HarpsiChord
    7Clavinet
    8Celesta
    9Glockenspiel
    10MusicBox
    11Vibraphone
    12Marimba
    13Xylophone
    14TubularBells
    15Santur
    16Organ1
    17Organ2
    18Organ3
    19ChurchOrgan
    20ReedOrgan
    21Accordion
    22Harmonica
    23Bandoneon
    24NylonGuitar
    25SteelGuitar
    26JazzGuitar
    27CleanGuitar
    28MutedGuitar
    29OverDriveGuitar
    30DistortonGuitar
    31GuitarHarmonics
    32AcousticBass
    33FingeredBass
    34PickedBass
    35FretlessBass
    36SlapBass1
    37SlapBass2
    38SynthBass1
    39SynthBass2
    40Violin
    41Viola
    42Cello
    43ContraBass
    44TremoloStrings
    45PizzicatoString
    46OrchestralHarp
    47Timpani
    48Strings
    49SlowStrings
    50SynthStrings1
    51SynthStrings2
    52ChoirAahs
    53VoiceOohs
    54SynthVox
    55OrchestraHit
    56Trumpet
    57Trombone
    58Tuba
    59MutedTrumpet
    60FrenchHorn
    61BrassSection
    62SynthBrass1
    63SynthBrass2
    64SopranoSax
    65AltoSax
    66TenorSax
    67BaritoneSax
    68Oboe
    69EnglishHorn
    70Bassoon
    71Clarinet
    72Piccolo
    73Flute
    74Recorder
    75PanFlute
    76BottleBlow
    77Shakuhachi
    78Whistle
    79Ocarina
    80SquareWave
    81SawWave
    82SynCalliope
    83ChifferLead
    84Charang
    85SoloVoice
    865thSawWave
    87Bass&Lead
    88Fantasia
    89WarmPad
    90PolySynth
    91SpaceVoice
    92BowedGlass
    93MetalPad
    94HaloPad
    95SweepPad
    96IceRain
    97SoundTrack
    98Crystal
    99Atmosphere
    100Brightness
    101Goblins
    102EchoDrops
    103StarTheme
    104Sitar
    105Banjo
    106Shamisen
    107Koto
    108Kalimba
    109BagPipe
    110Fiddle
    111Shanai
    112TinkleBell
    113AgogoBells
    114SteelDrums
    115WoodBlock
    116TaikoDrum
    117MelodicTom1
    118SynthDrum
    119ReverseCymbal
    120GuitarFretNoise
    121BreathNoise
    122SeaShore
    123BirdTweet
    124TelephoneRing
    125HelicopterBlade
    126Applause/Noise
    127GunShot
     
    +

    + +

    + +
    +Drum Notes +

    + +

    +When defining a drum tone, you can specify the patch to use with a +symbolic constant. Any combination of upper and lower case is +permitted. In addition to the drum tone name and the MIDI value, the +equivalent ``name'' in +$^{superscript}$ is included. The ``names'' may help you +find the tones on your keyboard. + +

    + +

    +Drum Notes, Alphabetically +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Cabasa69$^{A}$
    Castanets84$^{C}$
    ChineseCymbal52$^{E}$
    Claves75$^{E\flat}$
    ClosedHiHat42$^{G\flat}$
    CowBell56$^{A\flat}$
    CrashCymbal149$^{D\flat}$
    CrashCymbal257$^{A}$
    HandClap39$^{E\flat}$
    HighAgogo67$^{G}$
    HighBongo60$^{C}$
    HighQ27$^{E\flat}$
    HighTimbale65$^{F}$
    HighTom150$^{D}$
    HighTom248$^{C}$
    HighWoodBlock76$^{E}$
    JingleBell83$^{B}$
    KickDrum136$^{C}$
    KickDrum235$^{B}$
    LongGuiro74$^{D}$
    LongLowWhistle72$^{C}$
    LowAgogo68$^{A\flat}$
    LowBongo61$^{D\flat}$
    LowConga64$^{E}$
    LowTimbale66$^{G\flat}$
    LowTom143$^{G}$
    LowTom241$^{F}$
    LowWoodBlock77$^{F}$
    Maracas70$^{B\flat}$
    MetronomeBell34$^{B\flat}$
    MetronomeClick33$^{A}$
    MidTom147$^{B}$
    MidTom245$^{A}$
    MuteCuica78$^{G\flat}$
    MuteHighConga62$^{D}$
    MuteSudro85$^{D\flat}$
    MuteTriangle80$^{A\flat}$
    OpenCuica79$^{G}$
    OpenHiHat46$^{B\flat}$
    OpenHighConga63$^{E\flat}$
    OpenSudro86$^{D}$
    OpenTriangle81$^{A}$
    PedalHiHat44$^{A\flat}$
    RideBell53$^{F}$
    RideCymbal151$^{E\flat}$
    RideCymbal259$^{B}$
    ScratchPull30$^{G\flat}$
    ScratchPush29$^{F}$
    Shaker82$^{B\flat}$
    ShortGuiro73$^{D\flat}$
    ShortHiWhistle71$^{B}$
    SideKick37$^{D\flat}$
    Slap28$^{E}$
    SnareDrum138$^{D}$
    SnareDrum240$^{E}$
    SplashCymbal55$^{G}$
    SquareClick32$^{A\flat}$
    Sticks31$^{G}$
    Tambourine54$^{G\flat}$
    VibraSlap58$^{B\flat}$
     
    +

    + +

    +Drum Notes, by MIDI Value +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    27HighQ$^{E\flat}$
    28Slap$^{E}$
    29ScratchPush$^{F}$
    30ScratchPull$^{G\flat}$
    31Sticks$^{G}$
    32SquareClick$^{A\flat}$
    33MetronomeClick$^{A}$
    34MetronomeBell$^{B\flat}$
    35KickDrum2$^{B}$
    36KickDrum1$^{C}$
    37SideKick$^{D\flat}$
    38SnareDrum1$^{D}$
    39HandClap$^{E\flat}$
    40SnareDrum2$^{E}$
    41LowTom2$^{F}$
    42ClosedHiHat$^{G\flat}$
    43LowTom1$^{G}$
    44PedalHiHat$^{A\flat}$
    45MidTom2$^{A}$
    46OpenHiHat$^{B\flat}$
    47MidTom1$^{B}$
    48HighTom2$^{C}$
    49CrashCymbal1$^{D\flat}$
    50HighTom1$^{D}$
    51RideCymbal1$^{E\flat}$
    52ChineseCymbal$^{E}$
    53RideBell$^{F}$
    54Tambourine$^{G\flat}$
    55SplashCymbal$^{G}$
    56CowBell$^{A\flat}$
    57CrashCymbal2$^{A}$
    58VibraSlap$^{B\flat}$
    59RideCymbal2$^{B}$
    60HighBongo$^{C}$
    61LowBongo$^{D\flat}$
    62MuteHighConga$^{D}$
    63OpenHighConga$^{E\flat}$
    64LowConga$^{E}$
    65HighTimbale$^{F}$
    66LowTimbale$^{G\flat}$
    67HighAgogo$^{G}$
    68LowAgogo$^{A\flat}$
    69Cabasa$^{A}$
    70Maracas$^{B\flat}$
    71ShortHiWhistle$^{B}$
    72LongLowWhistle$^{C}$
    73ShortGuiro$^{D\flat}$
    74LongGuiro$^{D}$
    75Claves$^{E\flat}$
    76HighWoodBlock$^{E}$
    77LowWoodBlock$^{F}$
    78MuteCuica$^{G\flat}$
    79OpenCuica$^{G}$
    80MuteTriangle$^{A\flat}$
    81OpenTriangle$^{A}$
    82Shaker$^{B\flat}$
    83JingleBell$^{B}$
    84Castanets$^{C}$
    85MuteSudro$^{D\flat}$
    86OpenSudro$^{D}$
     
    +

    + +

    + +
    +MIDI Controllers +

    + +

    +When specifying a MIDI Controller in a MIDISEQ or +MIDIVOICE command you can use the absolute value in (either as +a decimal number or in hexadecimal by prefixing the value with a +``0x''), or the symbolic name in the following tables. The tables have +been extracted from information at +http://www.midi.org/about-midi/table3.shtml. Note that all the +values in these tables are in hexadecimal notation. + +

    +Complete reference for this is not a part of +MMA . Please refer to a +detailed text on MIDI or the manual for your synthesizer. + +

    + +

    +Controllers, Alphabetically +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    AllNotesOff7b
    AllSoundsOff78
    AttackTime49
    Balance08
    BalanceLSB28
    Bank00
    BankLSB20
    Breath02
    BreathLSB22
    Brightness4a
    Chorus5d
    Ctrl10266
    Ctrl10367
    Ctrl10468
    Ctrl10569
    Ctrl1066a
    Ctrl1076b
    Ctrl1086c
    Ctrl1096d
    Ctrl1106e
    Ctrl1116f
    Ctrl11270
    Ctrl11371
    Ctrl11472
    Ctrl11573
    Ctrl11674
    Ctrl11775
    Ctrl11876
    Ctrl11977
    Ctrl140e
    Ctrl150f
    Ctrl2014
    Ctrl2115
    Ctrl2216
    Ctrl2317
    Ctrl2418
    Ctrl2519
    Ctrl261a
    Ctrl271b
    Ctrl281c
    Ctrl291d
    Ctrl303
    Ctrl301e
    Ctrl311f
    Ctrl3523
    Ctrl4129
    Ctrl462e
    Ctrl472f
    Ctrl5234
    Ctrl5335
    Ctrl5436
    Ctrl5537
    Ctrl5638
    Ctrl5739
    Ctrl583a
    Ctrl593b
    Ctrl603c
    Ctrl613d
    Ctrl623e
    Ctrl633f
    Ctrl794f
    Ctrl8555
    Ctrl8656
    Ctrl8757
    Ctrl8858
    Ctrl8959
    Ctrl909
    Ctrl905a
    Data06
    DataDec61
    DataInc60
    DataLSB26
    DecayTime4b
    Detune5e
    Effect10c
    Effect1LSB2c
    Effect20d
    Effect2LSB2d
    Expression0b
    ExpressionLSB2b
    Foot04
    FootLSB24
    General110
    General1LSB30
    General211
    General2LSB31
    General312
    General3LSB32
    General413
    General4LSB33
    General550
    General651
    General752
    General853
    Hold245
    Legato44
    LocalCtrl7a
    Modulation01
    ModulationLSB21
    NonRegLSB62
    NonRegMSB63
    OmniOff7c
    OmniOn7d
    Pan0a
    PanLSB2a
    Phaser5f
    PolyOff7e
    PolyOn7f
    Portamento05
    Portamento41
    PortamentoCtrl54
    PortamentoLSB25
    RegParLSB64
    RegParMSB65
    ReleaseTime48
    ResetAll79
    Resonance47
    Reverb5b
    SoftPedal43
    Sostenuto42
    Sustain40
    Tremolo5c
    Variation46
    VibratoDelay4e
    VibratoDepth4d
    VibratoRate4c
    Volume07
    VolumeLSB27
     
    +

    + +

    +Controllers, by Value +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    00Bank
    01Modulation
    02Breath
    03Ctrl3
    04Foot
    05Portamento
    06Data
    07Volume
    08Balance
    09Ctrl9
    0aPan
    0bExpression
    0cEffect1
    0dEffect2
    0eCtrl14
    0fCtrl15
    10General1
    11General2
    12General3
    13General4
    14Ctrl20
    15Ctrl21
    16Ctrl22
    17Ctrl23
    18Ctrl24
    19Ctrl25
    1aCtrl26
    1bCtrl27
    1cCtrl28
    1dCtrl29
    1eCtrl30
    1fCtrl31
    20BankLSB
    21ModulationLSB
    22BreathLSB
    23Ctrl35
    24FootLSB
    25PortamentoLSB
    26DataLSB
    27VolumeLSB
    28BalanceLSB
    29Ctrl41
    2aPanLSB
    2bExpressionLSB
    2cEffect1LSB
    2dEffect2LSB
    2eCtrl46
    2fCtrl47
    30General1LSB
    31General2LSB
    32General3LSB
    33General4LSB
    34Ctrl52
    35Ctrl53
    36Ctrl54
    37Ctrl55
    38Ctrl56
    39Ctrl57
    3aCtrl58
    3bCtrl59
    3cCtrl60
    3dCtrl61
    3eCtrl62
    3fCtrl63
    40Sustain
    41Portamento
    42Sostenuto
    43SoftPedal
    44Legato
    45Hold2
    46Variation
    47Resonance
    48ReleaseTime
    49AttackTime
    4aBrightness
    4bDecayTime
    4cVibratoRate
    4dVibratoDepth
    4eVibratoDelay
    4fCtrl79
    50General5
    51General6
    52General7
    53General8
    54PortamentoCtrl
    55Ctrl85
    56Ctrl86
    57Ctrl87
    58Ctrl88
    59Ctrl89
    5aCtrl90
    5bReverb
    5cTremolo
    5dChorus
    5eDetune
    5fPhaser
    60DataInc
    61DataDec
    62NonRegLSB
    63NonRegMSB
    64RegParLSB
    65RegParMSB
    66Ctrl102
    67Ctrl103
    68Ctrl104
    69Ctrl105
    6aCtrl106
    6bCtrl107
    6cCtrl108
    6dCtrl109
    6eCtrl110
    6fCtrl111
    70Ctrl112
    71Ctrl113
    72Ctrl114
    73Ctrl115
    74Ctrl116
    75Ctrl117
    76Ctrl118
    77Ctrl119
    78AllSoundsOff
    79ResetAll
    7aLocalCtrl
    7bAllNotesOff
    7cOmniOff
    7dOmniOn
    7ePolyOff
    7fPolyOn
     
    +

    + +

    +


    Footnotes

    +
    +
    ... +assumption.A.1
    +
    Sometimes a reliable source agrees with us ... in +this case Standardized Chord Symbol Notation is quite clear +that ``dim'' is a Diminished 7th and a diminished triad should be +notated as mi$^{(\flat{}5)}$. +
    -
    -
    William Duckworth. Music Fundamentals. Wadsworth Publishing, -Belomnt, CA. - -

    -

    -
    -
    Michael Esterowitz. How To Play From A Fakebook. Ekay Music, -Inc. Katonah, NY. - -

    -

    -
    -
    Pete Goodliffe. MIDI documentation (for the TSE3 library). -http://tse3.sourceforge.net/. - -

    -

    -
    -
    Norman Lloyd. The Golden Encyclopedia Of Music. Golden Press, -New York, NY. - -

    -

    -
    -
    The MIDI Manufacturers Association. Various papers, tables and - other information. http://www.midi.org/. - -

    -

    -
    -
    Victor López. Latin Rhythms: Mystery Unraveled. Alfred Publishing Company. These are handout notes from the 2005 Midwest Clinic 59th Annual Conference, Chicago, Illinois, December 16, 2005. A PDF of this document is available on various internet sites. - -

    -

    -
    - -

    -And, finally, to all those music teachers my parents and I paid for, -and the many people who have helped by listening and providing helpful -suggestions and encouragement in my musical pursuits for the -last 40 plus years that I've been banging, squeezing and blowing. You know -who you are--thanks. - -

    -


    +

    @@ -126,15 +3451,15 @@ who you are--thanks. previous
    Next: Command Summary + HREF="node28.html">Bibliography and Thanks Up: Reference Manual Previous: Symbols and Constants + HREF="node26.html">Frequency Asked Questions
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node28.html b/mma/docs/html/ref/node28.html index a9ab42b..110e230 100644 --- a/mma/docs/html/ref/node28.html +++ b/mma/docs/html/ref/node28.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -Command Summary - +Bibliography and Thanks + @@ -26,409 +26,121 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: About this document ... - Up: Next: Command Summary + Up: Reference Manual - Previous: Bibliography and Thanks + Previous: Symbols and Constants

    -Command Summary +Bibliography and Thanks

    -

    -TRACK Accent <beat adj> Adjust volume for specified beat(s) in each bar of a track. -
    -

    -

    AdjustVolume <name=value> Set the volume ratios for named volume(s). -
    -

    -

    AllTracks <cmds> Applies cmds(s) to all active tracks. -
    -

    -

    TRACK Articulate <value> ... Duration/holding-time of notes. -
    -

    -

    Author <stuff> A specialized comment used by documentation extractors. -
    -

    -

    AutoSoloTracks <tracks> Set the tracks used in auto assigning solo/melody notes. -
    -

    -

    BarNumbers Leading <number> on data line (ignored). -
    -

    -

    BarRepeat Data bars can repeat with a ``* nn'' -
    -

    -

    BeatAdjust <beats> Adjust current pointer by <beats>. -
    -

    -

    Begin Delimits the start of a block. -
    -

    -

    TRACK ChShare <track> Force track to share MIDI track. -
    -

    -

    TRACK Channel <1..16> Force the MIDI channel for a track. -
    -

    -

    TRACK ChannelPref <1..16> Set a preferred channel for track. -
    -

    -

    ChordAdjust <Tonic=adj> Adjust center point of selected chords. -
    -

    -

    Comment <text> ignore/discard <text>. -
    -

    -

    TRACK Compress <value> ... Enable chord compression for track. -
    -

    -

    TRACK Copy <source> Overlay <source> track to sepecified track. -
    -

    -

    [TRACK] Cresc <[start] end count> Decrease volume over bars. -
    -

    -

    [TRACK] Cut <beat> Force all notes off at <beat> offset. -
    -

    -

    Debug <options> Selectively enable/disable debugging levels. -
    -

    -

    Dec <name> [value] Decrement the value of variable <name> by 1 or <value>. -
    -

    -

    [TRACK] Decresc <[start] end count> Increase volume over bars. -
    -

    -

    DefChord <name notelist scalelist> Define a new chord. -
    -

    -

    DefGroove <name> [Description] Define a new groove. -
    -

    -

    TRACK Define <pattern> Define a pattern to use in a track. -
    -

    -

    TRACK Delete Delete specified track for future use. -
    -

    -

    TRACK Direction [Up | Down | BOTH | RANDOM] ... Set direction of runs in Scale, Apreggio and Walk tracks. -
    -

    -

    Doc <stuff> A special comment used by documentation extractors. -
    -

    -

    DrumTR <old>=<new> translates MIDI drum tone <old> to <new>. -
    -

    -

    TRACK DrumType Force a solo track to be a drum track. -
    -

    -

    DrumVolTr <tone>=<adj> ... adjusts volume for specified drum tone. -
    -

    -

    TRACK DupRoot <octave> Duplicate the root note in a chord to lower/higher octave. -
    -

    -

    End Delimits the end of a block. -
    -

    -

    EndIf End processing of ``IF''. -
    -

    -

    EndMset End of a ``Mset'' section. -
    -

    -

    EndRepeat [count] End a repeated section. -
    -

    -

    Eof Immediately stop/end input file. -
    -

    -

    Fermata <beat> <count> <adjustment> Expand <beat> for <count> by <adjustment percentage. -
    -

    -

    TRACK ForceOut Force voicing and raw data output for track. -
    -

    -

    Goto <name> jump processing to <name>. -
    -

    -

    Groove <name> Enable a previously defined groove. -
    -

    -

    TRACK Harmony [Option] ... Set harmony for Bass, Walk, Arpeggio, Scale, Solo and Melody tracks. -
    -

    -

    TRACK HarmonyOnly <Option> ... Force track to sound only harmony notes from current pattern. -
    -

    -

    TRACK HarmonyVolume <Percentage> ... Set the volume used by harmony notes. -
    -

    -

    If <test> <cmds> Test condition and process <cmds>. -
    -

    -

    IfEnd End processing of ``IF''. -
    -

    -

    Inc <name> [value] Increment the value of variable <name> by 1 or <value>. -
    -

    -

    Include <file> Include a file. -
    -

    -

    TRACK Invert <value> ... set the inversion factor for chords in track. -
    -

    -

    KeySig <sig> Set the key signature. -
    -

    -

    Label <name> Set <name> as a label for ``GOTO''. -
    -

    -

    TRACK Limit <value> Limit number of notes used in a chord to <value>. -
    -

    -

    Lyric <options> Set various lyrics options. -
    -

    -

    MIDI <values> Send raw MIDI commands to MIDI meta-track. -
    -

    -

    TRACK MIDIClear <Beat Controller Data> Set command (or series) of MIDI commands to send when track is completed. -
    -

    -

    MIDIFile <option> Set various MIDI file generation options. -
    -

    -

    TRACK MIDIGlis <1..127> Set MIDI portamento (glissando) value for track. -
    -

    -

    TRACK MIDIInc <File> <Options> Include an existing MIDI file into a track. -
    -

    -

    MIDIMark [offset] Label Inserts Label into the MIDI track. -
    -

    -

    TRACK MIDIPan <0..127> Set MIDI pan/balance for track. -
    -

    -

    TRACK MIDISeq <Beat Controller Data> options> ... Set MIDI controller data for a track. -
    -

    -

    MIDISplit <channel list> Force split output for track. -
    -

    -

    TRACK MIDITName <string> Assigns an alternate name to a MIDI track. -
    -

    -

    TRACK MIDIVoice <Beat Controller Data> Set ``one-time'' MIDI controller command for track. -
    -

    -

    TRACK MIDIVolume <1..128> Set MIDI volume for track. -
    -

    -

    TRACK Mallet <Rate=nn | Decay=nns> Set mallet repeat for track. -
    -

    -

    MmaEnd <file> Set filename to process after main file completed. -
    -

    -

    MmaStart <file> Set file to include before processing main file. -
    -

    -

    Mset <name> <lines> Set <variable> to series of lines. -
    -

    -

    MsetEnd End of a ``Mset'' section. -
    -

    -

    TRACK NoteSpan <start> <end> set MIDI range of notes for track. -
    -

    -

    TRACK Octave <0..10> ... Set the octave for track. -
    -

    -

    TRACK Off Disable note generation for specified track. -
    -

    -

    TRACK On Enable note generation for specified track. -
    -

    -

    Print <stuff> Print <stuff> to output during compile. Useful for debugging. -
    -

    -

    PrintActive Print list of active tracks to output. -
    -

    -

    PrintChord <name(s)> Print the chord and scale for specific chord types. -
    -

    -

    TRACK RSkip <Value> ... Skip/silence random percentage of notes. -
    -

    -

    TRACK RTime <Value] ... -
    -

    -

    TRACK RVolume <adj> ... Set volume randomization for track. -
    -

    -

    TRACK Range <value> Set number of octaves used in Scale and Arpeggio tracks. -
    -

    -

    Repeat Start a repeated section. -
    -

    -

    RepeatEnd [count] End a repeated section. -
    -

    -

    RepeatEnding Start a repeat-ending. -
    -

    -

    TRACK Riff <pattern> Define a special pattern to use in track for next bar. -
    -

    -

    RndSeed <Value> ... Seed random number generator. -
    -

    -

    RndSet <variable> <list of values> Randomly set variable. -
    -

    -

    TRACK ScaleType <Chromatic | Auto> ... Set type of scale. Only for Scale tracks. -
    -

    -

    Seq Set the sequence point (bar pattern number). -
    -

    -

    [TRACK] SeqClear Clears sequence for track (or all tracks). -
    -

    -

    [TRACK] SeqRnd <On/Off/Tracks> Enable random seqeuence selection for track (or all tracks). -
    -

    -

    [TRACK] SeqRndWeight <list of values> Sets the randomization weight for track or global. -
    -

    -

    SeqSize <value> Set the number of bars in a sequence. -
    -

    -

    TRACK Sequence <pattern> ... Set pattern(s) to use for track. -
    -

    -

    Set <name> <stuff> Set the variable <name> to <stuff>. -
    -

    -

    SetAutoLibPath <path> Set the Auto-Include file path. -
    -

    -

    SetIncPath <path> Set the path for included files. -
    -

    -

    SetLibPath <path> Set the path to the style file library. -
    -

    -

    SetOutPath <path> Set the output filename. -
    -

    -

    ShowVars Display user defined variables. -
    -

    -

    StackValue <stuff> Push <stuff> onto a temporary stack. Remove with special macro $_StackValue. -
    -

    -

    TRACK Strum <value> ... Set the strumming factor for Chord tracks. -
    -

    -

    SwingMode <on/off> Set swing mode timing. -
    -

    -

    Tempo <rate> Set the rate in beats per minute. -
    -

    -

    Time <count> Set number of beats in a bar. -
    -

    -

    TimeSig <nn dd> Set the MIDI timesignature (not used by MMA). -
    -

    -

    TRACK Tone <Note> ... Set the drum-tone to use in a sequence. -
    -

    -

    Transpose <value> Transpose all tracks to a different key. -
    -

    -

    UnSet <name> Remove the variable <name>. -
    -

    -

    [TRACK] Unify <On | Off> ... Unify overlapping notes. -
    -

    -

    Use <file> Include/import an existing .mma file. -
    -

    -

    VExpand <on/off> Set variable expansion. -
    -

    -

    TRACK Voice <instrument> ... Set MIDI voice for track. -
    -

    -

    VoiceTr <old=new> ... - translates MIDI instrument <old> to <new>. -
    -

    -

    VoiceVolTr <voice>=<adj> ... - adjusts volume for specified voice. -
    -

    -

    TRACK Voicing <options. Set the voicing for a chord track. -
    -

    -

    [TRACK] Volume <value> ... Set the volume for a track or all tracks. -
    -

    -

    -
    +I've had help from a lot of different people and sources in developing +this program. If I have missed listing you in the CONTRIB +file shipped with the +MMA distribution, please let me know and I'll +add it right away. I really want to do this! + +

    +I've also had the use of a number of reference materials: +

    +
    +
    Craig Anderson. MIDI for Musicians. Amsco Publishing, New +York, NY. + +

    +

    +
    +
    William Duckworth. Music Fundamentals. Wadsworth Publishing, +Belomnt, CA. + +

    +

    +
    +
    Michael Esterowitz. How To Play From A Fakebook. Ekay Music, +Inc. Katonah, NY. + +

    +

    +
    +
    Pete Goodliffe. MIDI documentation (for the TSE3 library). +http://tse3.sourceforge.net/. + +

    +

    +
    +
    Norman Lloyd. The Golden Encyclopedia Of Music. Golden Press, +New York, NY. + +

    +

    +
    +
    The MIDI Manufacturers Association. Various papers, tables and + other information. http://www.midi.org/. + +

    +

    +
    +
    Victor López. Latin Rhythms: Mystery Unraveled. Alfred Publishing Company. These are handout notes from the 2005 Midwest Clinic 59th Annual Conference, Chicago, Illinois, December 16, 2005. A PDF of this document is available on various internet sites. + +

    +

    +
    +
    Carl Brandt and Clinton Roemer. Standardized Chord + Symbol Notation. Roerick Music Co. Sherman Oaks, CA. + +

    +

    +
    + +

    +And, finally, to all those music teachers my parents and I paid for, +and the many people who have helped by listening and providing helpful +suggestions and encouragement in my musical pursuits for the +last 40 plus years that I've been banging, squeezing and blowing. You know +who you are--thanks.


    - next - up - previous
    - Next: About this document ... - Up: Next: Command Summary + Up: Reference Manual - Previous: Bibliography and Thanks + Previous: Symbols and Constants
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node29.html b/mma/docs/html/ref/node29.html index 6f59668..d50d29d 100644 --- a/mma/docs/html/ref/node29.html +++ b/mma/docs/html/ref/node29.html @@ -7,8 +7,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds Jens Lippmann, Marek Rouchal, Martin Wilck and others --> -About this document ... - +Command Summary + @@ -18,56 +18,426 @@ original version by: Nikos Drakos, CBLU, University of Leeds + + -next - +next + up - previous
    - Up: Next: About this document ... + Up: Reference Manual - Previous: Command Summary + Previous: Bibliography and Thanks

    -About this document ... +Command Summary

    - LOST LOGO

    -Reference Manual

    -This document was generated using the -LaTeX2HTML translator Version 2002-2-1 (1.71) +

    +TRACK Accent <beat adj> Adjust volume for specified beat(s) in each bar of a track. +

    -Copyright © 1993, 1994, 1995, 1996, -Nikos Drakos, -Computer Based Learning Unit, University of Leeds. +

    AdjustVolume <name=value> Set the volume ratios for named volume(s). +
    +

    +

    AllTracks <cmds> Applies cmds(s) to all active tracks. +
    +

    +

    TRACK Articulate <value> ... Duration/holding-time of notes. +
    +

    +

    Author <stuff> A specialized comment used by documentation extractors. +
    +

    +

    AutoSoloTracks <tracks> Set the tracks used in auto assigning solo/melody notes. +
    +

    +

    BarNumbers Leading <number> on data line (ignored). +
    +

    +

    BarRepeat Data bars can repeat with a ``* nn'' +
    +

    +

    BeatAdjust <beats> Adjust current pointer by <beats>. +
    +

    +

    Begin Delimits the start of a block. +
    +

    +

    TRACK ChShare <track> Force track to share MIDI track. +
    +

    +

    TRACK Channel <1..16> Force the MIDI channel for a track. +
    +

    +

    TRACK ChannelPref <1..16> Set a preferred channel for track. +
    +

    +

    ChordAdjust <Tonic=adj> Adjust center point of selected chords. +
    +

    +

    Comment <text> ignore/discard <text>. +
    +

    +

    TRACK Compress <value> ... Enable chord compression for track. +
    +

    +

    TRACK Copy <source> Overlay <source> track to sepecified track. +
    +

    +

    [TRACK] Cresc <[start] end count> Decrease volume over bars. +
    +

    +

    [TRACK] Cut <beat> Force all notes off at <beat> offset. +
    +

    +

    Debug <options> Selectively enable/disable debugging levels. +
    +

    +

    Dec <name> [value] Decrement the value of variable <name> by 1 or <value>. +
    +

    +

    [TRACK] Decresc <[start] end count> Increase volume over bars. +
    +

    +

    DefChord <name notelist scalelist> Define a new chord. +
    +

    +

    DefGroove <name> [Description] Define a new groove. +
    +

    +

    TRACK Define <pattern> Define a pattern to use in a track. +
    +

    +

    TRACK Delete Delete specified track for future use. +
    +

    +

    TRACK Direction [Up | Down | BOTH | RANDOM] ... Set direction of runs in Scale, Apreggio and Walk tracks. +
    +

    +

    Doc <stuff> A special comment used by documentation extractors. +
    +

    +

    DocVar <description> A specialized comment used to document user variables in a library file. +
    +

    +

    DrumTR <old>=<new> translates MIDI drum tone <old> to <new>. +
    +

    +

    TRACK DrumType Force a solo track to be a drum track. +
    +

    +

    DrumVolTr <tone>=<adj> ... adjusts volume for specified drum tone. +
    +

    +

    TRACK DupRoot <octave> Duplicate the root note in a chord to lower/higher octave. +
    +

    +

    End Delimits the end of a block. +
    +

    +

    EndIf End processing of ``IF''. +
    +

    +

    EndMset End of a ``Mset'' section. +
    +

    +

    EndRepeat [count] End a repeated section. +
    +

    +

    Eof Immediately stop/end input file. +
    +

    +

    Fermata <beat> <count> <adjustment> Expand <beat> for <count> by <adjustment percentage. +
    +

    +

    TRACK ForceOut Force voicing and raw data output for track. +
    +

    +

    Goto <name> jump processing to <name>. +
    +

    +

    Groove <name> Enable a previously defined groove. +
    +

    +

    GrooveClear Delete all current Grooves from memory. +
    +

    +

    TRACK Harmony [Option] ... Set harmony for Bass, Walk, Arpeggio, Scale, Solo and Melody tracks. +
    +

    +

    TRACK HarmonyOnly <Option> ... Force track to sound only harmony notes from current pattern. +
    +

    +

    TRACK HarmonyVolume <Percentage> ... Set the volume used by harmony notes. +
    +

    +

    If <test> <cmds> Test condition and process <cmds>. +
    +

    +

    IfEnd End processing of ``IF''. +
    +

    +

    Inc <name> [value] Increment the value of variable <name> by 1 or <value>. +
    +

    +

    Include <file> Include a file. +
    +

    +

    TRACK Invert <value> ... set the inversion factor for chords in track. +
    +

    +

    KeySig <sig> Set the key signature. +
    +

    +

    Label <name> Set <name> as a label for ``GOTO''. +
    +

    +

    TRACK Limit <value> Limit number of notes used in a chord to <value>. +
    +

    +

    Lyric <options> Set various lyrics options. +
    +

    +

    MIDI <values> Send raw MIDI commands to MIDI meta-track. +
    +

    +

    TRACK MIDIClear <Beat Controller Data> Set command (or series) of MIDI commands to send when track is completed. +
    +

    +

    MIDIFile <option> Set various MIDI file generation options. +
    +

    +

    TRACK MIDIGlis <1..127> Set MIDI portamento (glissando) value for track. +
    +

    +

    TRACK MIDIInc <File> <Options> Include an existing MIDI file into a track. +
    +

    +

    MIDIMark [offset] Label Inserts Label into the MIDI track. +
    +

    +

    TRACK MIDIPan <0..127> Set MIDI pan/balance for track. +
    +

    +

    TRACK MIDISeq <Beat Controller Data> options> ... Set MIDI controller data for a track. +
    +

    +

    MIDISplit <channel list> Force split output for track. +
    +

    +

    TRACK MIDITName <string> Assigns an alternate name to a MIDI track. +
    +

    +

    TRACK MIDIVoice <Beat Controller Data> Set ``one-time'' MIDI controller command for track. +
    +

    +

    TRACK MIDIVolume <1..128> Set MIDI volume for track. +
    +

    +

    TRACK Mallet <Rate=nn | Decay=nns> Set mallet repeat for track. +
    +

    +

    MmaEnd <file> Set filename to process after main file completed. +
    +

    +

    MmaStart <file> Set file to include before processing main file. +
    +

    +

    Mset <name> <lines> Set <variable> to series of lines. +
    +

    +

    MsetEnd End of a ``Mset'' section. +
    +

    +

    NewSet <name> <stuff> Set the variable <name> to <stuff>. +
    +

    +

    TRACK NoteSpan <start> <end> set MIDI range of notes for track. +
    +

    +

    TRACK Octave <0..10> ... Set the octave for track. +
    +

    +

    TRACK Off Disable note generation for specified track. +
    +

    +

    TRACK On Enable note generation for specified track. +
    +

    +

    Print <stuff> Print <stuff> to output during compile. Useful for debugging. +
    +

    +

    PrintActive Print list of active tracks to output. +
    +

    +

    PrintChord <name(s)> Print the chord and scale for specific chord types. +
    +

    +

    TRACK RSkip <Value> ... Skip/silence random percentage of notes. +
    +

    +

    TRACK RTime <Value] ... +
    +

    +

    TRACK RVolume <adj> ... Set volume randomization for track. +
    +

    +

    TRACK Range <value> Set number of octaves used in Scale and Arpeggio tracks. +
    +

    +

    Repeat Start a repeated section. +
    +

    +

    RepeatEnd [count] End a repeated section. +
    +

    +

    RepeatEnding Start a repeat-ending. +
    +

    +

    TRACK Riff <pattern> Define a special pattern to use in track for next bar. +
    +

    +

    RndSeed <Value> ... Seed random number generator. +
    +

    +

    RndSet <variable> <list of values> Randomly set variable. +
    +

    +

    TRACK ScaleType <Chromatic | Auto> ... Set type of scale. Only for Scale tracks. +
    +

    +

    Seq Set the sequence point (bar pattern number). +
    +

    +

    [TRACK] SeqClear Clears sequence for track (or all tracks). +
    +

    +

    [TRACK] SeqRnd <On/Off/Tracks> Enable random seqeuence selection for track (or all tracks). +
    +

    +

    [TRACK] SeqRndWeight <list of values> Sets the randomization weight for track or global. +
    +

    +

    SeqSize <value> Set the number of bars in a sequence. +
    +

    +

    TRACK Sequence <pattern> ... Set pattern(s) to use for track. +
    +

    +

    Set <name> <stuff> Set the variable <name> to <stuff>. +
    +

    +

    SetAutoLibPath <path> Set the Auto-Include file path. +
    +

    +

    SetIncPath <path> Set the path for included files. +
    +

    +

    SetLibPath <path> Set the path to the style file library. +
    +

    +

    SetOutPath <path> Set the output filename. +
    +

    +

    ShowVars Display user defined variables. +
    +

    +

    StackValue <stuff> Push <stuff> onto a temporary stack. Remove with special macro $_StackValue. +
    +

    +

    TRACK Strum <value> ... Set the strumming factor for Chord tracks. +
    +

    +

    SwingMode <on/off> Set swing mode timing. +
    +

    +

    Tempo <rate> Set the rate in beats per minute. +
    +

    +

    Time <count> Set number of beats in a bar. +
    +

    +

    TimeSig <nn dd> Set the MIDI timesignature (not used by MMA). +
    +

    +

    TRACK Tone <Note> ... Set the drum-tone to use in a sequence. +
    +

    +

    Transpose <value> Transpose all tracks to a different key. +
    +

    +

    UnSet <name> Remove the variable <name>. +
    +

    +

    [TRACK] Unify <On | Off> ... Unify overlapping notes. +
    +

    +

    Use <file> Include/import an existing .mma file. +
    +

    +

    VExpand <on/off> Set variable expansion. +
    +

    +

    TRACK Voice <instrument> ... Set MIDI voice for track. +
    +

    +

    VoiceTr <old=new> ... - translates MIDI instrument <old> to <new>. +
    +

    +

    VoiceVolTr <voice>=<adj> ... - adjusts volume for specified voice. +
    +

    +

    TRACK Voicing <options. Set the voicing for a chord track. +
    +

    +

    [TRACK] Volume <value> ... Set the volume for a track or all tracks. +
    +

    +

    +
    + +

    +


    + + +next + +up + +previous
    -Copyright © 1997, 1998, 1999, -Ross Moore, -Mathematics Department, Macquarie University, Sydney. -

    -The command line arguments were:
    - latex2html -split +1 -dir html -no_math -no_footnode -local_icons -up_url ../mma.html -up_title 'Main MMA Reference' mma.tex -

    -The translation was initiated by Bob on 2006-10-15 -


    + Next: About this document ... + Up: Reference Manual + Previous: Bibliography and Thanks +
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/ref/node3.html b/mma/docs/html/ref/node3.html index 92dab2c..2115002 100644 --- a/mma/docs/html/ref/node3.html +++ b/mma/docs/html/ref/node3.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
    - Next: Next: Patterns - Up: Up: Reference Manual - Previous: Previous: Running

    @@ -49,31 +49,33 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -112,8 +114,8 @@ When your library and song files are processed various tracks will be created. Each track is created a unique name. The track types are discussed later in this chapter, but for now they are BASS, CHORD, -WALK, DRUM, ARPEGGIO, SCALE, MELODY -and SOLO. +WALK, DRUM, ARPEGGIO, SCALE, MELODY, +SOLO and ARIA.

    All tracks are named by appending a ``-'' and ``name'' to the @@ -146,10 +148,10 @@ Track Channels

    MIDI defines 16 distinct channels numbered 1 to 16.3.1 There is nothing which says that ``chording'' + HREF="#foot960">3.1 There is nothing which says that ``chording'' should be sent to a specific channel, but the drum channel should always be channel 10.3.2 + HREF="#foot961">3.2

    For MMA to produce any output, a MIDI channel must be assigned to a @@ -166,10 +168,10 @@ for other programs or as a ``keyboard track'' on your synth. In most cases this will work out just fine. However, there are a number of methods you can use to set the channels ``manually.'' You might want to read the sections on CHANNEL -(here), CHSHARE -(here), ON -(here), and OFF -(here). +(here), CHSHARE +(here), ON +(here), and OFF +(here).

    Why bother with all these channels? It would be much easier to put all @@ -276,8 +278,8 @@ Arpeggio

    -In musical terms an arpeggio3.3 is the notes of a chord played +In musical terms an arpeggio3.3 is the notes of a chord played one at a time. MMA arpeggio tracks take the current chord and, in accordance to the current pattern, play single notes from the chord. @@ -319,7 +321,7 @@ sums up the logic used to create the scales:

    Minor
    A melodic minor scale3.4 + HREF="#foot1010">3.4

    Diminished
    @@ -392,6 +394,21 @@ transitions.

    +

    + +
    +Automatic Melodies +

    + +

    +Real composers don't need to fear much from this feature ...but it +can create some interesting effects. ARIA tracks use a +predefined pattern to generate melodies over a chord progression. They +can be used to actually compose a bit of music or simply to +augment a section of an existing piece. + +

    +

    Silencing a Track

    @@ -402,7 +419,7 @@ There are a number of ways to silence a track:

      -
    • Use the OFF (page [*]) command to stop the +
    • Use the OFF (page [*]) command to stop the generation of MIDI data,

      @@ -418,7 +435,7 @@ There are a number of ways to silence a track:

    • Disable the MIDI channel with a ``Channel 0'' (page - [*]). + [*]).

    • @@ -433,14 +450,14 @@ details.



      Footnotes

      -
      ... 16.... 16.3.1
      The values 1 to 16 are used in this document. Internally they are stored as values 0 to 15.
      -
      ... 10.... 10.3.2
      This is not a MIDI rule, but a convention established in the GM (General MIDI) standard. If you @@ -448,13 +465,13 @@ details. available.
      -
      ...arpeggio...arpeggio3.3
      The term is derived from the Italian ``to play like a harp''.
      -
      ... scale... scale3.4
      If you think that support for Melodic and Harmonic minor scales is @@ -463,26 +480,26 @@ details.

      - next - up - previous
      - Next: Next: Patterns - Up: Up: Reference Manual - Previous: Previous: Running
      -Bob -2006-10-15 +bob +2007-03-07
      diff --git a/mma/docs/html/ref/node30.html b/mma/docs/html/ref/node30.html new file mode 100644 index 0000000..9786b72 --- /dev/null +++ b/mma/docs/html/ref/node30.html @@ -0,0 +1,73 @@ + + + + + +About this document ... + + + + + + + + + + + + + + + + +next + +up + +previous +
      + Up: Reference Manual + Previous: Command Summary +
      +
      + + +

      +About this document ... +

      + LOST LOGO + +

      +Reference Manual

      +This document was generated using the +LaTeX2HTML translator Version 2002-2-1 (1.71) +

      +Copyright © 1993, 1994, 1995, 1996, +Nikos Drakos, +Computer Based Learning Unit, University of Leeds. +
      +Copyright © 1997, 1998, 1999, +Ross Moore, +Mathematics Department, Macquarie University, Sydney. +

      +The command line arguments were:
      + latex2html -split +1 -dir html -no_math -no_footnode -local_icons -up_url ../mma.html -up_title 'Main MMA Reference' mma.tex +

      +The translation was initiated by bob on 2007-03-07 +


      +
      +bob +2007-03-07 +
      + + diff --git a/mma/docs/html/ref/node4.html b/mma/docs/html/ref/node4.html index f377269..c4b2cc2 100644 --- a/mma/docs/html/ref/node4.html +++ b/mma/docs/html/ref/node4.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
      - Next: Next: Sequences - Up: Up: Reference Manual - Previous: Previous: Tracks and Channels

      @@ -49,28 +49,30 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -87,7 +89,7 @@ Patterns MMA builds its output based on PATTERNs and SEQUENCEs supplied by you. These can be defined in the same file as the rest of the song data, or can be included (see -here) from a library file. +here) from a library file.

      A pattern is a definition for a voice or track which describes what @@ -149,11 +151,11 @@ The following concepts are used when defining a pattern: ``and ahh'' of the first beat is ``1.75'', etc. Using a beat offset greater than the number of beats in a bar or less than ``0'' is not permitted. Please note that offsets in the range ``0'' to ``.999'' - will actually be played in the previous bar (this can be + will actually be played in the previous bar (this can be useful in Jazz charts, and it will generate a warning!).4.1 See TIME - (here). + HREF="#foot1523">4.1 See TIME + (here).

      The offset can be further modified by appending a note length (see @@ -169,15 +171,15 @@ You can subtract note lengths as well, but this is rarely done. And, to make your style files completely unreadable, you can even use note length combinations. So, yes, the following pattern is fine:4.2 + HREF="#foot1524">4.2

      - - +
      + +
      + Chord Define C1 2-81+4 82 90 -
      Chord Define C1 2-81+4 82 90
      - -
      +

      @@ -193,12 +195,12 @@ You can subtract note lengths as well, but this is rarely done. And,

      - - +
      - + +
      + - - + + @@ -247,14 +249,15 @@ You can subtract note lengths as well, but this is rarely done. And,
      NotationDescription
      NotationDescription
      1 Whole note
      -
      +

      The ``81'' and ``82'' notations represent the values of a pair of eighth notes in a swing pair. These values vary depending on the - setting of SWINGMODE SKEW, see here. + setting of SWINGMODE SKEW, see here.

      The note length ``0'' is a special value often used in drum @@ -275,33 +278,33 @@ Note lengths can be combined using ``+''. For example, to make a

      Note lengths can also be combined using a ``-''. For example, to make a dotted half you could use ``1-4''. Subtraction might appear - silly at first, but is useful in generating a note just a bit + silly at first, but is useful in generating a note just a bit shorter than its full beat. For example, ``1-0'' will generate a note 1 MIDI tick shorter than a whole note. This can be used in generating breaks in sustained tones.4.3 + HREF="#foot1526">4.3

      It is permissible to combine notes with ``dots'', ``+''s and ``-''s. The notation ``2.+4'' would be the same as a whole note.

      The actual duration given to a note will be adjusted by the - ARTICULATE value here). + ARTICULATE value here).

      Volume
      The MIDI velocity4.4 to use for the specified note. + HREF="#foot1305">4.4 to use for the specified note. For a detailed explanation of how MMA calculates the volume of a - note, see read this. + note, see read this.

      MIDI velocities are limited to the range 0 to 127. However, MMA does not check the volumes specified in a pattern for validity.4.5 + HREF="#foot1310">4.5

      In most cases velocities in the range 50 to 100 are useful. @@ -313,7 +316,7 @@ In most cases velocities in the range 50 to 100 are useful. WIDTH="12" HEIGHT="21" ALIGN="BOTTOM" BORDER="0" SRC="img1.png" ALT="$\flat$">, and G) has 3 offsets: 0, 1 - and 2. Note that the offsets refer to the chord not the + and 2. Note that the offsets refer to the chord not the scale. For example, a musician might refer to the ``fifth''--this means the fifth note of a scale ...in a major chord this is the third note, which has an offset of 2 in @@ -326,8 +329,8 @@ In most cases velocities in the range 50 to 100 are useful.

      Patterns can be defined for BASS, WALK, CHORD, ARPEGGIO and DRUM tracks. All patterns are -shared by the tracks of the same type--Chord-Sus and -Chord-Piano share the patterns for Chord. As a +shared by the tracks of the same type--Chord-Sus and +Chord-Piano share the patterns for Chord. As a convenience, MMA will permit you to define a pattern for a sub-track, but remember that it will be shared by all similar tracks. @@ -335,28 +338,28 @@ For example:

      - - +
      + +
      + Drum Define S1 1 0 50 -
      Drum Define S1 1 0 50
      - -
      +

      and

      - - +
      + +
      + Drum-woof Define S1 1 0 50 -
      Drum-woof Define S1 1 0 50
      - -
      +

      Will generate identical outcomes.4.6 + HREF="#foot1323">4.6

      @@ -369,12 +372,12 @@ A bass pattern is defined with:

      - - +
      + +
      + Position Duration Offset Volume ; ... -
      Position Duration Offset Volume ; ...
      - -
      +

      Each group consists of an beat offset for the start point, the note @@ -399,27 +402,27 @@ even use both together if you're in a mood to obfuscate. The note offset can be further modified with a single accidental "#", "&" or "b". This modifier will raise or lower the note by a semitone.4.7 In the boogie-woogie + HREF="#foot1327">4.7 In the boogie-woogie library file a "6#" is used to generate a dominant 7th.

      -
      - - +
      - Bass Definition -
      - + + +
      + Bass Definition +
      + - - +
      - -
      Bass Define Broken8 1 8 1 90 ; \ + +
      + Bass Define Broken8 1 8 1 90 ; \
          2 8 5 80 ; \
          3 8 3 90 ; \ -
          4 8 1+ 80
      +
          4 8 1+ 80 -
      +


      @@ -433,7 +436,8 @@ library file a "6#" is used to generate a dominant 7th. Lost Image -

      +

      @@ -476,12 +480,12 @@ A Chord pattern is defined with:

      - - +
      + +
      + Position Duration Volume1 Volume2 .. ; ... -
      Position Duration Volume1 Volume2 .. ; ...
      - -
      +

      Each group consists of an beat offset for the start point, the note @@ -491,24 +495,24 @@ remaining notes.

      -
      - - +
      - Chord Definition -
      - + + +
      + Chord Definition +
      + - - +
      - -
      Chord Define Straight4+3 1 4 100 ; \ + +
      + Chord Define Straight4+3 1 4 100 ; \
          2 4 90 ; \
          3 4 100 ; \
          4 3 90 ; \
          4.3 3 80 ; \ -
          4.6 3 80
      +
          4.6 3 80 -
      +


      @@ -520,7 +524,8 @@ remaining notes. Lost Image -

      +

      @@ -537,12 +542,12 @@ root and third of a chord to sound, you could use something like:

      - - +
      + +
      + Chord Define Dups 1 8 90 0 90 0; 3 8 90 0 90 0 -
      Chord Define Dups 1 8 90 0 90 0; 3 8 90 0 90 0
      - -
      +

      @@ -555,45 +560,45 @@ An Arpeggio pattern is defined with:

      - - +
      + +
      + Position Duration Volume ; ... -
      Position Duration Volume ; ...
      - -
      +

      The arpeggio tracks play notes from a chord one at a time. This is quite different from chords where the notes are played all at once--refer to the STRUM directive -(here). +(here).

      Each group consists of an beat offset, the note duration, and the note volume. You have no choice as to which notes of a chord are played (however, they are played in alternating ascending/descending order.4.8 Volumes are + HREF="#foot1529">4.8 Volumes are selected for the specific beat, not for the actual note.

      -
      - - +
      - Arpeggio Definition -
      - + + +
      + Arpeggio Definition +
      + - - +
      - -
      Arpeggio Define 4s 1 4 100; \ + +
      + Arpeggio Define 4s 1 4 100; \
          2 4 90; \
          3 4 100; \ -
          4 4 100
      +
          4 4 100 -
      +


      @@ -602,7 +607,8 @@ selected for the specific beat, not for the actual note. Lost Image -

      +

      @@ -621,17 +627,17 @@ A Walking Bass pattern is defined with:

      - - +
      + +
      + Position Duration Volume ; ... -
      Position Duration Volume ; ...
      - -
      +

      Walking bass tracks play up and down the first part of a scale, paying attention to the ``color''4.9 of the + HREF="#foot1531">4.9 of the chord. Walking bass lines are very common in jazz and swing music. They appear quite often as an ``emphasis'' bar in marches. @@ -643,26 +649,27 @@ current chord (you cannot change this).

      -
      - - +
      - Walking Bass Definition -
      - + + +
      + Walking Bass Definition +
      + - - +
      - -
      Walk Define Walk4 1 4 100 ; \ + +
      + Walk Define Walk4 1 4 100 ; \
          2 4 90; \ -
          3 4 90
      +
          3 4 90 -
      +

      -

      +

      @@ -681,12 +688,12 @@ A scale pattern is defined with:

      - - +
      + +
      + Position Duration Volume ; ... -
      Position Duration Volume ; ...
      - -
      +

      Each group consists of an beat offset for the start point, the note @@ -694,26 +701,27 @@ duration, and volume.

      -
      - - +
      - Scale Definition -
      - + + +
      + Scale Definition +
      + - - +
      - -
      Scale Define S1 1 1 90 + +
      + Scale Define S1 1 1 90
      Scale Define S4 S1 * 4
      -Scale Define S8 S1 * 8
      +Scale Define S8 S1 * 8 -
      +
      -
      +

      @@ -729,12 +737,34 @@ are set to a MIDI velocity of 90.

      Scale patterns are quite useful in endings. More options for scales detailed in the SCALEDIRECTION -(here) and SCALETYPE -(here) sections. +(here) and SCALETYPE +(here) sections.

      -

      +

      +Aria +

      + +

      +An aria pattern is defined with: + +

      + + + +
      + Position Duration Volume ; ... + +
      + +

      +much like a scale pattern. Please refer to the the ARIA section +(here) for more details. + +

      + +


      Drum

      @@ -749,34 +779,35 @@ A Drum pattern is defined with:

      - - +
      + +
      + Position Duration Volume; ... -
      Position Duration Volume; ...
      - -
      +

      -
      - - +
      - Drum Definition -
      - + + +
      + Drum Definition +
      + - - +
      - -
      Drum Define S2 1 0 100; \ + +
      + Drum Define S2 1 0 100; \
          2 0 80 ; \
          3 0 100 ; \ -
          4 0 80
      +
          4 0 80 -
      +
      -
      +

      @@ -791,7 +822,7 @@ indicates 1 MIDI tick.

      -

      +


      Drum Tone

      @@ -813,10 +844,9 @@ more):

      - - +
      - -
      Drum Define S1 1 0 90 + +
      + Drum Define S1 1 0 90
      Drum Define S2 S1 * 2
      @@ -828,9 +858,10 @@ SeqSize 4
      Drum Sequence S4 S2 S2 S4
      -Drum Tone SnareDrum1 SideKick LowTom1 Slap
      +Drum Tone SnareDrum1 SideKick LowTom1 Slap -
      +

      Here the drum patterns ``S2'' and ``S4'' are defined to sound a drum @@ -854,13 +885,13 @@ To repeat the same ``tone'' in a sequence list, use a single ``/''.

      The ``tone'' can be specified with a MIDI note value or with a symbolic name. For example, a snare drum could be specified as ``38'' -or ``SnareDrum1''. The Drumnames +or ``SnareDrum1''. The Drumnames appendix lists all the defined symbolic names.

      It is possible to substitute tone values. See -TONETR. +TONETR.

      @@ -875,12 +906,12 @@ chord pattern (which is played on beats 1 and 3) as:

      - - +
      + +
      + Chord Define M13 1 4 80; 3 4 80 -
      Chord Define M13 1 4 80; 3 4 80
      - -
      +

      you can create a new pattern which plays on same beats and adds a @@ -888,12 +919,12 @@ single push note just before the third beat:

      - - +
      + +
      + Chord Define M1+3 M13; 2.5 16 80 0 -
      Chord Define M1+3 M13; 2.5 16 80 0
      - -
      +

      A few points to note: @@ -942,12 +973,12 @@ with a command like:

      - - +
      + +
      + Track Define NewPattern OldPattern * N -
      Track Define NewPattern OldPattern * N
      - -
      +

      where ``Track'' is a valid track name (``Chord'', ``Walk'', ``Bass'', @@ -961,16 +992,15 @@ The ``*'' is absolutely required.

      -
      - - +
      - Multiply Define -
      - - -
      - -
      Drum Define S1 1 1 100 + + + +
      + Multiply Define +
      + + +
      + Drum Define S1 1 1 100
      Drum Define S13 S1 * 2
      @@ -982,12 +1012,14 @@ Drum Define S16 S8 * 2
      Drum Define S32 S16 * 2
      -Drum Define S64 S1 * 64
      +Drum Define S64 S1 * 64 -
      +
      -
      +

      @@ -1020,23 +1052,23 @@ swing pattern which might be useful on a snare drum.

      -
      - - +
      - Swing Beat Drum Definition -
      - + + +
      + Swing Beat Drum Definition +
      + - - +
      - -
      Begin Drum Define + +
      + Begin Drum Define
          SB8 1 2+16 0 90 ; 3.66 4+32 80
          SB8 SB8 * 4
      -End
      +End -
      +


      @@ -1055,7 +1087,8 @@ End Lost Image -

      +

      @@ -1066,18 +1099,18 @@ and process it though

      Even cooler4.10 is combining a multiplier, and + HREF="#foot1498">4.10 is combining a multiplier, and existing pattern and a new pattern all in one statement. The following is quite legal (and useful):

      - - +
      + +
      + Drum Define D1234 1 0 90 * 4 -
      Drum Define D1234 1 0 90 * 4
      - -
      +

      which creates drum hits on beats 1, 2, 3 and 4. @@ -1087,12 +1120,12 @@ More contrived (but examples are needed) is:

      - - +
      + +
      + Drum Define Dfunny D1234 * 2; 1.5 0 70 * 2 -
      Drum Define Dfunny D1234 * 2; 1.5 0 70 * 2
      - -
      +

      If you're really interested in the result, run @@ -1102,7 +1135,7 @@ option with the above definition.

      -An existing pattern can be modified by shifting it a beat, or +An existing pattern can be modified by shifting it a beat, or portion of a beat. This is done in a MMA definition with the SHIFT directive. This @@ -1111,20 +1144,20 @@ play on beat 1, and then a second pattern played on beat 3.

      -
      - - +
      - Shift Pattern Definition -
      - + + +
      + Shift Pattern Definition +
      + - - +
      + +
      + Chord Define C1-3 1 3 90; \ +
          1.33 3 90; 1.66 3 90
      -
      Chord Define C1-3 1 3 90; \ -
          1.33 3 90; 1.66 3 90
      - -
      +


      @@ -1137,18 +1170,19 @@ play on beat 1, and then a second pattern played on beat 3.

      - - +
      + +
      + Chord Define C3-3 C1-3 Shift 2 -
      Chord Define C3-3 C1-3 Shift 2
      - -
      +

      Lost Image -

      +

      @@ -1164,56 +1198,56 @@ to define a series of quarter notes on the offbeat you could use:

      - - +
      + +
      + Drum Define D1234' 1 0 90 * 4 Shift .5 -
      Drum Define D1234' 1 0 90 * 4 Shift .5
      - -
      +

      which would create the same pattern as the longer:

      - - +
      + +
      + Drum Define D1234' 1.5 1 90; 2.5 1 90; 3.5 1 90; 4.5 1 90 -
      Drum Define D1234' 1.5 1 90; 2.5 1 90; 3.5 1 90; 4.5 1 90
      - -
      +



      Footnotes

      -
      ... warning!).... warning!).4.1
      The exception is that RTIME may move the chord back into the bar.
      -
      ... fine:... fine:4.2
      The start offset is the value of the first of a pair - of swing eights plus a quarter before the second beat. + of swing eights plus a quarter before the second beat.
      -
      ... tones.... tones.4.3
      See the supplied GROOVE ``Bluegrass'' for an example.
      -
      ... velocity... velocity4.4
      MIDI ``note on'' events are declared with a ``velocity'' value. Think of this as the ``striking pressure'' on a piano.
      -
      ... validity.... validity.4.5
      This is a feature that you probably don't want to use, but if you want to ensure that a note is always sounded use a @@ -1222,27 +1256,27 @@ which would create the same pattern as the longer: be clipped to the maximum permitted MIDI velocity.
      -
      ... outcomes.... outcomes.4.6
      What really happens is that this definition is stored in a slot named ``DRUM''.
      -
      ... +
      ... semitone.4.7
      Be careful using this feature ...certain scales/chords may return non-musical results.
      -
      ... +
      ... order.4.8
      See the DIRECTION command - (here). + (here).
      -
      ... ``color''... ``color''4.9
      The color of a chord are items like ``minor'', ``major'', etc. The current walking bass algorithm @@ -1251,7 +1285,7 @@ order. -
      ... cooler... cooler4.10
      In this case the word ``cool'' substitutes for the more correct ``useful''. @@ -1259,26 +1293,26 @@ order.

      - next - up - previous
      - Next: Next: Sequences - Up: Up: Reference Manual - Previous: Previous: Tracks and Channels
      -Bob -2006-10-15 +bob +2007-03-07
      diff --git a/mma/docs/html/ref/node5.html b/mma/docs/html/ref/node5.html index bbd0ef3..42b88c4 100644 --- a/mma/docs/html/ref/node5.html +++ b/mma/docs/html/ref/node5.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
      - Next: Next: Grooves - Up: Up: Reference Manual - Previous: Previous: Patterns

      @@ -49,15 +49,15 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -85,12 +85,12 @@ each track in your song:

      - - +
      + +
      + Track Sequence Pattern1 Pattern2 ... -
      Track Sequence Pattern1 Pattern2 ...
      - -
      +

      ``Track'' can be any valid track name: ``Chord'', ``Walk'', @@ -104,17 +104,16 @@ definition in a set of curly brackets ``{ }''.

      -
      - - +
      - Simple Sequence -
      - + + +
      + Simple Sequence +
      + - - +
      - -
      SeqClear + +
      + SeqClear
      SeqSize 2
      @@ -134,12 +133,14 @@ Chord Sequence Broken8
      Bass Sequence Broken8
      -Arpeggio Sequence { 1 1 100 * 8 } { 1 1 80 * 4 }
      +Arpeggio Sequence { 1 1 100 * 8 } { 1 1 80 * 4 } -
      +
      -
      +

      @@ -148,12 +149,12 @@ Arpeggio Sequence { 1 1 100 * 8 } { 1 1 80 * 4 } pattern. The Drum, Chord and Bass patterns repeat on every bar; the Drum-1 sequence repeats after 2 bars. Note how the Arpeggio pattern is defined at run-time.5.1 + HREF="#foot2157">5.1

      If there are fewer patterns than SEQSIZE, the sequence will be filled out to correct size. If the number of patterns used is greater than SEQSIZE (see -directives) a warning +directives) a warning message will be printed and the pattern list will be truncated.

      @@ -163,14 +164,14 @@ equivalent:

      - - +
      - -
      Bass Sequence Bass1 Bass1 Bass2 Bass2 + +
      + Bass Sequence Bass1 Bass1 Bass2 Bass2
      -Bass Sequence Bass1 / Bass2 /
      +Bass Sequence Bass1 / Bass2 / -
      +

      @@ -182,12 +183,12 @@ and decide to delete the Bass halfway though the song you could:

      - - +
      + +
      + Bass Sequence - -
      Bass Sequence -
      - -
      +

      The special sequences, ``-'' or ``z'', are also the equivalent of a @@ -197,18 +198,18 @@ with a 1-5 bass pattern on the first 3 bars and a walking bass on bar

      - - +
      - -
      Bass Sequence Bass4-13 / / z + +
      + Bass Sequence Bass4-13 / / z
      -Walk Sequence z / / Walk4-4
      +Walk Sequence z / / Walk4-4 -
      +

      If you already have a sequence defined5.2 you can repeat or copy the existing pattern by + HREF="#foot2172">5.2 you can repeat or copy the existing pattern by using a single ``*'' as the pattern name. This is useful when you are modifying an exisiting sequence. @@ -220,21 +221,21 @@ fourth bar in the pattern:

      - - +
      - -
      Groove Neato + +
      + Groove Neato
      Chord Sequence * * * {1 2 90}
      -Defgroove NeatoIntro
      +Defgroove NeatoIntro -
      +

      When a sequence is created a series of pointers to the existing patterns are created. If you change the definition of a particular -pattern later in your file the new definition will have no +pattern later in your file the new definition will have no effect on your existing sequences.

      @@ -260,12 +261,12 @@ when defining a new sequence and you want to be sure that no

      - - +
      + +
      + SeqClear -
      SeqClear
      - -
      +

      deletes all sequence information, with the important exception that @@ -276,15 +277,15 @@ Alternately, the command:

      - - +
      + +
      + Drum SeqClear -
      Drum SeqClear
      - -
      +

      -deletes all drum sequences. This includes the track ``Drum'', +deletes all drum sequences. This includes the track ``Drum'', ``Drum1'', etc.

      @@ -292,16 +293,16 @@ If you use a sub-track:

      - - +
      + +
      + Chord-Piano SeqClear -
      Chord-Piano SeqClear
      - -
      +

      only the sequence for that track is cleared.5.3 + HREF="#foot2254">5.3

      In addition to clearing the sequence pattern, the following other settings are restored to a default condition: @@ -353,27 +354,27 @@ CHORD using this command. The command

      - - +
      + +
      + Chord SeqClear -
      Chord SeqClear
      - -
      +

      -resets all CHORD tracks, whereas the command: +resets all CHORD tracks, whereas the command:

      - - +
      + +
      + Chord-Foo SeqClear -
      Chord-Foo SeqClear
      - -
      +

      -resets the CHORD-FOO track. If you need to clear only +resets the CHORD-FOO track. If you need to clear only the CHORD track use the ``-'' option.

      @@ -388,12 +389,12 @@ example, if you had a sequence:

      - - +
      + +
      + Drum-2 Sequence P1 P2 P3 z -
      Drum-2 Sequence P1 P2 P3 z
      - -
      +

      bar 1 would use ``P1'', bar 2 ``P2'', etc. However, it is quite @@ -408,12 +409,12 @@ sequences.

      - - +
      + +
      + Drum-Snare SeqRnd On -
      Drum-Snare SeqRnd On
      - -
      +

      @@ -421,12 +422,12 @@ sequences.

      - - +
      + +
      + SeqRnd On -
      SeqRnd On
      - -
      +

      @@ -434,12 +435,12 @@ sequences.

      - - +
      + +
      + SeqRnd Drum-Snare Chord-2 Chord-3 -
      SeqRnd Drum-Snare Chord-2 Chord-3
      - -
      +

      @@ -450,14 +451,14 @@ To disable random sequencing:

      - - +
      - -
      SeqRnd Off + +
      + SeqRnd Off
      -Drum SeqRnd Off
      +Drum SeqRnd Off -
      +

      To illustrate the different effects you can generate, assume that you @@ -467,18 +468,18 @@ sequence for each track with a commands similar to:

      - - +
      - -
      Drum-Snare Sequence D1 D2 D3 D4 + +
      + Drum-Snare Sequence D1 D2 D3 D4
      Drum-Low Sequence D11 D22 D33 D44
      Chord Sequence C1 C2 C3 C4
      -Bass Sequence B1 B2 B3 B4
      +Bass Sequence B1 B2 B3 B4 -
      +

      With no sequence randomization at all, the tracks will be be processed @@ -537,12 +538,12 @@ Next, assume we have set sequence randomization with:

      - - +
      + +
      + SeqRnd On -
      SeqRnd On
      - -
      +

      Now, the sequence may look like: @@ -605,14 +606,14 @@ Next, we will set randomization for a Drum and Chord track only:

      - - +
      - -
      Drum-Low SeqRnd On + +
      + Drum-Low SeqRnd On
      -Chord SeqRnd On
      +Chord SeqRnd On -
      +

      @@ -672,12 +673,12 @@ selected set of tracks. In this case we will set the Drum tracks only:

      - - +
      + +
      + SeqRnd Drum-Snare Drum-Low -
      SeqRnd Drum-Snare Drum-Low
      - -
      +

      @@ -749,12 +750,12 @@ you might have a sequence like this:

      - - +
      + +
      + Chord Sequence C1 C2 C3 C4 -
      Chord Sequence C1 C2 C3 C4
      - -
      +

      and you feel that the patterns C1 and C2 need to be used twice as often as C3 and C4. @@ -762,12 +763,12 @@ Simple:

      - - +
      + +
      + Chord SeqRndWeight 2 2 1 1 -
      Chord SeqRndWeight 2 2 1 1
      - -
      +

      Think of the random selection occurring like selecting balls out of bag. The SEQRNDWEIGHT @@ -795,18 +796,18 @@ For example:

      - - +
      + +
      + SeqSize 4 -
      SeqSize 4
      - -
      +

      sets it to 4 bars. The SeqSize applies to all tracks.

      -This command resets the sequence counter to 1. +This command resets the sequence counter to 1.

      If some sequences have already been defined, they will be truncated or @@ -817,7 +818,7 @@ until it is long enough.



      Footnotes

      -
      ... run-time.... run-time.5.1
      If you run MMA with the ``-s'' option @@ -826,50 +827,50 @@ until it is long enough. sequence.
      -
      ... defined... defined5.2
      In reality there is always a sequence defined for every track, but it might be a series of ``rest'' bars.
      -
      ... cleared.... cleared.5.3
      It is probably easier to use the command: - - +
      + +
      + Chord-Piano Sequence - -
      Chord-Piano Sequence -
      - -
      +
      if that is - what you want to do. In this case only sequence pattern is + what you want to do. In this case only sequence pattern is cleared.

      - next - up - previous
      - Next: Next: Grooves - Up: Up: Reference Manual - Previous: Previous: Patterns
      -Bob -2006-10-15 +bob +2007-03-07
      diff --git a/mma/docs/html/ref/node6.html b/mma/docs/html/ref/node6.html index 290928a..a59f563 100644 --- a/mma/docs/html/ref/node6.html +++ b/mma/docs/html/ref/node6.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
      - Next: Next: Riffs - Up: Up: Reference Manual - Previous: Previous: Sequences

      @@ -49,16 +49,20 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections +
    +
    +
  • Deleting Grooves +
  • Library Issues +
    @@ -90,12 +94,12 @@ A groove can be created at anytime in an input file with the command:

    - - +
    + +
    + DefGroove SlowRhumba -
    DefGroove SlowRhumba
    - -
    +

    Optionally, you can include a documentation string to the end of this @@ -103,25 +107,25 @@ command:

    - - +
    + +
    + DefGroove SlowRumba A descriptive comment! -
    DefGroove SlowRumba A descriptive comment!
    - -
    +

    A groove name can include any character, including digits and punctuation. However, it cannot include a space character (used as a delimiter) or a '/'6.1, nor can consist solely of digits6.2 + HREF="#foot2578">6.1, nor can consist solely of digits6.2

    In normal operation the documentation strings are ignored. However, when MMA is run with the -Dx command line option these strings are printed to the terminal screen in LATEX format. The standard library -document is generated from this data. The comments must be +document is generated from this data. The comments must be suitable for LATEX: this means that special symbols like ``#'', ``&'', etc. must be ``quoted'' with a preceding `` \''. @@ -223,12 +227,12 @@ with:

    - - +
    + +
    + Groove Name -
    Groove Name
    - -
    +

    At this point all of the previously saved information is restored. @@ -239,7 +243,7 @@ A few cautions:

      -
    • Pattern definitions are not saved in grooves. Redefining +
    • Pattern definitions are not saved in grooves. Redefining a pattern results in a new pattern definition. Sequences use the pattern definition in effect when the sequence is declared. @@ -260,12 +264,12 @@ selected after each bar. For example:

      - - +
      + +
      + Groove Tango LightTango LightTangoSus LightTango -
      Groove Tango LightTango LightTangoSus LightTango
      - -
      +

      would create the following bars: @@ -298,12 +302,12 @@ like:

      - - +
      + +
      + Groove Groove34 Groove44 -
      Groove Groove34 Groove44
      - -
      +

      For long lists you can use the ``/'' to repeat the last groove in the @@ -311,33 +315,32 @@ list. The example above could be written:

      - - +
      + +
      + Groove Tango LightTango LightTangoSus / -
      Groove Tango LightTango LightTangoSus /
      - -
      +

      When you use the ``list'' feature of GROOVEs you should be aware of what happens with the bar sequence number. Normally the sequence number is incremented after each bar is processed; and, when a new groove is selected the sequence number is reset (see SEQ, -discussed here). When +discussed here). When you use a list which changes the GROOVE after each bar the sequence number is reset after each bar ...with one exeption: if the same GROOVE is being used for two or more bars the sequence will not be reset.6.3 + HREF="#foot2663">6.3

      Another way to select GROOVEs is to use a list of grooves with a leading value. This lets you select the GROOVE to use based on the value of a variable ...handy if you want different sounds for repeated sections. Again, an example:

      - - +
      - -
      Set loop 1 // create counter with value of 1 + +
      + Set loop 1 // create counter with value of 1
      Repeat
        Groove $loop BossaNovaSus BossaNova1Sus BossaNovaFill @@ -346,9 +349,10 @@ Repeat
        Inc Loop // Bump the counter value
      RepeatEnd 4 -
      + -
      +

      If you use this option, make sure the value of the counter is greater than 0. Also, note that the values larger than the list count are ``looped'' to be valid. The use of ``/''s for repeated names is also permitted. For an example have a look at the file grooves.mma, included in this distribution. You could get the same results with various ``if'' statements, but this is easier. @@ -365,12 +369,12 @@ in a track setting:

      - - +
      + +
      + Scale Groove Funny -
      Scale Groove Funny
      - -
      +

      In this case only the information saved in the corresponding @@ -397,31 +401,31 @@ appropriate function is called and file parsing continues. If it is not a simple command MMA tests to see if it is a track specific command. But to do that, it first has to test the first word to see if -it is a valid track name like Bass or Chord-Major. And, +it is a valid track name like Bass or Chord-Major. And, if it is a valid track name and that track doesn't exist, the track is -created...this is done before the rest of the command is +created...this is done before the rest of the command is processed. So, if you have a command like:

      - - +
      + +
      + Bass-Foo Groove Something -
      Bass-Foo Groove Something
      - -
      +

      and you really meant to type:

      - - +
      + +
      + Bass-Foe Groove Something -
      Bass-Foe Groove Something
      - -
      +

      you'll have a number of things happening: @@ -429,20 +433,20 @@ you'll have a number of things happening:

        -
      1. The track Bass-Foo will be created. This is not an issue +
      2. The track Bass-Foo will be created. This is not an issue to be concerned over since no data will be created for this new track unless you set a SEQUENCE for it.

      3. As part of the creation, all the existing GROOVEs will - have the Bass-Foo track (with its default/empty settings) + have the Bass-Foo track (with its default/empty settings) added to them.

      4. And the current setting you think you're modifying with the - Bass-Foe settings will be created with the Bass-Foo + Bass-Foe settings will be created with the Bass-Foo settings (which are nothing).

        @@ -464,9 +468,61 @@ you will get a warning.

        -

        +

        +Deleting Grooves +

        + +

        +There are times when you might want +MMA to forget about all the +GROOVEs in its memory. Just do a: + +

        + + + +
        + GrooveClear + +
        + +

        +at any point in your input file and that is exactly what happens. But, +``why,'' you may ask, ``would one want to do this?'' One case would be +to force the re-reading of a library file. For example, a library file +might have a user setting like: + +

        + + + +
        + If Ndef ChordVoice +
        +Set ChordVoice Piano1 +
        +Endif
        + +
        + +

        +In this case you could set the variable ``ChordVoice'' before loading +any of the GROOVEs in the file. All works! Now, assume that you +have a repeated section and want to change the voice. Simply changing +the variable does not work. The library file isn't re-read +since the exisiting GROOVE data is already in memory. Using +GROOVECLEAR erases the existing data and forces a re-reading of +the library file. + +

        +Please note that low-level setting like MIDI track assignments are +not changed by this command. + +

        + +

        Library Issues -

        +

        If you are using a groove from a library file, you just need to do @@ -474,23 +530,23 @@ something like:

        - - +
        + +
        + Groove Rhumba2 -
        Groove Rhumba2
        - -
        +

        at the appropriate position in your input file.

        -One minor problem which may arise is that more than one library +One minor problem which may arise is that more than one library file has defined the same groove name. This might happen if you have a third-party library file. For the proposes of this example, lets assume that the standard library file ``rhumba.mma'' and a second file ``xyz-rhumba.mma'' both define the groove ``Rhumba2''. The -auto-load routines +auto-load routines which search the library database will load the first ``Rhumba2'' it finds, and the search order cannot be determined. To overcome this possible problem, do a explicit loading of the correct file. In this @@ -498,12 +554,12 @@ case, simply do:

        - - +
        + +
        + Use xyz-rhumba -
        Use xyz-rhumba
        - -
        +

        near the top of your file. And if you wish to switch to the groove @@ -511,34 +567,34 @@ defined in the standard file, you can always do:

        - - +
        + +
        + Use rhumba -
        Use rhumba
        - -
        +

        just before the groove call. The USE will read the specified file and overwrite the old definition of ``Rhumba2'' with its own.

        -This issue in covered in more detail on page [*] +This issue in covered in more detail on page [*] of this manual.


        Footnotes

        -
        ... '/'... '/'6.1
        The '/' is reserved for future enhancements.
        -
        ... digits... digits6.2
        12345 and 2 are invalid; 11foo11 and a2-2 are permitted.
        -
        ... reset.... reset.6.3
        Actually, MMA checks to see the next @@ -548,26 +604,26 @@ of this manual.

        - next - up - previous
        - Next: Next: Riffs - Up: Up: Reference Manual - Previous: Previous: Sequences
        -Bob -2006-10-15 +bob +2007-03-07
        diff --git a/mma/docs/html/ref/node7.html b/mma/docs/html/ref/node7.html index fa3edd7..db98445 100644 --- a/mma/docs/html/ref/node7.html +++ b/mma/docs/html/ref/node7.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
        - Next: Next: Musical Data Format - Up: Up: Reference Manual - Previous: Previous: Grooves

        @@ -77,12 +77,12 @@ A RIFF is set with the command:

        - - +
        + +
        + Track Riff Pattern -
        Track Riff Pattern
        - -
        +

        where: @@ -110,10 +110,9 @@ Following is a short example using RIFF to change the Chord Patte

        - - +
        - -
        Groove Rhumba + +
        + Groove Rhumba
        1 Fm7
        @@ -125,9 +124,10 @@ Chord Riff 1 4 100; 3 8 90; 3.666 8 80; 4.333 8 70
        4 Eb6 / Eb
        -5 Fm7
        +5 Fm7 -
        +

        In this case there is a Rhumba Groove for the song; however, in bar 4 @@ -141,10 +141,9 @@ like the patterns used in a sequence.

        - - +
        - -
        Drum Define Emph8 1 0 128 * 8 + +
        + Drum Define Emph8 1 0 128 * 8
        Groove Blues
        @@ -160,14 +159,15 @@ Drum-Clap Riff Emph8
        Drum-Clap Riff Emph8
        -5 C
        +5 C -
        +

        -Here the Emph8 pattern is defined as a series of eighth notes. +Here the Emph8 pattern is defined as a series of eighth notes. This is applied for the third and fifth bars. If you compile and play this example -you will hear a sporadic hand-clap on bar 3. The Drum-Clap +you will hear a sporadic hand-clap on bar 3. The Drum-Clap track was previously defined in the Blues GROOVE as random claps on beats 2 and 4--our RIFF changes this to a louder volume with multiple hits. @@ -209,10 +209,9 @@ A few things to keep in mind when using RIFFs:

        - - +
        - -
        Mset CRiff + +
        + Mset CRiff
          Begin Scale
            Define Run 1 1 120
            Riff Run * $SSpeed @@ -238,9 +237,10 @@ Set SSpeed 8 Set SSpeed 12
        $CRIFF
        -5 C
        +5 C -
        +

      5. @@ -260,7 +260,7 @@ SOLO or MELODY track. Please see 7.1 a number of patterns to be processed sequentially. Each + HREF="#foot2960">7.1 a number of patterns to be processed sequentially. Each successive RIFF command adds a pattern to the stack; these patterns are then ``pulled'' from the stack as successive chord lines are processed. @@ -271,10 +271,9 @@ customized pattern for bars 4 and 5 in a mythical song:

        - - +
        - -
        Groove Rhumba + +
        + Groove Rhumba
        1 Fm7
        @@ -288,12 +287,13 @@ Chord Riff 1 2 100; 3 8 90;
        4 Eb6 / Eb
        -5 Fm7
        +5 Fm7 -
        +

        -In this example the first Chord Riff will be used in bar 4; the +In this example the first Chord Riff will be used in bar 4; the second in bar 5. For an example of this see the sample file egs/riffs.mma. @@ -301,7 +301,7 @@ second in bar 5. For an example of this see the sample file I often use this feature when creating a SOLO line.


        Footnotes

        -
        ... +
        ... ``stack''7.1
        Actually a queue or FIFO (First In, First Out) @@ -310,26 +310,26 @@ buffer.

        - next - up - previous
        - Next: Next: Musical Data Format - Up: Up: Reference Manual - Previous: Previous: Grooves
        -Bob -2006-10-15 +bob +2007-03-07
        diff --git a/mma/docs/html/ref/node8.html b/mma/docs/html/ref/node8.html index 88aa72c..b55d3ea 100644 --- a/mma/docs/html/ref/node8.html +++ b/mma/docs/html/ref/node8.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
        - Next: Next: Lyrics - Up: Up: Reference Manual - Previous: Previous: Riffs

        @@ -49,15 +49,15 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -71,7 +71,7 @@ Musical Data Format

        Compared to patterns, sequences, grooves and the various directives used in -MMA , +MMA , the actual bar by bar chord notations are surprisingly simple.

        @@ -111,42 +111,45 @@ Formally, this becomes:

        - - +
        + +
        + [num] Chord [Chord ...] [lyric] [solo] [* Factor] -
        [num] Chord [Chord ...] [lyric] [solo] [* Factor]
        - -
        +

        As you can see, all that is really needed is a single chord. So, the line:

        - - +
        + +
        + Cm -
        Cm
        - -
        +

        is completely valid. As is:

        - - +
        + +
        + 10 Cm Dm Em Fm * 4 -
        10 Cm Dm Em Fm * 4
        - -
        +

        -The optional solo or melody data is enclosed in ``{ }''. The +The optional solo or melody data is enclosed in ``{ }''s. The complete format and use is detailed in the Solo and Melody Tracks. +

        +Lyrics are enclosed in ''[ ]'' brackets. See the Lyrics section. +

        @@ -172,10 +175,9 @@ example:

        - - +
        - -
        1 Cm * 4 + +
        + 1 Cm * 4
        2
        @@ -183,9 +185,10 @@ example:
        4
        -5 A
        +5 A -
        +

        In the above example bars 2, 3 and 4 are comment bars. @@ -200,19 +203,19 @@ Bar Repeat Quite often music has several sequential identical bars. Instead of typing these bars over and over again, MMA has an optional -multiplier which can be placed at the end of a line of music +multiplier which can be placed at the end of a line of music data. The multiplier or factor can is specified as ``* NN'' This will cause the current bar to repeated the specified number of times. For example:

        - - +
        + +
        + Cm / Dm / * 4 -
        Cm / Dm / * 4
        - -
        +

        produces 4 bars of output with each the first 2 beats of each bar a Cm @@ -231,12 +234,12 @@ For example:

        - - +
        + +
        + Cm Dm Em Fm -
        Cm Dm Em Fm
        - -
        +

        specifies four different chords in a bar. It should be obvious by now @@ -249,24 +252,24 @@ automatically with the last chord name on the line. In other words:

        - - +
        + +
        + Cm -
        Cm
        - -
        +

        and

        - - +
        + +
        + Cm Cm Cm Cm -
        Cm Cm Cm Cm
        - -
        +

        are equivalent (assuming 4 beats per bar). There must be one (or more) @@ -278,24 +281,24 @@ last chord. So:

        - - +
        + +
        + Cm / Dm / -
        Cm / Dm /
        - -
        +

        is the same as

        - - +
        + +
        + Cm Cm Dm Dm -
        Cm Cm Dm Dm
        - -
        +

        It is perfectly okay to start a line with a ``/''. In this case the @@ -309,21 +312,21 @@ smart, but it doesn't read minds. MMA recognizes a wide variety of chords in standard notation. In addition, you can specify slash chords and shift the octave up or down. Refer to the complete table in the appendix for -details. +details.

        Rests -

        +

        To disable a voice for a beat you can use a ``z'' for a chord name. If used by itself a ``z'' will disable all but the drum tracks for the given beat. However, you can disable ``Chord'', ``Arpeggio'', -``Scale'', ``Walk'' or ``Bass'' tracks as well by appending a track +``Scale'', ``Walk'', ``Aria'', or ``Bass'' tracks as well by appending a track specifier to the ``z''. Track specifiers are the single letters ``C'', -``A'', ``S'', ``W'', ``B'' or `D'' and ``!''. Track specifiers are +``A'', ``S'', ``W'', ``B'', ``R'' or `D'' and ``!''. Track specifiers are only valid if you also specify a chord. The track specifiers are:

        @@ -352,6 +355,10 @@ only valid if you also specify a chord. The track specifiers are:

        S
        All scale tracks, +

        +

        R +
        All aria tracks, +

        !
        All tracks (almost the same as DWBCA, see below). @@ -388,12 +395,12 @@ Assuming that you have a drum, chord and bass pattern defined:

        - - +
        + +
        + Fm z G7zC CmzD -
        Fm z G7zC CmzD
        - -
        +

        would generate the following beats: @@ -422,7 +429,7 @@ would generate the following beats:

        In addition, there is a super-z notation. ``z!'' forces all instruments to be silent for the given beats. ``z!'' is the same as -``zABCDW'', except that the latter is not valid since it needs a +``zABCDWR'', except that the latter is not valid since it needs a prefixed chord.

        @@ -438,38 +445,38 @@ Case Sensitivity

        In direct conflict with the rest of the rules for input files, all -chord names are case sensitive. This means that you can - not use notations like ``cm''--use ``Cm'' instead. +chord names are case sensitive. This means that you can + not use notations like ``cm''--use ``Cm'' instead.

        The ``z'' and the associated track specifiers are also case sensitive. -For example, the form ``Zc'' will not work! +For example, the form ``Zc'' will not work!


        - next - up - previous
        - Next: Next: Lyrics - Up: Up: Reference Manual - Previous: Previous: Riffs
        -Bob -2006-10-15 +bob +2007-03-07
        diff --git a/mma/docs/html/ref/node9.html b/mma/docs/html/ref/node9.html index 4a3da3e..6f0198c 100644 --- a/mma/docs/html/ref/node9.html +++ b/mma/docs/html/ref/node9.html @@ -26,21 +26,21 @@ original version by: Nikos Drakos, CBLU, University of Leeds - next - up - previous
        - Next: Next: Solo and Melody Tracks - Up: Up: Reference Manual - Previous: Previous: Musical Data Format

        @@ -49,26 +49,26 @@ original version by: Nikos Drakos, CBLU, University of Leeds Subsections @@ -87,8 +87,8 @@ sequencers can display them as a file is played. Some, but not all.

        I'm not aware of any keyboards which display lyrics; and most Linux based players do not display them. Exceptions to the rule are the -programs Kmid which displays and highlights lyrics almost in a -Karaoke manner, xplaymidi and timidity which display the +programs Kmid which displays and highlights lyrics almost in a +Karaoke manner, xplaymidi and timidity which display the lyrics in a secondary panel.

        @@ -98,25 +98,25 @@ lyrics NOT to be useful in a program like a melody playing while they are vocalizing (really, they are no different in this than any other instrumentalist). And some platforms9.1 other than Linux support lyric display in a more + HREF="#foot3444">9.1 other than Linux support lyric display in a more useful format.

        -The ``Standard MIDI File'' document describes a Lyric Meta-event: +The ``Standard MIDI File'' document describes a Lyric Meta-event:

        FF 05 len text Lyric. A lyric to be sung. Generally, each syllable will be a separate lyric event which begins at the event's time.9.2
        + HREF="#foot3448">9.2

        Unfortunately, not all players and creators follow the specification--the most notable exception are ``.kar'' files. These -files eschew the Lyric event and place their lyrics as a -Text Event. There are programs strewn on the net which convert +files eschew the Lyric event and place their lyrics as a +Text Event. There are programs strewn on the net which convert between the two formats (but I really don't know if conversion is needed). @@ -151,24 +151,24 @@ EVENT option is used to select the desired mode.

        - - +
        + +
        + Lyric EVENT=LYRIC -
        Lyric EVENT=LYRIC
        - -
        +

        selects the default LYRIC EVENT mode.

        - - +
        + +
        + Lyric EVENT=TEXT -
        Lyric EVENT=TEXT
        - -
        +

        selects the TEXT EVENT mode. Use of this option also prints a @@ -193,24 +193,24 @@ lyrics for several bars into one event. In this case simply set the

        - - +
        + +
        + Lyric SPLIT=BAR -
        Lyric SPLIT=BAR
        - -
        +

        You can return to normal (syllable/word) mode at anytime with:

        - - +
        + +
        + Lyric SPLIT=NORMAL -
        Lyric SPLIT=NORMAL
        - -
        +

        @@ -225,12 +225,12 @@ insert them as a lyrics. The option:

        - - +
        + +
        + Lyric CHORDS=On -
        Lyric CHORDS=On
        - -
        +

        will enable this. In this mode the chord line is parsed and inserted @@ -261,17 +261,17 @@ in the LYRIC command:

        - - +
        + +
        + Lyric CHORDS=On Transpose=2 -
        Lyric CHORDS=On Transpose=2
        - -
        +

        -Please note that the Lyrics code does not look at the global +Please note that the Lyrics code does not look at the global TRANSPOSE setting.9.3 + HREF="#foot3474">9.3

        MMA isn't too smart in it's transposition and will often display the @@ -282,12 +282,12 @@ example:

        - - +
        + +
        + Lyric CHORDS=On Transpose=2 CNames=Flat -
        Lyric CHORDS=On Transpose=2 CNames=Flat
        - -
        +

        By default, the ``flat'' setting is used. In addition to ``Flat'' and @@ -310,35 +310,35 @@ things, there is more than one way to do it.

        Lyrics can be set for a bar in-between a pair of []s somewhere in a data bar.9.4 For + HREF="#foot3480">9.4 For example:

        - - +
        - -
        z [ Pardon ] + +
        + z [ Pardon ]
        C [ me, If I'm ]
        E7 [ sentimental, \r]
        -C [when we say good ]
        +C [when we say good ] -
        +

        The alternate method is to use the LYRIC SET directive:

        - - +
        + +
        + Lyric Set Hello Young Lovers -
        Lyric Set Hello Young Lovers
        - -
        +

        Unlike the other LYRIC options, the SET option must be @@ -384,12 +384,12 @@ In this case you simply specify two more sets of lyrics:

        - - +
        + +
        + A / Am / [First verse] [Second Verse] -
        A / Am / [First verse] [Second Verse]
        - -
        +

        However, for this work properly you must set the internal counter @@ -398,12 +398,12 @@ the command:

        - - +
        + +
        + Lyric Verse=Value | INC | DEC -
        Lyric Verse=Value | INC | DEC
        - -
        +

        This means that you can directly set the value (the default value is @@ -411,12 +411,12 @@ This means that you can directly set the value (the default value is

        - - +
        + +
        + Lyric Verse=2 -
        Lyric Verse=2
        - -
        +

        And you can increment or decrement the value with the INC and @@ -424,12 +424,12 @@ DEC options. This is handy at to use in repeat sections:

        - - +
        + +
        + Lyric Verse=Inc -
        Lyric Verse=Inc
        - -
        +

        You cannot set the value to a value less than 1. @@ -466,14 +466,14 @@ and you'd like the lyrics for the first bar to start on beat 4:

        - - +
        - -
        z z z C [ <4>Hello ] + +
        + z z z C [ <4>Hello ]
        -F [ Young lovers ]
        +F [ Young lovers ] -
        +

        Assuming 4/4 the above would put the word ``Hello'' at beat @@ -504,32 +504,31 @@ keep

        - - +
        + +
        + C [ <><Verse_1.>This is a Demo ] -
        C [ <><Verse_1.>This is a Demo ]
        - -
        +

        This example 9.5 shows a complete + HREF="#foot3545">9.5 shows a complete song with lyrics. You should also examine the file egs/lyrics.mma for an alternate example.

        -
        - - +
        - Twinkle, Twinkle, Little Star -
        - + + +
        + Twinkle, Twinkle, Little Star +
        + - - +
        - -
        Tempo 200 + +
        + Tempo 200
        Groove Folk
        @@ -561,12 +560,14 @@ Repeat
         
          Lyric Verse=Inc
        -RepeatEnd
        +RepeatEnd -
        +
        -
        +

        @@ -594,35 +595,35 @@ A few combinations are not permitted:



    Footnotes

    -
    ... +
    ... platforms9.1
    Pointers and reviews to other players would be would appreciated.
    -
    ... time.... time.9.2
    I am quoting from ``MIDI Documentation'' distributed with the TSE Library. Pete Goodliffe, Oct. 21, 1999. Page 41.
    -
    ... setting.... setting.9.3
    This is a feature! It permits you to have separate control over music generation and chord symbol display.
    -
    ... bar.... bar.9.4
    Although the lyric can be placed anywhere in the bar, it is recommended that you only place the lyric at the end of the bar. All the examples follow this style.
    -
    ...eg:twk ...eg:twk 9.5
    Included in this distribution as songs/twinkle.mma. @@ -630,26 +631,26 @@ platforms

    - next - up - previous
    - Next: Next: Solo and Melody Tracks - Up: Up: Reference Manual - Previous: Previous: Musical Data Format
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/index.html b/mma/docs/html/tut/index.html index ffdfe4a..9f5cbc7 100644 --- a/mma/docs/html/tut/index.html +++ b/mma/docs/html/tut/index.html @@ -50,7 +50,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    LOST LOGO + ALT="LOST LOGO">

    Tutorial

    @@ -58,7 +58,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    Bob van der Poel

    Wynndel, BC, Canada

    -

    October 15, 2006

    +

    March 7, 2007

    @@ -118,8 +118,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds


    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/mma-tutorial.html b/mma/docs/html/tut/mma-tutorial.html index ffdfe4a..9f5cbc7 100644 --- a/mma/docs/html/tut/mma-tutorial.html +++ b/mma/docs/html/tut/mma-tutorial.html @@ -50,7 +50,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    LOST LOGO + ALT="LOST LOGO">

    Tutorial

    @@ -58,7 +58,7 @@ original version by: Nikos Drakos, CBLU, University of Leeds

    Bob van der Poel

    Wynndel, BC, Canada

    -

    October 15, 2006

    +

    March 7, 2007

    @@ -118,8 +118,8 @@ original version by: Nikos Drakos, CBLU, University of Leeds


    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/mup/bass.png b/mma/docs/html/tut/mup/bass.png index 24f5f0904bd724f62c89d2ae0cf0a20d5dc7b48d..8fe24bffaa09e37c38a616574bba9d91dad4bc51 100644 GIT binary patch literal 2788 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 diff --git a/mma/docs/html/tut/mup/deep.png b/mma/docs/html/tut/mup/deep.png index 668733b7199b92bff3ae6eda290ffbd191299c0e..c98fc0706b4d786b9e774e2c4cb24bc1db22a6ce 100644 GIT binary patch literal 37196 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
    rGQ@(Ry6~~Gr~5-v8g`QIcgH~p+m>A=p(wY)i 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 A%>V!Z literal 24804 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 Gh5Zi@f0u0l diff --git a/mma/docs/html/tut/mup/drums.png b/mma/docs/html/tut/mup/drums.png index cfbdf387bd45a2701c4839e0aeafb2c369dd300b..1fb71b9974c78634c6dadbaa3159bf1fb5646b32 100644 GIT binary patch literal 3162 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 BOo;#h diff --git a/mma/docs/html/tut/mup/fella.png b/mma/docs/html/tut/mup/fella.png index 775a7c25a359a73f52ab5301459d9eead3b6e842..9254d62aa7d051f36fe3f19001dcff85ee81c49c 100644 GIT binary patch literal 28213 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 literal 19244 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 dU=SG|hW3e71Qkp=y*not in the public domain. Certainly ``Happy Birthday'' should be public domain, but isn't. User's should note1.1 that the + HREF="#foot186">1.1 that the copyrighted songs in this document are examples only. It is probably not legal for you to copy it or play them. If this document is violating copyright by including any of the sheet music used in the @@ -100,12 +100,13 @@ examples, please let us know and it will be removed.

    - - +
    - This is a draft document. + +
    + This is a draft document. Feedback is solicited! -
    +
    @@ -116,7 +117,7 @@ examples, please let us know and it will be removed.



    Footnotes

    -
    ... note... note1.1
    Bad pun intended! @@ -141,8 +142,8 @@ examples, please let us know and it will be removed. HREF="mma-tutorial.html">Tutorial
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/node2.html b/mma/docs/html/tut/node2.html index 691b862..ba04090 100644 --- a/mma/docs/html/tut/node2.html +++ b/mma/docs/html/tut/node2.html @@ -58,8 +58,8 @@ on the reference manual and the READMEs for this.

    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/node3.html b/mma/docs/html/tut/node3.html index e6c3dc8..99f93ff 100644 --- a/mma/docs/html/tut/node3.html +++ b/mma/docs/html/tut/node3.html @@ -69,16 +69,17 @@ Fella Bird, Basic Edition

    -
    - - +
    - Sheet Music for a Popular Song -
    - + + +
    + Sheet Music for a Popular Song +
    + Lost Image -
    +

    @@ -139,12 +140,12 @@ After the comments in the file, the first line to note is:

    - - +
    + +
    + Tempo 120 -
    Tempo 120
    - -
    +

    This sets the tempo, or speed, of the piece to 120 beats per minute. You may @@ -162,12 +163,12 @@ we can select one of the predefined grooves:

    - - +
    + +
    + Groove Rhumba -
    Groove Rhumba
    - -
    +

    Note that this command also sets up the ``time signature'' to 4/4. @@ -182,12 +183,12 @@ indicates an ``F'' chord. So that's what we tell

    - - +
    + +
    + 1 F -
    1 F
    - -
    +

    We continue in a similar manner for the rest of the song. @@ -200,24 +201,24 @@ We could have entered the first bar as:

    - - +
    + +
    + 2 F F F F -
    2 F F F F
    - -
    +

    or, more simply:

    - - +
    + +
    + 2 F / / / -
    2 F / / /
    - -
    +

    and had the same result. But, who wants to do all that typing? @@ -230,12 +231,12 @@ The line:

    - - +
    + +
    + 16 F / / z! -
    16 F / / z!
    - -
    +

    causes an ``F'' chord to be used on the first three beats, the fourth @@ -251,12 +252,12 @@ Change to this directory and type the command:

    - - +
    + +
    + mma fella1 -
    mma fella1
    - -
    +

    Your computer should run the python script called ``mma'' and process the @@ -383,12 +384,12 @@ So, let's look at the changes.

    - - +
    + +
    + Groove Metronome2-4 -
    Groove Metronome2-4
    - -
    +

    This sets the current ``groove'' to a metronome. To find this groove @@ -402,12 +403,12 @@ to create an empty bar:

    - - +
    + +
    +    z * 2 -
       z * 2
    - -
    +

    Mind you, we could have specified a chord here and gotten the same @@ -469,8 +470,8 @@ improvement. HREF="node2.html">Installation

    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/node4.html b/mma/docs/html/tut/node4.html index 2b75e9c..5a933d1 100644 --- a/mma/docs/html/tut/node4.html +++ b/mma/docs/html/tut/node4.html @@ -74,18 +74,19 @@ Deep River--A Swinging Spiritual

    -
    - - +
    - A Public Domain Song -
    - + + +
    + A Public Domain Song +
    + Lost Image
    -
    +

    @@ -99,24 +100,24 @@ We start out with a comment block.

    - - +
    + +
    + // Deep River -
    // Deep River
    - -
    +

    Start off by selecting the 4 beat metronome.

    - - +
    + +
    + Groove metronome2-4 -
    Groove metronome2-4
    - -
    +

    We want to surprise our listeners a bit, so we start off with a ``normal'' @@ -124,34 +125,34 @@ tempo. The single ``z'' produces a 4 beat introduction.

    - - +
    - -
    Tempo 90 + +
    + Tempo 90
    z
    -Groove FolkArticulated
    +Groove FolkArticulated -
    +

    As an introduction we play some nice, gentle chords for 4 bars.

    - - +
    - -
    1 F + +
    + 1 F
    2 Dm
    3 Gm
    -4 C7
    +4 C7 -
    +

    Surprise time. We are going to pump the tempo up to 140 BPM and @@ -159,14 +160,14 @@ select the Swing2 Groove.

    - - +
    - -
    Tempo 140 + +
    + Tempo 140
    -Groove Swing2
    +Groove Swing2 -
    +

    If we just did a switch of rhythm and tempo it'd be quite ``interesting''. @@ -178,26 +179,26 @@ drummer a real workout. So, here we double the time and put in a single

    - - +
    - -
    Tempo *2 + +
    + Tempo *2
    -z
    +z -
    +

    Now, we restore the tempo to the original 140.

    - - +
    + +
    + Tempo *.5 -
    Tempo *.5
    - -
    +

    Each time we restart the piece we want the same volume setting. This is bit @@ -206,26 +207,26 @@ of overkill, but it's supposed to be an example. So, we set the volume to

    - - +
    - -
    Volume mf + +
    + Volume mf
    -DefVolume Main
    +DefVolume Main -
    +

    Now, just like the sheet music we insert a repeat start.

    - - +
    + +
    + Repeat -
    Repeat
    - -
    +

    Set the volume, and advise @@ -234,24 +235,23 @@ next 8 bars.

    - - +
    - -
    SetVolume Main + +
    + SetVolume Main
    -Decresc mp 8
    +Decresc mp 8 -
    +

    This is straightforward chording.

    - - +
    - -
    5 F + +
    + 5 F
    6 Gm
    @@ -269,19 +269,19 @@ This is straightforward chording.
    13 Dm
    -14 Am
    +14 Am -
    +

    Increase the volume over the next 4 bars, and more chording.

    - - +
    - -
    Cresc ff 4 + +
    + Cresc ff 4

    15 Bb @@ -298,9 +298,10 @@ Increase the volume over the next 4 bars, and more chording.
    21 F
    -22 Gm
    +22 Gm -
    +

    This is the first/second ending. Note how we've put a ``2'' at the end @@ -308,17 +309,17 @@ of the next line ... this forces 2 repeats.

    - - +
    - -
    RepeatEnding 2 + +
    + RepeatEnding 2

    23 / / / C7
    -24 F
    +24 F -
    +

    For the second and third time we play this we want a more interesting @@ -327,24 +328,24 @@ its thing.

    - - +
    + +
    + Groove Swing2Plus -
    Groove Swing2Plus
    - -
    +

    This ends the repeated section.

    - - +
    + +
    + RepeatEnd -
    RepeatEnd
    - -
    +

    For our 2 bar ending we select the ``Swing2End'' groove. Next, we @@ -352,17 +353,17 @@ ritard our tempo over the next 2 bars.

    - - +
    - -
    Groove Swing2End + +
    + Groove Swing2End
    Tempo -40 2

    -1 / / / C7
    +1 / / / C7 -
    +

    The ``Swing2End'' groove has a neat little saxophone scale. But only on the @@ -372,18 +373,18 @@ the bar with the solo. We also set the solo to a louder volume.

    - - +
    - -
    Scale Volume ff + +
    + Scale Volume ff
    Seq 3
    1 F
    -Fermata -1 1 200
    +Fermata -1 1 200 -
    +

    To finish off the example, we add a bit of time to the last note with a fermata @@ -437,8 +438,8 @@ sample songs--then, it's all up to you. Have fun! HREF="node3.html">A Simple Example

    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/node5.html b/mma/docs/html/tut/node5.html index 8b70294..d55d1dc 100644 --- a/mma/docs/html/tut/node5.html +++ b/mma/docs/html/tut/node5.html @@ -83,7 +83,7 @@ of you'll see here is just one way to create a GROOVE. We have tried to keep it simple and organized it in different sections so that you understand how the GROOVE was built.5.1 + HREF="#foot670">5.1

    The day that you decide to create your proper GROOVEs you'll have to read the manual in detail! @@ -105,18 +105,18 @@ and initialize some variables (those are explained in detail in the

    - - +
    - -
    SeqClear + +
    + SeqClear
    SeqSize 1
    Time 4
    -Timesig 4 4
    +Timesig 4 4 -
    +

    Now let start to create our patterns. @@ -162,13 +162,13 @@ patterns that we will use:

    - - +
    + +
    + Begin Drum Define +
        D1 1 8 90 ; 2.5 8 90 ; 4 8 90
    -
    Begin Drum Define -
        D1 1 8 90 ; 2.5 8 90 ; 4 8 90
    - -
    +

    @@ -183,18 +183,18 @@ So what have we done? Well, we have just translated what we have seen on the score. We have created a pattern D1 with a 8th note on beats 1, 2.5 and 4 and a velocity of 90.5.2 + HREF="#foot672">5.2

    Using the same logic we can create the pattern for the snare drum.

    - - +
    + +
    + S1 2 8 90 ; 4 8 90 -
    S1 2 8 90 ; 4 8 90
    - -
    +

    For the closed HiHat pattern we will use a little trick to avoid having to @@ -202,14 +202,14 @@ enter 8 notes

    - - +
    - -
    CH1 1 8 90 + +
    + CH1 1 8 90
    -C1 CH1 * 8
    +C1 CH1 * 8 -
    +

    As you can see we just define one note on the first beat and multiplied @@ -220,23 +220,22 @@ And we close the definition by adding

    - - +
    + +
    + End -
    End
    - -
    +

    Now that we have the patterns for our drum, we will create the different instruments.5.3 + HREF="#foot673">5.3

    - - +
    - -
    Begin Drum-Kick + +
    + Begin Drum-Kick
      Tone KickDrum1
      Sequence D1
    @@ -254,9 +253,10 @@ Begin Drum-HH
      Tone ClosedHiHat
      Sequence C1
    -End
    +End -
    +

    @@ -289,15 +289,15 @@ for the drum (the line after End) and we add:

    - - +
    - -
    Begin Bass Define + +
    + Begin Bass Define
      B1 1 4+8 1 90 ; 2.5 8 1 90 ; 3 8 1 90 ; 3.5 4 1 90 ; 4.5 8 1 90
    -End
    +End -
    +

    You will already recognize the timing of the riff, the duration and @@ -307,26 +307,26 @@ player is that we add in the pitch definition for the note to be played.

    If we look at the first note definition we see that beat 1 is a note with duration 4+8 (dotted quarter),5.4the note to play is the first + HREF="#foot633">5.4the note to play is the first (root) of the chord and the volume or velocity of the note is 90.5.5 + HREF="#foot674">5.5

    Now the only thing left is to add the bass player at the end of the file, the same way we did with the drums.

    - - +
    - -
    Begin Bass-Simple + +
    + Begin Bass-Simple
      Voice AcousticBass5.6 + HREF="#foot714">5.6
      Sequence B1
    -End
    +End -
    +

    @@ -359,7 +359,7 @@ here is just one of the possibilities.

    We will define both ``hands'' of the piano player separately.5.7 + HREF="#foot676">5.7

    Let's start with the easiest, the left hand. Actually if you think a bit about it, there is not a big difference between a bass player @@ -375,12 +375,12 @@ In the pattern section of our GROOVE we will add:

    - - +
    + +
    + L1 1 2+4 1 90 -
    L1 1 2+4 1 90
    - -
    +

    Remember: First beat, half+fourth note, root of the @@ -391,17 +391,17 @@ And we will create a new bass player

    - - +
    - -
    Begin Bass-LeftHandPiano + +
    + Begin Bass-LeftHandPiano
      Voice Piano1
      Sequence L1
      Octave 3 // This a new command, but simple to understand
    -End
    +End -
    +

    Now the right hand. What the right hand of the piano player does is @@ -414,23 +414,23 @@ On the example score we see that he plays the chord in his first inversion form, but for the sake of simplicity of this ``Getting started'' document we are just ignoring this and we will define the standard form of the chord.5.8 + HREF="#foot677">5.8

    Again, we go up in the definition section of our GROOVE and under the bass patterns we will enter the chord definition

    - - +
    - -
    Begin Chord Define + +
    + Begin Chord Define
      C1 1 2+4 80 ; 4 4 80 5.9 + HREF="#foot732">5.9
    -End
    +End -
    +

    As you can see the chord definition structure is a bit different from @@ -447,16 +447,16 @@ Finally we need our piano right hand player

    - - +
    - -
    Begin Chord-RightHandPiano + +
    + Begin Chord-RightHandPiano
      Voice Piano1
      Sequence C1
    -End
    +End -
    +

    @@ -474,25 +474,24 @@ in a song:

    - - +
    + +
    + DefGroove Myrock1 -
    DefGroove Myrock1
    - -
    +

    is added at the end of the file.

    The file that we created should look like this5.10 + HREF="#foot679">5.10

    - - +
    - -
    SeqClear + +
    + SeqClear
      SeqSize 1
      Timesig 4 4
       @@ -562,9 +561,10 @@ Begin Chord-RightHandPiano End
      
    -DefGroove Myrock1
    +DefGroove Myrock1 -
    +

    @@ -591,16 +591,16 @@ Now start a new textfile to create a song and start the file with:

    - - +
    - -
    Groove Myrock1 + +
    + Groove Myrock1
    Tempo 120
      -
    // Enter chords here
    +
    // Enter chords here -
    +

    Save the file as Mysong.mma and compile it as explained in the first @@ -630,7 +630,7 @@ so don't think you will learn it in a day.

    Also read the README files that are delivered with the distribution. You can find valuable information in these.5.11 + HREF="#foot667">5.11

    Have fun with MMA ! @@ -640,44 +640,44 @@ You can find valuable information in these.


    Footnotes

    -
    ... built.... built.5.1
    This chapter was written by Rony Steelandt of Kara Music Production with minor spelling and grammar fixes by Bob van der Poel.
    -
    ......5.2
    See MMA Reference Manual section [*] for more details.
    -
    ......5.3
    See MMA Reference Manual section [*] for more details.
    -
    ... quarter),... quarter),5.4
    When specifying the duration of a note the following are equal: ``4+8'', ``4.'' or ``8+8+8''.
    -
    ......5.5
    See MMA Reference Manual section [*] for more detail.
    -
    ... AcousticBass... AcousticBass5.6
    For drums we use TONE for other instruments we use VOICE.
    -
    ......5.7
    As many things in MMA there are different ways to define that kind @@ -685,26 +685,26 @@ of pattern. If you're curious, look at the Reference Manual section [*].
    -
    ......5.8
    If you are curious about how to define inverted chords, see the Reference Manual section [*], page [*].
    -
    ......5.9
    This is not exactly right, it will play the 7th on a C7 chord too, but this is beyond the scope of this tutorial.
    -
    ... this... this5.10
    If you are really lazy and don't want to type the text, you download the file here: http://www.kara-moon.com/MMA/tut1.mma.
    -
    ......5.11
    Amongst others, some very good information about fake books. @@ -729,8 +729,8 @@ the file here: A More Complex Example
    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/docs/html/tut/node6.html b/mma/docs/html/tut/node6.html index 6527c09..5e71ba3 100644 --- a/mma/docs/html/tut/node6.html +++ b/mma/docs/html/tut/node6.html @@ -45,7 +45,7 @@ About this document ... LOST LOGO + ALT="LOST LOGO">

    Tutorial

    @@ -63,11 +63,11 @@ Mathematics Department, Macquarie University, Sydney. The command line arguments were:
    latex2html -split +1 -dir html -no_math -no_footnode -local_icons -up_url ../mma.html -up_title 'Main MMA Reference' mma-tutorial.tex

    -The translation was initiated by Bob on 2006-10-15 +The translation was initiated by bob on 2007-03-07


    -Bob -2006-10-15 +bob +2007-03-07
    diff --git a/mma/egs/README b/mma/egs/README index 7ad1ad8..0fc62f3 100644 --- a/mma/egs/README +++ b/mma/egs/README @@ -15,7 +15,7 @@ are clearly public domain. This really does limit things! However, a gzip file of many songs is available on the main MMA website: - http://users.xplornet.com/~bvdp/mma/mma.html + http://www.mellowood.ca/mma/mma.html PLEASE NOTE THAT THE SONGS IN THE ARCHIVE ARE DISTRIBUTED FOR EDUCATIONAL PURPOSES ONLY. diff --git a/mma/egs/aria/aria.txt b/mma/egs/aria/aria.txt new file mode 100644 index 0000000..8e99ce9 --- /dev/null +++ b/mma/egs/aria/aria.txt @@ -0,0 +1,202 @@ + +This is the initial doc file for the new ARIA track. The plan is to +incorporate this into the main documentation once the command settles +down. In the meantime I really do want feedback. Thanks. + +Purpose: + +The new ARIA tracks are designed to let MMA auto generate +something resembling melody. Honest, this will never put real +composers on the unemployment line (well, no more than they are mostly +there already). + +You might want to use an ARIA to embellish a section of a song (like +an introduction or an ending). Or you can have MMA generate a complete +melody over the song chords. + + +Theory: + +In a traditional song the melody depends on two parts: patterns +(IE. note lengths, volume, articulation) and pitch (usually determined +by the chords in a song). If you have been using MMA at all you will +know that that chords are the building block of what MMA does +already. So, to generate a melody we just need some kind of +pattern. And, since MMA already uses patterns in most things it +does, it is a short step to use a specialized pattern to generate a +melody. + +It might serve to look at the two sample song files enclosed in this +package. Compile them and play them. Not to bad? + +Now, let's get into the command set. In addition to the existing +tracks, there is a new ARIA track defined. Just like other tracks, you +can create as many ARIAs as you want. So, you can have the tracks +Aria-1, Aria, and Aria-silly all at the same time. + +Most of the commands which you can apply to the other tracks also +apply to ARIAs. This includes things like VOICE, RTIME, VOLUME, HARMONY, etc. + +A few things work differently: + +PATTERN - the pattern definition for an ARIA is . Much like a Scale pattern. + +RANGE - Just like scale tracks. A RANGE of 2 would let MMA work on a 2 +octave chord, etc. + +SCALETYPE: Much like a scale track. By default, the setting for this +is CHORD. But, you can use AUTO, SCALE or CHROMATIC. AUTO and SCALE +are identical and force MMA to select notes from the scale associated +with the current chord; CHROMATIC generates an 11 tone scale starting +at the root note of the chord. + +DIRECTION: As MMA processes the song it moves a note-selection pointer +up or down. By default DIRECTION is set to the single value "1" which +tells MMA to add 1 after each note is generated. However, you can set +the value to an integer -4 to 4 or the special value "r". With "r" a +random value -1, 0 or 1 will be used. + +To further confuse, you can have a list of values for direction. Note +that this this has nothing to do with the sequence size! So, look at +this: + + Aria Direction 0 0 1 2 4 -2 r r 1 -1 + +Now, if we have a piece with only Cmajor chord the following notes +would be generated: + + Event Offset Pointer Note + 1 0 c + 2 0 c + 3 1 e + 4 3 -> 0 c + 5 4 -> 0 c + 6 -2 -> 2 g + 7 random c,e,g + 8 random c,e,g + 9 .... etc. + +But, if you were to change the SCALETYPE to SCALE you would get a +completely different series. + +Things to try: + +- use seqrnd in an ARIA for a less predictable pattern. + +- use HARMONYONLY with a 2nd voice. + +Other Changes: + +The 'z' notation has been expanded with a 'CHORDzR' (like 'zS', etc) to +disable an aria for specific beats. + +PROBLEMS and CAVEATS: + +1. ARIAs are NOT saved or modified by GROOVE commands. Well, almost +... the sequence size will be adjusted to match the new size from the +groove. This might be unexpected: + + - load a groove. Let's say it has a seqsize of 4. + - create a ARIA. Use 4 patterns to match the groove size (if you + don't MMA will expand the sequence size for the ARIA stuff, just + like other tracks). + - Process a few bars of music. + - Load a new groove, but this time with a seqsize of 2. Now, the + ARIA will be truncated. This behaviour is duplicated in other + tracks as well, but it might be unexpected here. + +2. DIRECTION can not be changed on a bar per bar basis. It applies to +the entire sequence. Probably not an issue. + +3. The timing for the elements in the sequence are hard +coded when you create the pattern. Example: + + Aria Pattern {1 1 90 * 4} + +will generate 1/4 notes on each beat. What if you want to have some +1/4, some 1/8 and some 1/2? Well, right now you can do this by having +3 different patterns and using a random selection. But, this is not +ideal. Suggestions? + + +3. The current method of doing all this is quite ugly. I have thought +that it might make some sense to save ARIAs with GROOVEs ... but +probably not. After all, the pattern _I_ think sounds great with a +bossanova might just suit you idea of rock. So, saving ARIAs as part +of a groove will probably not happen. I think it would limit things +too much. + +So, how do I see these things being used? One simple way might be to +have a ARIA directory. Easy to have this as a subdir in the existing +"includes" directory. Now, for each aria you create, make a +directory. So, let's assume you create something to sound like Joplin +(Scott, not Janis). And, we'll further assume that the pattern has 4 +built in styles. First off, create a directory +"includes/joplin". Next, create 5 files with some example code. First +off the main file which sets the voicing, etc. + +FILE: include/joblin/main + +-------------- + +seqsize 4 +Begin Aria + Voice Piano3 + Volume f + Articulate 120 + Harmony Open+8Below / / 8Below + Octave 6 + Rskip 10 + Rtime 10 + Rvolume 20 + Direction r 0 0 1 -1 0 0 1 r + ScaleType Chord / / Auto +End + +----------------- + +Next, the specific stuff for pattern 1: + +FILE: includes/joplin/pat1 + +----------------------- + +Include joplin/main /// this will load the aria voicing, etc. + +Aria Sequence {1.5 8 90; 2 8 90; 2.5 8 90; 3 8 90; 3.5 8 90; 4 8 90; 4.5 8 90} \ + {1 8 90; 1.5 8 90; 2 8 90; 2.5 8 90; 3 8 90; 3.5 8 90; 4 4 90 } + +------------------- + +Do similar stuff for patterns 2, 3 and 4. + + +Now, in your song you can do something like: + +-------------- + +Tempo 120 +Groove Swing +Include joplin/pat1 +..... + +include joplin/pat3 +.... + + +Comments on this will be accepted!!! Better ideas will be gratefully +accepted!!!!! + + +NOTE: I thought that it might be handy to be able to copy an +existing sequence/pattern (eg. the CHORD sequence) and use that for +the aria sequence. Matter of fact, I got it running ... but it's quite +useless since it just really duplicates the specified pattern and +notes and doesn't add enough interesting notes to be worthwhile. Just +a dead end. So, the code has been dumped. + + + + + diff --git a/mma/egs/aria/barb.mid b/mma/egs/aria/barb.mid new file mode 100644 index 0000000000000000000000000000000000000000..d28d0ddb11c7613bdeda860f12f4eefb6f85a9d5 GIT binary patch literal 14888 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 literal 3307 zcmai#Yfl^59mbylCfTBuDplJTY_k%=awuXlBv~L}Y|o7C8J{`hA;5ZbYZ_rl} zdK0OEP1{-Wruzw6^`?GoP&io z@Rzhbcm!AzII%uoAMAFX?slhlo=>M~;NoQbbLsBWPJ7U~{|G0Wu9(`00p#Hlm-8=ocgU<%oVYqF;~bHzWG(h<-Ps-;d}IBl_cr{xqULkLZ*0 z-{MGLil2P#+0*I0hmUukboO^k(+@g>{evgZ-TnPe=5wTTZ+{ynx5xeioGc*M0-tj5 ziCX7_4>JGL>0^9%?km~U9J1ov*2OtonCWCwGwSVzdYkJh+w4rL4rgb!hqm1FcK$YV z=i&_Gy2H0rz0KdvrsgqQY-LkL#(i~YyQOT!JL)hi7B?>zS%EfPy`}0c(6)ftIi_aW zIrgG$o4S|1;oEzBdo|DaGc`|R@N7TxKLft!tf0`a9H0Qpe}v+7%Lj@$a#t*;0v9xS zg}Ozn*MqYNcg^wu`nz;XEp}FRmQ}pFhC*ubw16?c!z_o+HGRIy!@w<}D3!Gcs}Nb< zzN+Wp&|OwmXBqC2c4oL>F%)B_e(tadSTwn8Lh2?4j5=~FJn{VlRv9aXRw31C@u71K zH0kCl#dT&FSL3zR3A^%k82emz6|k-u4~3ep*rNZTv#P_(D!-#!DhkURppd8%oV>t+ zT{V*BKW6zC?lsjM+x5N_i?&H96bLHAPg*~6!u zLFWJU?PGku(zLzA4iYSh+^gnX{($J9Rc$ zVW_Y}hBBj0H>o0{GubAq!Va2el1-|bu^lyE<)5rFJp+?dN9D-&V!JL>x_8RD=Q`{N zc175JWY^hsq=)fg=LS`ZdC$yJNo;?Vg?$?5EG$dg(?f-c$*+g7l_641hw`jpEw(+j zp4bf*UNb5-V6QQPwIjR1RHqGU1{$amBk~#Y8f$tum5RfiiAZz=H}zUXnJd(Ld9ABg z+sD7SeOqro^Z)jR<8S^T4Y66r`yp;d*VIdogqP=+`We6Aw@Q4JUVl{STE%RIwhG=_WyI>K&uaX$QSPgm|BpA1@uRqpq&?5E z64-GM$(G?Rk`2QOpQ9?m})D-ho^dBe3#oWd#j( zp?!q*QQU>lK0^D%+9%dNvG!5iMXY^d?eqT@vy|%P@oGxgsb1cY_40uZ$s9-X_aRVu0ptm%Mh0gmmnO&D-iQJ|IZ(bE1Cb#FCXK_LH`&55cEIx1018;&-^Oj@xlLp bpAY`a2Yk>c>>q=|*7;UfE*~ow{s;dTJqSuj diff --git a/mma/egs/lyrics/twinkle.mid b/mma/egs/lyrics/twinkle.mid index e808afa2850a25e145e2a69796afbf76a4316b1e..8c1f9f0efe810785cb7353e74f4b164812e1db54 100644 GIT binary patch literal 5566 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 diff --git a/mma/egs/lyrics/twinkle1.mid b/mma/egs/lyrics/twinkle1.mid index f5668dc9a5342d4cc51e8a4c8213294731a744ea..79d68cfed49241b04807ab360f8d2ed7999d96eb 100644 GIT binary patch literal 5553 zcmc&%OOM>f5$+kz@;xKlu=TP4uLHv{;8&u<5ThmthMXpw9FnjT1$Gc5!PpvW7h3HK zyQ>I_^$0Dj5yJ)o=aig+9COQ0$k93FCn;Z5&q~^b0RsW-oO-8N)m>fv)%Vr5SGTSS zA#5=aBk`~H>i!KOtV8j5a30ywepkFWclLI# zt@hb_;-S}wlcPkTexMlvZ@9gdGTw|Mc zu*a*twS9f-EfZ(9*=V+J8290l?e4Yh)i8`rhv9L?%zSu-27x zclQprj(2bl@aM_|4{w`d-`d+f@faJZ&pL}I4|cG%e&7w5_WA5*5rMz2ZylaU>-~5*EufqN+>~COw<6FKT@B22szx^%WPoMW){@?fa)A{_+_y2#N z|9#i@yY~NK@Bg$f1`+keeE;^%KK-}&O8j;Do556kF`TwoKD#&l1k2}Q`XQD--e=>N z_op8im*0}hgXu4^{7LY)FN`OQ4Fx=y-oWx`IQ@GbdHn2wNWnw`o@GnFVU!%o7J8wLtXY0m@?rhF-i(MYlm96s`GWxzmNz!6TT86 zX?-mQS?MeMQTF3R1pHx;EIchl)_AI-i06*C8eVQ)L`2$``e^eqP(g6HLhwP|@R$rPSo*;?*NPqPvwo5cOgtCNO1c2$QOPJ$LG&Ka+`23FIiUg;NVl z6~6BLy6Y#LrkzzIEo`MmwQ%(!tn1$A51|&rta4Os)xyzDP&fT^nQ(ZkLA3B|6tDFX zlspmvu$_ouRC}`VlR07AqvRT7;>uw0hOcjL7h{9fgG-Ufe1@!N26|vwwfS93oFvLRD+su*IzQ3P#qP}>caGdNk&oQ z%F0a&@}hU=D@Bd#XJ`x8qIlmdN39qyt&f-9RxY3hp*wx(ZMM zJOl6t@QWx92}#A8t^h$nUN{#8W-pvOl(n7I6LdFv4I53Uy9*~-glIo>Hww-~)cQ%~ z)_gfR7^xDPWhA#g{;E_EZy{HnVVeMGJ{n?UQr-YMfQV4qrC&A0*(H~YiA-* z!b%hfWk?iMc{=aUm}gJAff7tXouisSYoZ|F0WCa$Mo@%uR6Ev94@M68!{~BO5mD~S z;^;@rO+ed~s0^j{3|63HPE>MZ*Qe-e4%h|>F8UNv9X9g72*4dS!W)dFvXgw0gU}g1 zfEOOX#TASRsknrwW|Am+Oxzt8wdDfuJ5H1bFAzH2J*Fpj(=G(a2<(uyxIxjJv>HRl z&a#QIqU;o6ir!(Y0CyvTkD4G5AY=Gw1VT*5v=_G*0tL4h1p?Mc-IX1@KzZ~gcqV`h z!fkLD(22%0W5CAw1SkM}2nDlh1aQYHfM~tQ(gq1p|Cw z#hVYag{#z9&j}1rFmUcLsk}@>^E?G91JSX9frKo^)gYUD3UFyj^FV3f8AuzmS`Hu_ zy>c0}O4JfXbtqdK{0kBRe27`2)+6;`UV&7gxEICmJO15P;0q#I?@Cvg9 z;Z8L^302Vpvru3+Ymg%ZLa5f$P=jNF#jOTe2h9Ulqc40!Ja3dE>poqHg0 zquCR}eqqaoG!FyW6H2zCJdhnxGW3E7G@?ubn&e8#cf7s=;0^)g5fE@E4bN&{`gHh0xx3;~1}31C#hi@S-X%@l1EX_us;eX0wi zsKV6Xz+}crJ8Gc|D6O01)R{;XXt1)@RdY`_9!_|HPhhGjyjl!N+VU|39|Zly9U_v`{u4Dr7{%AFGcq(8b zdS+TFcr;-F#ADG^K+{$i7-=(lf$OCHM#ub_0ui}! z6M~ywnu!3aJ8QsTcAWbd&YuXNB^6$mDglB7*qNK4WB3Q;n49p=4i~4S;T*b;;;>f{ z;x&<~DIrWl)qYgbEGmB!y8hE316f*%+chK{SUY-B1ae+FPNEeIsqhgE}0+ hW*8syv92isDv1UfUG9hwBJIeEqz&AJS&;sp`!BcfbnpNG literal 5724 zcmc&%TaO$^6|SC{?XJGeZWkD^et+gr}-LbvxJZJKbE~+GLE` z%whxfujcapHO2-$yKg;~?Jwqsi_P^bZ?8AaS6*TF`);#1oL}Cbzj=+_|7zd))jGTX z#$eEUm9r0iz?hdX=QZ}>YWADe?6<4g?^d(luV#N(&HlKW{b@D(^J?~&)$FgU+22;P zzprNhSk3;qntk9L!K4et?prqw*T1*Dv)G+qUwnD}@aFdJwVlP6Ub%jK-X*Z9|LY&J z`)lrHBY%1Q9=`bUOMf^!+lPlc3q7|F4(Iz~{ax(od3qSAy_@E{(1UYxZ+COCuXnHA z+?pSnU2pH*(37?K{^Aw0-<x^ zcXm#P!r7$@PN{MF0{)o>gWdlkGmy}K9Q8j)=LZK}^3gi``Ex~g?m5<7eF5VO7$5z9 z9`ffQe+lDDAG3ZD@{5qai1EdbS$}ZvC9GfinDs~B`=tG!_WGmxeAf2=zu*6~{rgGx zf426Y)P+@1T}=0HTaHz@cy0g0>j-q;}XNW{qZ;H>uCIK497>~ zD>U31Z_(P?!)x!~8h;DIA6erH1CG^!&-uxW@3VH7-ba zTc7*s(fBI9j^7!7*Q~uxYj?C^c!+i$-_h@3i`J#5Z+Y+bcus3axiiv zH{FF0SwS)Ahm9kOATB9=AcCzdtv%Uzs&Y%!J(e<0GQ7yr%q>|@Lfn-C3;@)U;CR$=WMR5ImVTGC_r(qYAfYT5V zPc)t>R(PAIB?Uk>fy!*C_PEvq(t%=j$p*4=RqnyTaMuXhq_w4Jd#_}U%7GCUKlM7e? zs3Gb+DyY^H;EC#>Er7_5rUTrSpp=nBS_B~KMY)$`PS$qMY5>p(CjCU|yEJlOS6{Ti zCQiGwUIc1{v>L9A60VSVaTwROQ33^J6D(8#fi2v57_jCjxI9HigTT0tt&HM)r2&FAS^HtM%o}P zeX4D_T=3!+Xy&9-EO@d-7I%+5z^2}YBs2@BzEH=X-$3&7h_e&)=AzUh;4-p6#{?w} zzQA)QVRALKIY~Z5`XE<0I3Q|?Rg%I7LqP=6^5MrQ^OB1EXsC@x8LoGe#y3f3cJ;)J zlecG-KF~{tsSV=dgd8AZ6ih{_xT0KeHFj|vMC5=Y$UBf0kEY;L$^xVhUa%$#3L}k) zv|KG>6BR_IlYmSoEQpvxyK;zl0=U#7*u+Ewy@uddc!COPNo}={97eg}MORG8?6}ot z>sWY#Y}BgaMdL!$Lp%jIxN?x4Rj5rU}?CTSRyt3k|9U4fc6Qq2Go(ok7*0 zHi(EVKsjONkRKl+e->sVD#MEO0<{r7hovJLYA2xt2$0%IDpr);l)45KE7E9?N-j%J zHAJ3IXs@^$5kR4RIkQzgf`XtnJZvbO>h*> zzo#?2aIy)dVKK7iu}>P0GC}fK0p#`BuHOSF*@J})J6v*i3AVQI*`@z=TPms zF$3ja3QI1U5i$vnz&1b3kx915iL^{>g5&*AqK8J0NRPlN$Z;eW3Wu`t zt9$Hzl-o%g0IncHyX!|Y9OMbQXGw5{T~GquGx%Z%k)hln0TD{2p%`iAl;mPUp1hUxQXbH`zyekfB NTi4ixbfN#b{{mF%l^_5B diff --git a/mma/egs/lyrics/twinkle2.mid b/mma/egs/lyrics/twinkle2.mid index 9cc5cedac3ed0aa850d537246ad97e718f746bf7..b6ad177c548960228b787397707ff08edf784194 100644 GIT binary patch literal 5525 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 Bi=F@g diff --git a/mma/egs/lyrics/twinkle3.mid b/mma/egs/lyrics/twinkle3.mid index 558ab11a21b0642421356f15fb52de407cc0f5de..7d919ef89c67b1289836a83bb6a9de0ec2ed371c 100644 GIT binary patch literal 3332 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 AIRF3v delta 2660 zcmZuxTW=Fr5T3Pt0!a}80Tn3%idcK&&1MN9H+$EP-HpR7X;DQX0dj#rE)5X~sZuMb zR?7p=Eq>x(lu~-XJoh*BrGKGMeS>~8=VY^v`ZTlOneY2%<{bOq@UPleN31trzgvx8 zJ|^mE(4H&wZJNDGv+vUEb((#jW7o&6#OI2zIl12 zmW$8Q+k9c_(Pvvp<4>|)*fW+Nl1-LR$+Q<*9wp?D<7>&x3(saK) zCn~W_)$~T0dQj|&+O*=00o$kheaEh#-15gD>dK^+eHBPj(>v;u8GSiPykZEuL%N-U zG-}!7s6H$EAbXaXfs7NQUtX`P`<)Rvt5}1;6LIU2aR=o%Z-2tfs&t0!b2k%uyMfuR z4B8Dhzou`|H=c4Y=f(3&aU7OC#kd!qGglnv6?KVQK{U(u6}T1jHpaAPpM2SRPCfep zxtzyhQ;;#oWVbnSNhzi?dA)osHTdL3v)t}ecaG&=oSQ2Q&Gwz6 z+z=JYlpGV0r?FpY|E-S4oDd+q7~I;VTqr^{#h%966&Q+=Nkh*D)brjsq_iDuM+z7} za)cDyM;ZOL)pe*>Ug?ffd!XyR{T;FuDa$kiy-NE@S6}Wz1XF~X_7dx1(N;vc3< zR6-Z-dCMiMRJQO@b1&ip*bHONkmWG;k;X3QFvX!>Dp~Gj@C`<#0c2Wl)^cOknAT@4 z6JVQ`OsDmEXM{}x7c3@yfPiMmIfH&k>@Nwe$on#wCnY9$Z$*7ka2 zPE!|4VIC8s=|Gyup*eh14T*)=3r6*ARUQGlk;`z2Ke#S067=>A z&0c-9Nn~B*Ki})^w|ft?lkUSOo;&>)lfHg(1`r0)P{vo8p0~f~K7LB)jtPS}8Kmtm z8(((&^X?P3&2fj!v+Xj2`l!Z#uaPjpoOObxatMSWa)uFx+i$v$_KP1mCY%I*lAKcr zr^q>taN2}d^`85C<2BXTP|;H2g`^s!BBJn?YTQ=QLKeEG8fz+A&O-C5aYIFOS?Gak zJXFzE7DCm$iWalbhG?y8DAty%Qnr#ULu0U9%R(#C*tIMK;*yFwh>NPRxU2oUqIGwN zm^4CQw^S5or~sE$b49guVUtt~+gMP|HPzA!GSI4OE~(b0$QkIC5cSRsw4s{Is-?GK zpnIyhs9HBN#5mkk%?;J+U_xwFwe*~ZxvrY)s)AIlT diff --git a/mma/egs/misc/cascade.mid b/mma/egs/misc/cascade.mid index 11180d211b4dfd5ce035df41e144a010d38bcee7..5f7d8da5f3b81faf6f1a9f73a1d8343ae18e8a77 100644 GIT binary patch delta 15 WcmbQs+Qu?LlrepxnAOJT+ZX{SOa*EH delta 168 zcmZo;naessl=0t0F{}EG)eH<=4h-x844dGr&2ZKhIBP4MwGGbN4rlFvvv$H+yWp(d aaMm6;YcGT)0kn7@TyQ^}wP9nxHbwxJ!6F?1 diff --git a/mma/egs/misc/extended-voice.mid b/mma/egs/misc/extended-voice.mid index 1a0c8991a72eb662127099078438baf65268475f..e195e8638dbccc4fc6cb2ffa36725bd5a55513c2 100644 GIT binary patch delta 15 WcmeBW{>C^#goz<N`w=pj!4 diff --git a/mma/egs/misc/grooves.mid b/mma/egs/misc/grooves.mid index f56e81e4f6df7c96a70a33745928994ec885c34f..70e5103cd15a0837d854b106f6d50bb9267cdd33 100644 GIT binary patch literal 13283 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 MHth59#tWYR1<(tz!vFvP diff --git a/mma/egs/misc/macros.mid b/mma/egs/misc/macros.mid index 761b805e843d9b11db7bd255ea271e00b3419b1c..a2960e0473dc302519c6238092166fb9fed13944 100644 GIT binary patch delta 16 Ycmcb_zME}=2opp7L@}$4&tEeE05G=(CIA2c delta 169 zcmdnZc8Pt02os~&L@}%SjnxbcTn-HE0Sueqtj%!N7C37woV5+k+74&!fU|bOS-aq@ b-Eh_(IBPG2B>}W}A6#%hoV8(Nz-uM|Pvjxm diff --git a/mma/egs/misc/volumes.mid b/mma/egs/misc/volumes.mid index e7f8a77ed8c7bdb93f991059c6451c578004ffcf..ce4cd6fc9e4d13e0aef0c0a2f71dad4fc6f55148 100644 GIT binary patch delta 16 YcmbOt`&W8`2oqD~L@}$4&)4z-05U%Y9smFU delta 169 zcmew>Jw}W}A6#%hoV8(Nz*=4aY#kxe diff --git a/mma/egs/riffs/riffs.mid b/mma/egs/riffs/riffs.mid index 500ee76bb020e573141df845b267ca4da5125729..78e7465cad93e437141626c551ed43322a456bb9 100644 GIT binary patch literal 1922 zcmZ`(TW=dh6#jO7Nm3rD5E4dhQztKJlOxVZ}-AM?~@H2UP%r8l*i#m>9k%L#>>xv z6EzH7#?Vu$eShiRgPraC?Yo=n_j+6FEI+t=`}RX~YpW+}RQcAYFTcX!RsA2}a2iLP zt3;5V?>&6@y!K0e_?wAP7!wd}b6FTB4z7*2gfR|ral9eVgAXUK2xAiB=H#M051JE~ zRQ|<@C3zm)n7pjwR|-^LIL4!&l04pEXG_$61-@-v(^`n1Hm_+-I@C>Ybrbx}o6NRn zH5&-#v;a@+X|iqm1NwffY&T%!*X*%##D z+7=ypP^HL@0;nC~%dn@A^}wR&UIJn(ct4mSm+BN>$hxMr6S*c3&8UFBL* z@L#ABE<-aEqJ&2ZctL&dD)a?Km`;RNlD2AU1V=ue_?T))Q%ycmxRpeZuHuelC?^u0 zDhZzQKUO5%p8YQ>lBVg9(~xdzu97r7ubQKfnimv7Sy2ut`aOkNO^DM+&~n63U5NQa z>zul2Nl%IXW2?9)S7fEPx$$-Fw>-W(cSjiKAX*bQ)oNWgB4HSKcd93hDZDrNv0SuM z6W3*M|HRaq^onqjl4&n*7B=MmWy~9LjZYeM7&tw?DwlXaca*$Rxb^0eYA;Darry6l zSbJXkUBmbOMZGwx^Gf`g5BN)|B2XM1;?TJ*W_-|nghMdy!JE~L(Rh~w+|PP|L7y`j zZ&p|wSpyjl!eM32ZR+M&ylnzz9xmYeBMcfVi&=8HIKgO-ienm|(^)&-lXPQ{n5C>t zn->*waSX{c*Ve4Fs9t*Zh|OgjNAs3a3Q#xmC5DUx&4XqERp>5s6T&vnrrdUl&BPrO zl$&BWZH^Lo)@{XsN%+XRILAvmk+R0KJyzE^L)}kH9piJPfTYyrw@!AE8ZVA&ypm?i zaafe@G{c$VC|DERj;~S`lWNab7jR69MoH?(u?ReDC_ySg4XBecWDGSEh@9U%xC zZTTzC1rb)lMgXiJw$e)alQ;VShb=!Z(&tw zi}Om{YB55I5@=#2tiEa-Z_T0BM$}54@9fZ@^q&S^@C)$I?~`J97xv|T5Gk96JGC!& zicjw+gMU3B?H&2k>fGO?;rs>sSnPv!y6S;6s|()j(%?C?lCnt?+2tU2hXd6g{(c5>kW+d2*#f7B|Rs<8EA>#m=nR_1cbOh#kY)YJh?q(-<6+0CfP> zqymkpl9%$-m!f{D|A2mf()O)I{gV2Bs`Sn*UDB7n%$_@Q?>T4g-rZ`WvjSik414fX zwb8o*un>0G{z9+ay3tLtEYge#yIyCaJj-4~%u$J6|hnv7N zIgFgbCjt62K%WKZ^8kGjpf3aTRe-(@&^H14HbCD6==%UY3eXP$`Y}KcNAA*%G-Wmo|*`^_Ixdh4#Mw@NMjz)&2%{rs1~&%XIH>zO}J&Klh71 z^lofXBw`RHu);wAaqZpG><|748f7`D&E8|wUg zlIoMYbhI(4Q|#Sb7rDp4gX%d}#o%t`9IMbnMZ!^$aQ+)TM(BaZnPtKQvvA8w(mH3o zOzWn?dCy`V!qyD!ykSk#TCk4NdfN)qn)hbuG^9>NS{;j$N4ZbDHR$xl8S~M(pcEKV_{xpg>06jRC_ea zD@aTl!b<63C!_KFpq@gQ&N(JiI^#7)9bBRkN_G%+XPJ43Wf$-Do$`yd=y9@! zYz1>JcOds&X%=(DYaE7KLx~U0s*a$9=iT&(IiY1w3{JTiF`-fB(|_B~^k(e8|^{{Zv!qJjVb diff --git a/mma/egs/rndset/rndchords.mid b/mma/egs/rndset/rndchords.mid index 695ca0c111f355ef7ef1fe12b2cab9f8a4822ed8..a238e0eb7e761b5e7cee543ad9f208a22b2f8531 100644 GIT binary patch literal 4319 zcmds3U2hxL5uLlsrEC>w9}2XMm4s@ROTb(p(Q7Mlcct~UwUH>5kwotD`&)8t$&Taz z4H87y*ZzX`p(y$f`V;!tKJ_Q5XXcWUT(n7$hbHKYA@7|z_sp3yb6Gz=n-Wox6cy-i z_2bJI_}_E7Q9p?>H7Hd^?H5#L%Oja)@N@<$CsnY3%Y68D}Pz1o3v1{HXhJl zzaUzTXyrGwa*f>gl8e`$y;+|>e>uAtozH%~et9vSoV~i7UVV6eKFT9x7k|G-Hy@F? zQ2hz$g`LsWRUZBQk^P7Ab)J;z(C@`Qz3(68iBDPiEG|>2{3#Yq<@u0cQYkK|;;Io)y{C%-T!pZJ-aH29=bP8qHA zDo;vuP?^LP`k-=>Clxv>eHxd@E%owZiSnz;VP33I{?+5J^5ijP8!zJxTHAP?CmYm$ z+>9U7qtXk;II8r3@m{6R7=zLUFy1lu9?QM&`Z)2aSw6(QmGbYnzLviaMnCiChHDEa zYvnIZB;41=XvxGqCe_6MHAW^kXu)pC?eV;a>@3dD31nujE_xyP1QX< zt81T+L7}jrEAXM02Dg7+;za)35F_a&Sue8Z=0g0u%3JX5!J%-Ni*p4+U)w zs8&@YoV-1V1y>rO zq72`s!RU@p^$<6v-hm3o921hYha3CIWd!#Cn5k4}3BFYuGAqey3K~U2AP>A};KsRo zR9JB1x)fx0$qG+_+|@IRMg$zzidE|CDgN#TFCmUq-61dL^1TH@Cbz3_fLx_}h|F|~ ze+$(FVX8J$?o+f0_#F>sXi@Z zrqtr-E>(A_#vCvR;FCsUFtLoQ#Y+npg(**mIN7+Xr`rpOP$O&~&6s(FdNtU##dU4D z-4=bEU<`)MuqPnWaaK4rF0#>9k4`XFHR!VkaSAdW%8h}Ri3cokQ6^}X%yL(%P@=7p zx(3F9+-MoVh=#g@>N4*s@KrDb2ddV&cZ;rZnB_jjEvEaK!8B9G%FNk6>?`&mdAqkB zwxT(^T5#Io1a+y!6mXZj%z<4*?k;)I|85aMsIe&A3O>E{4^`RNqj1P6JZmzWJj-L= zAxL*I`?1m;?i6H^FU8sfikTTN$_7Y<&k8yMJ;OF|Y~4k$CEn|q>cAYZXqJXE**}?= za9y(HxUB(bKrRIE4lz3cqlCIvWH+8*{HyzfsR0e$7GPaq{cu#_WN6lJa>51tSwgmgf z)T>7n@xY>3;~dNgPbJ2LZ((Je5Iu@naCD8OZZkfoJeU6Rdtp>Xk9fd?D=wMswAf~C z@z{z?tC{y!^(k`@KeKKc4*_GIL^ELW664Nhw-aRaF3$I3aYEhz-|{< z6!M@phL>8H8uMN(-x^yct|d;G!a2r%*tbZ;+rgEda;5GwS%chAw8@q}wuNC&aSBzU?4UAL(u(C-;(F*9myXk z!|$$S{v#3FU&{K;8ZI+7QzuBBZE3XHBqtzen|uAs&BO^3XIt9+_Cdo58qPL1y|GEe zaYP(S#L?XPU)=+GxS6a93O=q1be{Zo?7K?^8&?4vw*h-;hPTPwCFE}%Y^AGOth=g- zeG3ZO_!b=aQ)6fxD+laM`TkS+Z!CZ32mceE|6fz~-97wod*$10gH^MPR}$QgNbZI38QrY(^}4oQ(BsYeyb zF=ZEZQ$Uz)e?hw{`VZ3g`>{+{{YmO~&Lt`K1sFj#?e6m4d%pXf?|kPBYx}1oA}Wxg zJpHw{KRG8X=|+7$nv4f8$D^gA*Gsk9=7)5XyIUK-9PCd9!*jZ+=kEM;iEfg7-dcN$ zKL3p9UPyPI(9htKZL8f0(cSIA8r~zWVcg z^_ThT^E=l_>6`K8r>|Zv9iM$Nz8qYPKVF(#j)tetC!?zmFD?dIh@=WXyiYgZqNxrD z%H>4-u_r&j+ z->ZmRrKfA>(HgzKwwuLk)LQLCtF-K%G3LJi44C)*bH+^FJzy@I*LM9rPCoFT@JZX< zk=G3R5B!m!f47KNij=)xImiktlzrxYhcTb}r-)nvB}8`Ir-&@NSHkQ2epe!2nKz#K z9o#JX7ko2uySVwj`+_l2zlM`<`1^da?>@)L2PT*1+7WVDUPH_p)mKlDOVOQh%rk!< zF|L2YF%9<|G4B;$XK|4lE4^rimRI(&c!i!6Pop9&xj1nt@e|>CXkzM!xh=!pZ*v*8 zCa*5C@NYyv)(r|zsCuY0QAkuJ%ZZdjRMM(MJw3vHr!rI(vh+39%6q6hYB(BqtkMIe zj}c2H;_xb|AXNdSPEC0`KTR3=mTD@z;1u{3&M}p@azO$#C7Gt7r0HlX?J3Q+X=>XFh+ z2|I~CBuHVh2*%6}Izy$>BV^GMZOM5EJ~?lfwJIM%rEYizCYE3}qzX9zngUfR6@@L` z2COBDb@hP4F~5Q+=Mm6ax`CgEOkn_ce# z=UeGRvAk%WK!>0!lI}7T%E2l3*i>+!w@u{%Lb!;6qjZA(BpiuWUB(n|Fi)0?qf+sb z(k*fx<0ruTI>o}mTVTl6!Vc?j0IFb!*vb{LZm#M!sIPB`x#(m3&~dha z14_IZ9wEwfXwP(?7Ym8eF%8fPwCijBI zsBJad1=yOznUKkJt1uTRp=|m;HnQAtCcgo~y?xJP@g||cszyhD_(iUDc ziWSN!I4E&ATLM~z#{joQ=Qira&bggt9qA@c0S1t~`r!%g8}C`p4kO4by~-J@;obKB ztk-IIJ&~R@zAZ@Y8b({M3MK7w!mPwUEu#-!WN~B~i&ibsrw@72tvVqLH=H`u(QPK| zY_m#of9fBp^`X4d5+^9>HCu2xP%;=Ag{f5KiioQlq63wW!KZ*Z>BW45LY?(;y@C*Z%dqnuaMLB&8STp?$D@*#z zs+@vSJ7_^+o)7pe3jdts+rjIQ-P^+^p>mr3k8;8LKKsV4|Q54{GC&ZC>Z5k~-@bs5heQ}-sf zIhvih-G0%WN7AI|{g|75I;;7cjt;_2cmw(7WCC|&b{UmOaz7An6o^YxdEl(^TDj&8^|F)wO!AhI*_LFTj3AKwDtADAgEOlEz`T`-$M9l~c3 zG-hAM+dofs4}YHQi2vng;osl2e-b8klw@yXhD5Zo5#NjAtgu1%_($Ci>vmLcY!Ge4 zHpC5MT%sthY!H58{Wadl=Iu_lJKJIya|^KMmLLHYNB{;>{Xbk<+)8Xi@86*oZ+&T= zo3X7WU3(M8Am+Ilr<`sbJG5E1wPCn${4Wu2&QNe!Uq7UGMB)Es_10s%!fK)RnOY|s zoduC1T3$G)uM@4;aYU7wo~G#kE#RM#Hr`y@{|}eGBdrukXMNRuw3*mCk){zZ`^Nfj zPmPW8u-B)Z&elg~;J>5vwcKH^N(}eD?0lsR*Au&v*dU2n^k(j0V+rl3E^7U6})R8nsWl5w6@e2?I0t7)K5@pB*XgQ)tnu-*ww#Sj} zi1KtYO{c@rsxw_=*>2j&59mz$58AHUF4}$nN*C_A7ouD%QPg@o({2dheVljhx#!*| zdu{#UeIj~`6dIvFtgY`qCQ^S(FO>1x{_gg{?)}M~&nMT`su_BbczbR4V0(Rk`;*7? zB1(*YHAyd8$)vh4M!)+B(K(k!LmK@V_Fii|dG`EZ@<)$8-F>pXx4SfXu)Fu{X=ZP4 zd*H@9e<29J|9SlV-#-7eG{pJ#=a>JC=TCcnHTmuPPtKpj8P1;^AG{yq4xgWW5r6M| z@al88|8<{d={D5qwC7ppo{a0X?_r#0J%>7+^*pK5>EHB1r`WXg4>&aGZTI^F_s=(y zzntjxC+Ki>`c8kEf{BPfZcPXH2yd+SZ_wfLT%$inAI){}d$^iy^s^MsZ1iXFF|&?G zICGCb>iT+Lr@PZ_>^xkX2!Qj$i8iD8)9VRLIc|Y zvaNL}Um|xAI6?*sn1kXw*xqZFfYu7J9^;D`AMtfcS7TNi+8%bPc8!`jrWY1s%#JWg zYF(an9dPS5i@@m^83lXEWHgp$BPwFSTY}j-vS5}m z4VziPzD>@P#Cn{l%86q!sDdyAi4Qx*!KsIp+`fUE2+FiqdCaP0FIKn~a zvqI!Ii-VG(3p73yS%#rwS-?lz=NRES_5d5YmxjVcR5-TBxo*KZ+BS30VD4G6U1n}m z8@+>de(9yQSYK^s#7iblO!#FoBn4ddRrtImIwyox&(Bg`919Dmzxa2>Bwb}kV~rr&){f`K>)7BxVTFtZUTMJ3?DnqkC!j?$N1oAk zDep;Hl{x9saIjK|um)EtYuJHY@U6Hd?mvppw`nWRi$s*LaWxiW^K{{1?U7_^F?Myg zSq4teSs+f6addqm`vxw;G`k4dk^Y=$E@EX@`-~&x6K~96*#=tR&Ea3yYo;qPPsMMhH@g{?)L{uK`J7anX`|>aqJ4`KRF>ru3 zWN|u$A;?M60}rv-4XQNAYmkqK5DuiM5P3w%#Vd3FHxq7yY7JTjU6-gvv<%a{?vP}1 z2nS~!Bfhzbfd{NA>q{%(j68$ww1Ph8nuxp0Q4PnfB`)AMH}Q=s$0>uiVPS3`aV}wRxESr@jOkc1u&!yt%z^cB^1eRt zvM;NDL|-1O?mydo@ZizYf&2Fi{YEbaIt`Sl(%&o0;>d!ze9OuzCf%}V)XfDh-Egb;ov1AaHA*g9!7`m&%>=9T z-f|u97i9dhyMi@_(?Hl%%HZIe#avLNk(`HM#)?_IU(V@xf4^A8`ygpm5L41AV8i)p zJ*d*0Q^$M4vM@e)kXu^Tt&top>y%kAf(3eJdbdgy=2fEW zK}}bRPPzEq3c(LI%`9TNnqLX>bZ%i52ow1d-bYLw<3A{;fbfphz+qEPwr*Kt4%Kn+ zcy1OXujy%I;&N)SuIpnds_S%JmX15i;CN9EzEqzH>U7PkLDPi4z?wcRnTT959h^`o zq&R`ue2}H<^NY1??(KQ1WhqlA@wl*?a;kv4;4Mm876EZ-#ehxjd-E8Xa#EPRRQAC1 z`#BS|uIlrkHIlMmmJ7Ov_iQlmrT6lS-`pKd1H{^Rq&?f(+ugapdvoT-+cRrxjT9cmj;`(A-?_54^YR@$ z3Sx&pn8BlNJg#Ss;KK*NF$afzd^Fkpbh7)|WcTyQ?iZ8YFDJW?C%a!wcE6tNelywq zcC!23WcT~Y?hljQA1AvH5C4EEJ=b~d-kbMlUU~I#4hUcScT> z(2rDNAN?@;{j}=`Gvj#wpY>^RkMA9X|J{E_`8>If&PM0s^`QF)oj)0GjN`Mee_o8< z|Geuz3emmKy8i3!$p6zB0tYKJ=$M zjI%b~m1q|)cs#pgYzz%rjB8w0jh_5iOI#i%;7nA zXfeXTtsp4FPQ$E3abN=`Hp3jPnxEBtY`ZN4MHttR&+Ypd0x9NLjJ6dz^y~)2nL@Hk zB;u1qj9`3hgbiAC!Zx5;Irt{Q5Mj@$YHm@IatZPdtv8kDy6tE-4~y!dyr5#fCZlB- ztsABpZOU(OziGUoxfxPHPu*E0l7T|fcO?-`y&g+8NJ!7JlMZfG*jR*->RmseOI zzrriJ*%HnP(#62f%Sq%ZHO(TQmKW)7+-9+uV?V4j&JD$_maHRSIUEs;%A#+jVeBZP z$Z$%)5LHN?x8M|co!Q0Q24ilhyf&#lTWBF3T~$P9YGz&#npjud>ZFMJacYuLzOE65 zl>)2dZB2u)ys4 zgrUGgMJ*6})StXK~+oapNimV4E zS~X)&m5d-UU?K*!my+xhk}Wb!R^>UyVaHXZ)-Gap24;a^$V@j7Nypd-K4M{!?`{|` z!y&OL$y9YjKUkm-_N%$b2vf-d{6#4iyE`yprKEQBQQZW^wr1QTo`EY9BesuCw6qcR zav-INx0BXZ+$O>-$=2 z3FmGDJfxM%$yceUzKXx)R*_Vbka&Uu;dMC!eOu!Dn6mQVxR4=$u9K5`83WBN2u>H* z!xpPBP_r&>v#CpbTFN0xR)fgg?;YK@8Eun|Ngrbv!H^(IMLngHZB@HS4@hQI$)q>8 zth@s74k$Khb^;R(Tvu9!(dXfo%B9P$VRI?v#7(J@#_7u1`NF`qy9f>|GQer0n4}(P z)x*4K$(62;MSLbJe7zf1cpi&ppwBV>7K0FTq+ZRn>94Cvz8T6Sk900MnyR~H2C@x{ zA{d##!c|;#3e+nDGM{gXR0v6Zr#J^h9!h~5O2eDci7z9C8jv=pa}s?Ph3rv#em<&{ zu5hk9dDT-wew^dcpoV334cv^JP^b*WCu9a@$rO%X$hgJ*rkYw>kYxP6Uw~QD>=t3m7r`daQoeQmdmvxBEb)+JM!rt{%fOLn znkyf4b~JtBs`>-wPF7W4GcU37yWrQr2>YXkuV0hy=5>}}@($djN)&FFPzWOYzyMiDqBMOy0Ap~C(@wl9GpO6PF_ChR};(dVh>L1Z3C|EM{s ze}fcHir@Gz(THJOM|=qk5#oJ5Bg7HQU!Z|4A(CU-YzB&r#6H#0s5vglV-6?9_~fH; zE2B*y<5or+`X?Fc9W*;|qZ@Ug32@9Ec!S;JbkK@!uzMV!rEYwIhG@F%ql!jLgzAek zjG9q~tqD^t=&D|5Owv<@q<;4^{1kH(kf>Y6n0=yV*n zMEjXE8VRJ+*=Ei>mPRv&L?OcvC#|w);njN9t7ERYv?ODo<}QnuY%KN%`@>_rN;ettQDTWP@kjE$!3TCXIzVSW38&!!YQZfIe4);M^r~k zS)z&+EWVp8m0Q*N(Gpr!BpjPQ4_dSIKeXKNmT_`**;~a6%NF-NXO33G&N9hwRUpeYa4cW;@_fI;^J6uWKE-OzwwF&-VcW_j=vtyk7{}A|gmGMf a-)$|i7Netfo?g#38!YPWYK{0rp#K4>H4&%) diff --git a/mma/egs/scales/scales.mid b/mma/egs/scales/scales.mid index bdec69241614bab83f36ce7c6f3cf59f30d0a578..b10c55fd372e54791049d3c380f5576ea57f3aac 100644 GIT binary patch delta 15 WcmaDWbxm@DC}Y}0F{_Qw+jsym(FP6x delta 168 zcmca6`BrLzDC6IWVpjDVs~H%$92nRG7&gIKo8hc2aMo5hYa5)k9nRVTXYGWucEMS@ a;jBGy)?Nrp0%-9*xZr*`Ys1EXHXZ;Ob|S$5 diff --git a/mma/egs/simple/bill-bailey.mid b/mma/egs/simple/bill-bailey.mid index 40ed913a5ef7c8c214a6ac7ac44b63c47a58569a..b015e7824cbeb83166c2f8507af00cc67056cca6 100644 GIT binary patch literal 18692 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 I!ykG5FQ0?Qa{vGU literal 19140 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 diff --git a/mma/egs/simple/marine-hymn.mid b/mma/egs/simple/marine-hymn.mid index 524cd44bda9be26d04fa0604582007a80bf9d50f..02120699f19ea51abdbc817d3b891ad189025c5c 100644 GIT binary patch literal 4214 zcmeHJO-~zF6g_T8lTt-p1QI)0Koo0aVu&qdax53gf1JkO}G6A{SjTz``#PdGajc(x~NpC3*N`Q=bn4+eb0}{ zE^Mp=co#mL$B)^C#wP7Haq9aZ(J=I;u|8aQI-JeU+{Edb_p(M)UufuShSa_?-G8x`{g>2&+tJ7+$3MU;I{=-d-J9kr8cv2#znFFoTv z6#<>jp8bP$_T$EG&5~aNC*dc)FnrP@pM*=&A|ID%9F&%6yevJYF~CP*@pFuydoS^* z%hD4b#l|bPm+=fpd2VOSS2=!A%F%j|v-$0jA;tQ##PSL@k#~?Y2+oTatOuL_F6Iz6JCqBUO7kPbG`8eq4*%iA!R)OFg za3~FMy?&d4<+{q(fM^+@)g_N#)x0L1Os&kll)3!fl-3=tk4>x~uKBHP zJyh9MJ6Nd&tlqZLe^7k4c%t;0dS$k4J`HWd+D-P{5{E}+ zN9K;?2ixwQ*Wb$Ny_v5s%H{E#q2m_NwP^1=I93S1;VwGY#uL+KbHLg*4|-FzYcdJEqU)##%neQn3QhU|6SypD&# z27O!|rGlF@-IsRgVTXq^eInIRmh*K35j&rvCX>d@L zK*#xTkx=U+H8MSxHi>F2SRiPpzP^i8-&y|4IFVm{i04Ta85Q%YHJSu6z&tfQsUV|Z zo;uXAB~;9*NU6vYGy%*3DIiPegn~H*DFs;yaCzR8+ly^9D;ts_8X-f(y#fj{T}fqF&q7f5YBMKBKYGbTjnhYsouOjV4_W$qZzw=A$JPp3>&OgluWqoV=ME(tU5iKINiFnxx zM1dF(hgFI$BesmV?zDxAh!ini#>9pdpl|jFFb+%*I; literal 4483 zcmeHKOHUhD6#kr$M^i;z#O9GK0L2>N7=ne2+y+GKxB-tJA#M>#czFySzp%0EA&byO zG?1cp%c`htqAt5j-|xq=QQLIee?!l`cRaphyGgsLRH+N@ob#P?zWbdscg90%p_l`3 z5-yy^PpO5*Cg3`TBiBpOhMwKlb3^O*hEl1>WgH!UA*F9;7aG}(O&q0Vp?s;LZ)L0cm7!|3QQFeSiubBpm#fvR8K$;+e7A5k4r>yxQQJM& zvW9UO{`m^t_3jv6?4I@S7=FBc_8)jm14vxdC$)Dl?@-2 z2g*i(E>6#4xl}eTkxpmK>B;*!JEGlpgw7qIQ|g^m3(tAsbLm?5mMCaV_T&JY?5mBt zRWtkqIP@<;x$W`;3VM}QmxA-kBCUPO3a!0-?N{!Q?N)B_=rXP66tTVx8P z*TPvaluay^4*~r9^iU=xjKP}oL-K*t^OFZU=!** zLL*;2ymr9qL-fQZBxcr}J)2y=wHKeR)gQY9tUul?D}FGOUWTH=Uv{P0Ed(9&`{`AJ zginsv8DEp)qS&f*IGm=9dA*Y?+X=07=QppCENY^+U@qW&%@RswP0gi&Ii8>G@~vjhfUu; zIZT>UjkE#PKW~Q5l4tNKQ9Yiic(~HH(=9B5@-Ga1;?%I15G;lL{?JZG&bJO~?@K zNKjmc;vAZjp%|i^h>2t(NYq@12o^|Cz?Me3h)ZqLMUb@}#S?9DX<&Ucu+x!7T`v?$ zwI|_U)d%7CE2=qK!8`7px|qXWxj=3K=7NCt2sTG^a0}O+Auj{>I$hS`*6E_#UY)!; zc7x)&Eeg#Aaor78)Wr(Scu8F>;S6{7%DTF!D1uBd*h-(xe290N&ByR zb5xNWF(^0TD^czZe~~`)4${6iG#{4z4b6}ISVJ2_#;=imu<9*nUMwp$O@Zz!Q;t~;z#P5oqi2g$~2>-tbMB~+OS2+S@!4!EOrs>?5yqazM8`J zTdMH?N&a`9%hrp;Rcrn5-YjLeYKP(9fky!y!8}5n=0E@l0wI`%KnB4KLhCZ-&ttrT zi99At<^cUaHx5hyla%dW!*~`G>zG_^iv)_CTbFqP8iHAbvJPwm!5l()2eyKshLGmK z@?G+ldESbg$F!C)p<|LLomy8gzJiGiCaJ&?2@rP)p@Pg4$RfCg(3%4yt$KSNXzgcUbQ_AgYoxi5A4PG*8Hr=bmSxE|Nsc8ua$-A{ z9P2(E8|wgz0)5#6o3@)^|AC^9eO#a~S+u*`zoF=J-`dBfzjMgZFm+O-L0|g9%i+17 z^PTU<;RJJ!9}>|~(&!ldE|`1q1b6>H-)KK|U#zZdu0Cveu-y^_j!EAnj|Z!pD|0Va zK72yo%qE+D+d|(g966HcJ4S!EOVq5WX@;7rkiA@b`uyc)%i2dDuRdM*WHsCJaCP;0 z&x?;fTYX`E^2tg~LA=@M{*u)sy_0YGeDs$WYX2%1Utbi4rsjVM&o?MM|F$JO|HpfB zK6d?Y!}H&_$@%oPKa=zEj^EKYy%dG=&+z-m_{zq{=j!Vg`gK>ScD{>hkNR-#!?_*j zcAR@~?!oyA&Q}iUUp)G{jegyJZ=;=FpKM>o=~pMaDjQw6YpZOu;jVRVqZN0p*KxwL zr{S}g^6W}=;|iW#`4p$WI(hZ!##NTPC(pWW3TM|MPQN;NbzYubUBL-=2Xfc`GPJiF za`LGW*Zcp*aZS8<`AJRvp6H9hx`G8mHgWTl!*TRU4t#`y(Zs-X=!YaQemW z$Ss`SBv?c}CcUf~8B#>%80n-LxS%~_ST062lM1OoOOa-;labeKB4)^deqiQsv~`cg z&FrCUQa#laZ5bJ8Q1&y3RLuf79rcpTQ9OcvO?2)Wwpg+7)UqG5a?z|A7U;D?>N=~2 zZ8piqb`3|a6$_+h#H}Y}IAl7cm+H&vYo0=9yta{%VA#)_W%}d}K(x~Inq{bd_#G0g{W~q-z4=7dCAj7#Eg#CI> z2o{QvOBy*?sH-n>Y@+oQ^3BFsUqL-XfXS5NtmzYw+C@%TP@d`~N`)@qc0g2d#`le( zL(Ps_C$kqyAi~Tk+Cva%5D7VnM@%0V{XX>Xa9{L>UfC&IGY2HAl+7UUM9PAhT0Ux1Q!Gz{l(6qZ$Ckm#EvScZHevKM zN~*J8d*+~cy~>4(;ur$OfejR&4H%)Pq&v)Sm}K@vao8V{*#ki`1|JbFDjcz<0hZ6f1mj;&f0;kJh z4>aMljc&HWZAnMeBBW|r7-Ki#%LGe`Q(}zs8;U6-%`#z6s{3LrO)SWYl)VQ2q>lE> z!XA9xmH;#{Y#VG(Qx7;ddLFWDi`lr|yGB1}Mf8l@_XshBgCdm=pW>0D<~dFg+?OCZ z1|BatP8^FoVz>2Ci5cCAMD)N4WDDvRX92Qok#%xJ^{0E>F%lZ0fEz3#$wDBU@dYT{ zVg@7Brr@nwj#^XvsaagpJN%ga=8Wuy0gJl4T7&JRxSN1~+}eGIEupv?k@ame#&-D%rHdff~c7uu5FpNWcs*HsOOZr z$)0mjCzx4ebM_O+CiHn&)C@%?<`nDPW1et`BkC%dnAl|*Q|yD5x(lCcS$#>wW<{pN z=FOXIIJJPsNpp_$2O0}=d0~6kxJf29B{q<^H()p^{8bQ9VPlq<`35sciZ#)*XI^8S z#vB_q*$U}Pl)44evhJ$Tvuy^TJBG-bbGX*j4lM4#Z{C8K2ewGRE8+-%J;a#tN$ryU zsBZGQ^x-XL;$hB%-7zb;O^Avu18E>j?LoCBIZME46H|PdHHg%%NO2gvm91#{ZT6BU z;2s%1{E&Ti3Qu>DQ8U^*#*LfMkWjBkzXj!RV+Uav0d#_1KpyQXCz0#yYsO4S-;>%p zl0?nmGK7I?(j%{o>xcSneGNXqTjsI1pl8RZ;CdWBpo(x_$DSiWa$v?aNyGzw0PiK3 zJ@ysRvO{@Qg_of^((gzqR*})YD0r?w-ri$(_1k!wj5NUY8=(fpu|>V0h0cl2ZP8Fj zt#Jq0yM(+*%Jw8djya>L185+frz2-XD!FZx;FSgs!#?76<$7rLHpF+0Yq)ic5~(ew zb91qWyHZX^o>J-&@*)idwF~fhSCU0ieoIGzD_8|=Q8ZI(kv$Zj!!9czkB3DPf2vX# z#ZB$Ax9}%*N3w)8ayx_KN|tt{#~m&hOx%r3=-31}&s!$9i(^g`O2e_!5vkO6sNa|( zwNLsS@stRoLs7%Rp(30aLf&|NOtXjF0eE^Fo@}GgCQl4_VyS(0GIaxV9w1OFwceNf zSo%$AAn*s8{Zg8k^=PSi@b7X*hK4Yyq0o%{!zQY!T^ASmgW98NfOAOgCUV$NNLQH)u^tQdCMp;Tyh2e_FZ@vv3ErRr%k z!^2t&^4k%JT(FmamVnuVIGVF&1J~EF zHX{PKh+B??F;qcNxyFDLXmXOf8UFEJG7KJvH+k$a;X468N&uFoFbNn5+bJK{*oSa^ zz+p4Ym#~4<6@ygvBUCuft)QO3=@9JMh6&~n*y4QxzV0%-j5OH#q!yuDju1+cYMo`p zX9b`E=1?;Loc)ATjA#X4?HB`xKn9qK^l*<%bCFC8aNVL5@7s|7iEO7^yn#p9bX?E^ z-?CLpQ+L=5JIw$t#1aMB_JQGG62ODQ5D2=>$S1;v<7ysKT7-xg5h#0wU1SCTEhv}Q z7w#9QF#M1)rU6{uu&LISO9ikHsLfLI&hAFbQD2!wiQ9oq65wko6EMdTiZJL#U9~g+# z24U*go1|(?;W{7T8%Xi~OxO~^fc_D*qToZ1tck-Y{j}+ndq; z0B;!%1F48k zWQ%mXC1KCxJnTr8EPEf;lc6nvw{#QmSJw;44^OY9l}G=%w2NauumvKC>J zJDNFzSO{A&_mY$bvn8r8TUWA6Cj}Fqj&;<}BwmQaw{wDte#W>=8jLBNw{x6uv=E1U zRuK04(r*c@5kP8g10Ty_5vxv_In%p#h{n z&xoJrxkaPCI?IbF>Y{U!c}+B&#p**!#j!ql-#Eu$3gBxK-A*Z*L0n-X?2s^O~vkIi^wG^((;d_ zMD|&ac(iQ&C`!JaR6BX?%kU7{_vm#?NOJ2Wmq~5pw2{}=h_)l&LQV^LEe#S9&`M4# zd9ASoL|m~1w36FO#nxB?zKbGyV!=h48{xUh2$-B%s2y^-4C|0DWcD`Pe4(kFr7s$KNAk|XVMRG2ZcX6oBb*j!a zU8k^1a65FVUY2)Bp~2$iC@b7d;==!ylJ6qbMP8RAPRwEVg-!28U?h5$r&bZSmeU-YxR=TOI~k-1XTm%43IYvTUQZR zY+d13&VKUxKZ70W39EJB_UZ>x7nRtLEqRP1QP++peD z>QvMlB>0{pCq-T==DUvfdh+y`?-3<#PzSt%ws;@^KNx1q?~Jz}M0sbpVbT2ed50d3 zhFO#okCuNp#qB!Gi9$3Tl!7c1AKZ8 zdX_hOaD2qa^y)^Mf-5WdupL}^#K+c8@c}$&eT3uNpmS-X6Rh*X`Z2S1-Cz~zWx1Xg zbxWd7c&;pqqFa3ITw&R+8SuOfx>iK&8jG2CH%uIF@Ud&TLGM`PuGCb|A8w zkbN6mt%~j{>+afTFS=gHaZfxt5EWH9?lly(zToV%SJ`~WlZ_52GB-Jpo~Po)rU-Ab zKvz}NtqWya6n!R&HY7)DlI*G^`y)PfKIdrCPnf4?gSDAYpc%OnrD5&TYohutE4}i7 zRb0Kzaddsil+JsS@_SV+xA4!wkYa( zC2?+vx|gEvIjf7Rw$8$>qNweuh#jym?R$Les3QGA`cqaK)j+ZqR=;ZlAvcyvbBf=$ z77+-;9ZzGD-&8KK;Cmi5m7%M2+;dNrry?JPyH(dptXR!m8BHW$1X8PGE>-N=@0RW~*4ckfEk5HCvR-Odriw znk}z(F+)d%q-DJ3?Bq!Zp3P7*1XWqH=(sy|yg1$LS86|1)a+7|nobnym^+#9=~!|4 zB;tQh9yAvzp}b?R&+!!}-h;#m1x7lF*G}agbtjInL~sJRIHl;QODBp%e>{ESOP_wR z>Ey{Pke@#Q*kR;@_p%W}`uvfcz#m*UF(?}&e{8-^d9$9$QZ`Fg?jVC82PsRG9U=s5 z4dp<=twl|l5z1!B8kw(C-mF7Sd5nV51GdvoWuh`#hR}*RP;eVilQ%@=VG4%k>y$U^ zVxKN5ha`*NVjmeQ0TAT>blzD}ed*|yE#0K41NPQAp zx7a~@BcwFPhLmz_Ciy&ZI5wfYS@(Hb&}`2ECmkyqd|fn4G~1aI4qP|+1_cJq8uN9^ zn{_MN`Nc`Rj-z^btwMyI?4%T`$w~`sOtX_hK_+_$zc8pC$z+#gvQskI)yU*nn(~04 z#(X`uZ`QN;U6Fs7IN(BeNufiVojIvB)Hh}E+ZRA-dcID1vyK-7Zk*8rt`!mu_XZ^~ zgE`spaowawq~nI?>lD<@C2xX!PwEEn53!txNaq#!S= zdsw2vkiudej;(GUk`#=^RyPkoyd7txZhg{?m@b$i{js_Yl7$!1p;+C#0gNOH2F02o z)-Wbu&4^hG=S^?Sn#`8^ECHzazFCr{*>tSAydEm^6cTHllEX+iHkH#<#uQ4&r}DeA z1n)yw>79*Cj^VQhzs|;INe}VxiqDd+aDIJzmhkY3&62TE%8!v6le!H^-3G5?X#wi$=*ib{P>zpJe7t16DiA{luWs+w}@a!>61QDwjxI79b4(rtbi;2GkSUl#u zc)t4R(MQidSAY6|zVhzEc5TtQ?czTN-Ywi*@)up7YD+@8;N1b~qH`aQ&s(=$i!M9! zxNa4>@cNR_&u16#JJS{GK6rkfy~Wp=yZA}za`ry1&sld_HhT}(S2OoPzo_oGiq5;Y zU6)#lw~*ylxqg|y>E@|b-Nw_4?p-|n&r5%rq_1XY7G|kE@bT^L%xs0P=dR)3S)#na%_*U(Y)DE^{XEgzgBvB=m8n&lMKtz?0+ah1|jdz3yDF zaC$tOh1T%cK9?7pN+@zH4lNX^{aW6CB?But<*=({k*?v3<6eJrqj& zd^cP2%>|#@r~C2A=8WIX*IvKrMfAshA1Lsn7k<>{%H0cPdMw93e|$Y)f68T~qIUY) z4BV=nF3)jdu9xuS@oY)roWk*S=k*zo-aei!~D#aa!mzLN5t@26S%D{{nAKOji)0BzRmQrX( z9Kyc<7a0BnjvSfc0vEXR&xH5(lkK=%5^J^J?%TI-_fw;J|E`FI}hYyYvSrJQ*yC)>K0N6?JiIk^@9_AzH(Pu7u$Q@mqc3m~4>Q75ntGNA&WHZxsJe@a6`}Dj%bCaI4CC7NS>G^); zV|w10ZqRdMa=$+*S>>ADzXs3Abv&I%`YtP1KA~q-Gn{Wuru3Y>=F;=p9l~AMJLMH?VOPpxEr`swt$EmEJ+*6lJIraGp6q71A8gSg)^uPcexO9IIrYc#bN?3DO5AUZq5nIcj2jiH*gu!?2P z&eR2GA3VeW7RrQjm_P$`pr_35Llw{!f9IT&Lx~=^Ck+-jGj zXO^?iT5t-gKsVK=pxmamDunn`O^0aOWzC*OFUbITfJ2*IrbKhKCzrZ!<$5sPZ&`MW z*lZ{kYE-nG3r2uqkqG1`V_NWBXw$L) z3+e(?bpS;=3*tVf#YKcZNz+`ZGFh;3FxLs9QF7+2P6s)s$eF8)Mo`IGvLcM5FA=Rk zitq3a3$C0*rNVthWwP&7 zV}cn+;h=~!&bOSqGWH%j8*5L+)%k^(shK!mCV&*ZK;#5fxY`k5Gd;2)ytyBv;E>(a`5LIyik`9~s^P?_ z%k;}Isq>3~x>(3_H+rVqgC!W9nCu0`98)m4o+oshficC#O0|}@xpZ*j@Hnp?FaTEb z*@R9&b?m;NX0)f2H_wjt=K;CR{ZmX3CJX$N(vhOD)rWJzoez4c{B*D(&3;g|aFd+z z9)S;v8tQ@5k!L9=p43kCI7ACD?4a(_u?b346=sUrM>9>1-m?z)XWjzBq8AH$EMF}a zxSH2_nU_@csVVa5;LYxSop)UC-wq=K9x)s!OO|RW274?At;z2i=o93a4Vm}oQb)|q zYxaM^?CRQXu2S-eytq4*1bh!@Y7WBib432&=SZt}{NQ`{@Au@VQgVckq+8YcQB|^= z)d>I2o24&kyjf`+;nU|FCg(GAt)n@~KCLYu)g=3)%4`1pN2hl)_a94s#)ay2Bmp^&5^BW z*Tq|rVC}MLU%aLS-I3|Ln!O~RFTu*lRYNZMc_8Y--BkiH5ZNG+vkumhr1^J zqJ+zOe)OUt?zZ@t_tw}8AZ>~lOR#-8A0X5vh%TD|0Z6w-CY-!2-lhcYG251SYp)!Q z#9MvEgq(=BKRQ`t*^vZGmrX74wj?ls2fXfy+Z7)Z&{WSsfk4v|cT@a^gzIB(incFq zBt8bwP=D#jns}iEjZw}Mds)0dg4L0!Xs;-;^#d$$zk{v5J!ta*mWlG7tvg%d??`w% zn;Y1Q&Z?q8BZej${k|Qa-7Dt3B|`+ f8}F#L8mwcXFKHOijUn9qf6a(tW~x3akQ4qNDhQQw literal 0 HcmV?d00001 diff --git a/mma/egs/tutorial/fella1.mma b/mma/egs/tutorial/fella1.mma new file mode 100644 index 0000000..f8cfd5a --- /dev/null +++ b/mma/egs/tutorial/fella1.mma @@ -0,0 +1,23 @@ +// Sample tutorial file +// Fella Bird, try 1 + +Tempo 120 +Groove Rhumba + +1 F +2 F +3 C7 +4 F +5 F +6 F +7 C7 +8 F +9 Gm +10 F +11 C7 +12 F +13 Gm +14 F +15 C7 +16 F / / z! + diff --git a/mma/egs/tutorial/fella2.mid b/mma/egs/tutorial/fella2.mid new file mode 100644 index 0000000000000000000000000000000000000000..ef5adad3d3e9c40dca6cbdf8734185837730038e GIT binary patch literal 7060 zcmZu$%Xie~6~7uMrOipFU3UZL#Gx4t7K3>itkFo8C9vi3`z>i61``~xQ!s=Ol5k8; zeY(l2n|9Njp8f+}wwt!gcGLbz^!K};#LPf8Si0Z+?&Ei#8rtjk?~2Gz#FF>rU+wkB z5Ab$RUR%EiAMf{{?B6}N_xxPD9XRrO>}T!$C;j!u{W}lj^~%_pKcAD=+wZ+sY5Y|F z`alg}2k?@vY-=IdSTjj_Y!AaXiG^>3nU2oEIBS za$cw8c8;9u+xv*<3;E%qYwDj$yHTp(w zyJguTaob7`Bo-@?9M5=AdS-h#wc-`aTjr@JX}pZnF*^V~Ypqxn#fDcpK1Fu>*-WNF@K7WzQP< z9Xz7xpAp zD_2u<1Pj`;4a9UnR?I9&oPxqj-xmzTIMn8pir>miVY2x11NLj!NQJ~AvLf<>k zLWC7DuP64R3P+5d!_!Q8#+1h(BW@RVc3QiDbj(f!AV3=Pq`-%vNnVKmrHOS%=@tJ4 zBd(F{xWIM+MTCnvv;b#DvyhX+09d7%TZ{sNtDI^{Me$4x4hG?7t}!KU6$c3qnO_ZZ z6~aq@jW5Uz%{|)O@iID_JW}n0Y%H=us|@xC4QADkX~Z*ntrSS`89^9HhUBT`>=wQt z(1QEq2rC1-epBv&x>?WU+C)Arr&z{9=s-3pt zZE9N1&>lO+zdiQt&{!zV734swovq?*D-P_p8F`BCE&g+WVES+mv&L=~-VHrl$-d<+ z&`0*SX-MFNVt;FjtLe>Ny+C~Qw4yU5O+FP6fuw(^GF|%aETZ~oNpgUrRButKe@L-D zyi@ruFl++~T+HpOII`jy)p$jc`{YCoda?R``OT@}?8WHVmrDdViBR8xg_(VY@>N%6Q&$BHtn16-a_l1dd&(m!CvyVDS*=P^ z@q3B@`6(w3EMK$NhptI+Ib0y212ixbO=jvW=0wI2*G%hpnE1GhvEDM290-@Exkj0A z*>1s~JS69kwA`!&Doy-{@H)j7!B?W)wP%Dw*5sQyrCpARhw%zFZW^5IW42%LyKA~; zn4u2|(HjY=gDcC5_91LQ`Kwh?VUPb5+POdYN(cTrVa=XUG5dhKjL_%FBSObqEv7#v z9kl1zEP<ar99m^*@5TIjBhB<=wpseyQ`?qUZonB+1}fM(dWA{w z7q4vl%xzJA^gzn@x@rukp_xZUW7f(zzRjG~Zf|VJk}u$|;q0;DpwV@WQs^>wJ8YQf zC+axWX=j6c-C;}zHq!*X2zPUxZtRV;f&CfUp_+Em21@AABMb`@ZhBEMzWdMEpSACC z#ISbQx5e$S*A>$QqKYV(K3_?`$1ZjfQ5-rDg*^dxxfj7; z?Op7Uhz`;K_$!^W9v6G0V6!6gj?rk)%e)Q;hwhe~x!@V<%&A$`+)P!l5c-s+P}4^! zeMHIJRC|_#R)8(etU8kWSYx0!0W9XaPS0Z2V-x}zwXKkro6S(sFmuz?0wH45IInZ6 zE@smptD8tylmkw4%S;gLKfo3l!m-HV4kOcIUZd+48oPWbP-SEZBQwEd#Td6rj7!vu zMjw3=n3IPYYqA}46X{I^(BDj!YOFIZV7yBNXoDtv84*kO&w`(b?Vx<%Lgr>V4lvwH zAGz_C7V3;H_Gd*YWsA_l8SpS~i+nSgjJ+2|VpV`&!;_k0eaRq`A$yU!OwK|VviHrV z)YpWkk5tNyk-l>Qpv;Q-A^?T2x~rIHR1+?8ZGa-)ebXQCnrloeFaYI)Q*;kJB*$7o zSc;$sg+@%cBbj))*mAi$bz^*p71JNzGGMdteSzMtm}K5M;#FZgExLWKy98fpIs0ct zw+Lx&>D*jrfY7TUoLg4W!*lcX#~h}cw2%Ue?%Gcta}rUbmN|AXZ(eNIq)L}_YT8`v zV3Z^MT(I2$8W5GY7POyuw7l3cur}z#$CeT&R`MBMc^&fEQplM>V7Z527IP3QKB>;- zO0q9;Y!Jvf+%e**%kpNmY6cWD>!pclI1Bf|)^TPexvN<^sUGQY1l_-ftf*ioDL0MW zo>ZH;8|1Ko-|sry75Ur?1mhmsO}+5@i2N1sFt=wBI}1jZ(j@7^;FOLO*7lvKFvIT) zwg`nC7Uq8+{_(+j!5<&C`VSxc-v94Ml|R+)9N>468?}UgF4m_H>T;S*+&`F*lbcTO zz>$+Hjg@rLtv2NRq?|Sy`2l`Fxz@<|$DLRM2y5~q=6PQg5`+?Y16tMfRo1Lt+!23E!c}ZdtE!1a^v{sV zjN7-xzbzs9SF8fclPc`-0}1ij5viE21nUy*tdG~66{LU`!TPfZPcc!yR8`Q4s80a>aD7@)ssn- zxnh3gB@*KIDBxX^s$N?{^vZV6-BJ<#)$-^K%s^p7f)$B|#8(l$U|AwaA4H=o{*Hv} z7?bb12F=)QO{4}sUE;}+gQ|O3Z{V}Ap`pH^nrGe(HGD=PHr}!d<%;mH3|rNdp!rq> z-;!WnA~;HOSJc{k5zY3GihVG_E@XS?VF$#_});84hTMNPr8K+>@~Tc0S`|Rs7U+HkDC^oDGRR4K2?!%E1BT zBcF%b%`44k06kJdzE3N!kZ6vv-L1XlHCk6JA%5#O(HVFR8+s!)Xp@a4 zGA+L_0ob5rkF;kjX&eBk_0prN=SzrXainD!n F{{xLg&>{c; literal 0 HcmV?d00001 diff --git a/mma/egs/tutorial/fella2.mma b/mma/egs/tutorial/fella2.mma new file mode 100644 index 0000000..305939b --- /dev/null +++ b/mma/egs/tutorial/fella2.mma @@ -0,0 +1,42 @@ +// Sample tutorial file +// Fella Bird, try 2 + +Tempo 120 +Groove Metronome2-4 + + z * 2 + +Groove Rhumba +Repeat +Volume mp +Cresc mf 4 + +1 F +2 F +3 C7 +4 F +5 F +6 F +7 C7 +8 F +9 Gm +10 F +11 C7 + +Decresc p 4 + +12 F +13 Gm +14 F +15 C7 + +RepeatEnding + +16 F / / z + +RepeatEnd + +17 F / / z! + cut -1 + + diff --git a/mma/lib/README b/mma/lib/README index 05440fe..e1caa04 100644 --- a/mma/lib/README +++ b/mma/lib/README @@ -25,6 +25,8 @@ Some initial guidelines.... >> Include an "Author" directive line. Currently this is treated as a comment, but we might use it in the future. +>> Do document ANY variables you use in the file with the DocVar command. + >> Add a DocDefine to the end of each goove definition. Something like: DefGroove Waltz This is a nice waltz groove. @@ -55,7 +57,7 @@ Some initial guidelines.... files. >> Do use the standard pattern include files! And don't rename the - patterns defined in them! + patterns defined in them ... well, unless you're sure you want to. >> Create patterns in logical order. The order in which you define them is also the order in which they'll be listed in the docs. diff --git a/mma/lib/stdlib/.mmaDB b/mma/lib/stdlib/.mmaDB index c2d37380a35cd5a70e123a6f822bb51fd18694c1..6092b43c57da3b25851ba2971c311d89db67f207 100644 GIT binary patch literal 11092 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 MBBg!ITB`&911kSh($ diff --git a/mma/lib/stdlib/8beat.mma b/mma/lib/stdlib/8beat.mma index 9443c51..a24dd7e 100644 --- a/mma/lib/stdlib/8beat.mma +++ b/mma/lib/stdlib/8beat.mma @@ -175,7 +175,29 @@ DefGroove 8Beat1 Adds interest to bass line with alternate walking bars. Chord-Sus Groove 8BeatSus DefGroove 8Beat1Sus Adds sustained string to 8Beat1. - + +/////////////////////// +/// Intro + +Groove 8Beat + +Alltracks SeqRnd Off + +Drum-OHH Sequence * * * D1234 +Drum-CHH Sequence * * * D13 +Drum-Snare Sequence D24 / / / +Drum-Kick Sequence * * * D1 + +Bass Sequence Bmain / / B1 + +Chord Sequence P1 P2 P3 C123 + +Chord-Guitar Sequence G1 G1 G1 L1 + + +DefGroove 8BeatIntro Straight-ahead four bar introduction. + + /////////////////////////////////////// // 8BeatEnd diff --git a/mma/lib/stdlib/ballad.mma b/mma/lib/stdlib/ballad.mma index 5fd0f8a..70da4af 100644 --- a/mma/lib/stdlib/ballad.mma +++ b/mma/lib/stdlib/ballad.mma @@ -240,6 +240,11 @@ DefGroove BalladIntro2 Add in some sustained strings to BalladIntro1. Groove Ballad +Begin Alltracks + SeqRnd Off + Rskip 0 +End + Drum-Kick Sequence D13 Drum-Cym Sequence D1234 Drum-MuteTri Sequence D24 @@ -260,3 +265,25 @@ DefGroove BalladEnd A 4 bar ending with a scale played on a harp. \ The scale goes from 16ths, 8ths, quarters and half notes on \ bars 1 to 4. + +Groove BalladEnd + +Scale Sequence - + +Begin Arpeggio + SeqClear + Voice OrchestralHarp + Articulate 110 + Sequence A4 + Range 1.7 + Direction Up + Volume mf + Octave 5 + Harmony Open+8Below +End + +DefGroove Ballad1End A simpler 4 bar ending. We still have a harp, but it's \ + doing quarter note arpeggios. + + + diff --git a/mma/lib/stdlib/ballad128.mma b/mma/lib/stdlib/ballad128.mma new file mode 100644 index 0000000..f1c56f0 --- /dev/null +++ b/mma/lib/stdlib/ballad128.mma @@ -0,0 +1,157 @@ + +// ballad128 + +Begin Doc + A 12/8 Ballad. Written for "Memory" This is written in 4/4, so, when figuring + tempo use a dotted quarter for the beat count. +End + +Author Bob van der Poel + +SeqClear +Time 4 +Timesig 4 4 +Include stdpats + +///////// Additional Patterns + +Begin Chord Define + C3232 1 3 80; 1.33 3 80 ; 1.66 3 80; 2 4 90 + C3232 C3232; C3232 Shift 2 +End + +////////// Ballad + +SeqSize 4 + +Begin Drum-Snare + Tone SnareDrum2 + Sequence { 1 0 30 * 12} + Accent 1 100 2 100 3 100 4 100 + Volume p + Rtime 2 + Rvolume 5 +End + +Begin Drum-Kick + Tone SideKick + Volume pp + Sequence { 1 0 70 * 2} +End + +Begin Bass + Voice AcousticBass + Octave 3 + Articulate 120 + Volume m + Sequence {B13; 2.66 8 3 70; 4.66 8 3 70} / / z +End + +Begin Walk + Voice $_Bass_Voice + Octave $_Bass_Octave + Articulate $_Bass_Articulate + Volume $_Bass_Volume + Direction Down + Sequence z z z W1234 +End + +Begin Chord + Voice OrchestralHarp + Volume p + Articulate 110 + Octave 6 + Voicing Mode=Optimal + Sequence C3232 +End + +DefGroove Ballad128 A very simple, relaxed 12/8 ballad pattern. + +//////////////////// +// Arpeggios + +Groove Ballad128 + +Begin Arpeggio + Voice Piano1 + Volume m + Octave 5 + Direction Up + Range 1 + Sequence { 1 1+1 80 * 12} + Rskip 30 + Articulate 120 +End + +DefGroove Ballad128Plus Adds arpeggiated . + +///////////////////////////////// +// Add in sustained strings + +Groove Ballad128 + +Begin Chord-Sus + Voice TremoloStrings + Sequence { 1 1 90 0 90 0 * 4 } + Voicing Mode=Optimal + Octave 5 + Articulate 100 + Unify On + Rvolume 10 + Volume pp +End + +DefGroove Ballad128Sus Add in sustained TremoloStrings + +Groove Ballad128Plus +Chord-Sus Groove Ballad128Sus +DefGroove Ballad128SusPlus Sustained strings and apreggiating piano. + +/////////////////////////////////////////////////// +/// Intro ... just an arpeggio and bass, no drums + +Groove Ballad128 + +Drum-Snare Sequence - +Drum-Kick Sequence - +Chord Sequence - + +Begin Arpeggio + Voice $_Chord_Voice + Volume m + Octave 5 + Direction Both + Harmony Open+8Below + Range .9 / / 1 + Sequence { 1 1+1 80 * 12} / / z + Articulate 120 +End + +Begin Bass-Intro + Voice $_Arpeggio_Voice + Volume $_Arpeggio_Volume + Octave $_Arpeggio_Octave + Harmony $_Arpeggio_Harmony + Articulate $_Arpeggio_Articulate + Sequence z z z {1 8 6# 90; 1.33 8 6# 80; 1.66 8 6# 70; \ + 2 8 5 90; 2.33 8 5 80; 2.66 8 5 70; \ + 3 8 3 90; 3.33 8 3 80; 3.66 8 3 70; \ + 4 4 1 80 } +End + +DefGroove Ballad128Intro This 4 bar intro plays bass notes and harp arpeggios. \ + It pretty much assumes a 7th chord on the 4th bar. + +///////////////////////////////// +/// Ending + +Groove Ballad128 +SeqSize 2 + +Drum-Snare Sequence * {1 0 40 * 4} +Drum-Kick Sequence * +Bass Sequence * B11 +Walk Sequence - +Chord Sequence * C1234 + +DefGroove Ballad128End A 2 bar ending. diff --git a/mma/lib/stdlib/beguine.mma b/mma/lib/stdlib/beguine.mma index 1b12179..1060288 100644 --- a/mma/lib/stdlib/beguine.mma +++ b/mma/lib/stdlib/beguine.mma @@ -3,11 +3,11 @@ Begin Doc - This started life as a copy of the rumba patterns. I've changed - the drum sounds from snares to toms, and deleted hits on final 8th - beat. I really don't know the difference between a rhumba and a - beguine, so help would be welcome! - + This started life as a copy of the rumba patterns. I've changed + the drum sounds from snares to toms, and deleted hits on final 8th + beat. I really don't know the difference between a rhumba and a + beguine, so help would be welcome! + End Author Bob van der Poel @@ -44,7 +44,7 @@ Begin Drum-Maraca Rtime 2 RSkip 5 End - + Begin Drum-Lconga Tone LowConga Sequence D4 { D4; D3 shift .5 } @@ -108,8 +108,8 @@ End Begin Walk Voice FretLessBass Begin Define - Wa 1 4 85 ; 2.5 4 88 ; 4 4 80 - Wb Wa ; 4.5 8 77 + Wa 1 4 85 ; 2.5 4 88 ; 4 4 80 + Wb Wa ; 4.5 8 77 End Sequence Wa z Wb z Accent 1 20 @@ -129,7 +129,7 @@ End DefGroove Beguine Nice, smooth easy listening. -//////// Sustained strings in the background. +//////// Sustained strings in the background. Begin Chord-Sus Voice TremoloStrings @@ -151,7 +151,7 @@ DefGroove BeguineSus Adds in a sustained string. Groove Beguine Begin Arpeggio - Sequence A4 + Sequence A4 Invert 0 0 1 2 SeqRnd On Voice PizzicatoString @@ -183,11 +183,11 @@ Begin Drum-Wis /// added tone Volume mp Rvolume 5 Rtime 2 -End +End Drum-Maraca Sequence D8 Drum-Lconga Sequence D24 -Drum-Toms1 Sequence D3 +Drum-Toms1 Sequence D3 Drum-Toms2 Sequence D14 Drum-Hconga Sequence D2 Drum-HH Sequence D8 @@ -209,7 +209,7 @@ Alltracks RSkip 0 Drum Sequence * * * D12 Drum-Maraca Sequence * * * D12 Drum-Lconga Sequence D4 / / z -Drum-HH Sequence * +Drum-HH Sequence * Chord Sequence * * * {1 2 90} @@ -227,6 +227,8 @@ DefGroove BeguineIntro Simple enough 4 bar introduction. Groove Beguine +Alltracks SeqRnd Off + Begin Scale Sequence Scale8 Scale4 Scale2 Scale Voice SlowStrings @@ -244,5 +246,25 @@ DefGroove BeguineEnd Ending with string scales. Uses 8ths \ on the 4th. Use a CUT if the final chord sounds too long. +Groove Beguine +Seqsize 2 + +Alltracks SeqRnd Off + +Drum Sequence * D13 // claves +Drum-Maraca Sequence * D12 +Drum-Lconga Sequence D1234 z +Drum-Toms1 Sequence D13 / +Drum-Toms2 Sequence D1234 D12 +Drum-Hconga Sequence * +Drum-HH Sequence * + +Chord Sequence C1234 {1 2 90} +Walk Sequence z +Bass Sequence B13 B1 + +DefGroove Beguine2End A more abrupt 2 bar ending. + + diff --git a/mma/lib/stdlib/bigband.mma b/mma/lib/stdlib/bigband.mma index 3e138b9..104f4c1 100644 --- a/mma/lib/stdlib/bigband.mma +++ b/mma/lib/stdlib/bigband.mma @@ -231,6 +231,29 @@ End DefGroove BigBandFill Simple fill bar, good in an ending. +Groove BigBandFill + +// Drum-HH +Drum-Snare Sequence D13 +// Drum-Kick +// Drum-Ride + +Walk Sequence - +Begin Bass + Voice $_Walk_Voice + Octave $_Walk_Octave + Sequence B1234 +End + +Chord Sequence C1234 +Begin Chord-Hits1 + Octave 5 + Sequence {1 4. 80; 3 8. 95; 4 8 90} +End + +DefGroove BigBand1Fill Louder, 4 in the bar fill. + + /////////////////////////////////// // Intros diff --git a/mma/lib/stdlib/bossanova.mma b/mma/lib/stdlib/bossanova.mma index 7d3d47f..19bdb63 100644 --- a/mma/lib/stdlib/bossanova.mma +++ b/mma/lib/stdlib/bossanova.mma @@ -152,8 +152,7 @@ End DefGroove BossaNova Standard bossanova beat. ////////////////////////////////// -// BossaNovaSus -// Add in sustained 1st ,3rd and 5ths +// Sustained versions Groove BossaNova @@ -175,6 +174,8 @@ End DefGroove BossaNovaSus Adds sustained choir voices. +/// Back to 4 bar patterns + Groove BossaNova Begin Chord-Sus @@ -189,6 +190,36 @@ End DefGroove BossaNova1Sus Adds sustained strings. +Groove BossaNova + +Begin Bass-Sus + Voice Strings + Octave 6 + Harmony Open+8Below + Sequence {1 2. 5 90; 4 4 3 90} {1 1 1 90} + Articulate 120 + Unify On + Volume mp +End + +DefGroove BossaNova2Sus Basic Bossa with decending string pattern. + +Groove BossaNova1Sus +SeqSize 4 +Begin Bass-Sus + Groove BossaNova2Sus + Sequence * * z z +End + +Begin Chord-Sus + Sequence z z * * + Volume mp + Octave 6 +End + +DefGroove BossaNova3Sus A combination of BossaNova1Sus and BossaNova2Sus. Alternating \ + bars of decending strings with full chords. + ////////////////////////// // BossaNovaFill // Add some bells. Good for a 1/2 bar transition diff --git a/mma/lib/stdlib/chacha.mma b/mma/lib/stdlib/chacha.mma index eac946c..508d75d 100644 --- a/mma/lib/stdlib/chacha.mma +++ b/mma/lib/stdlib/chacha.mma @@ -3,15 +3,25 @@ Begin Doc - A popular, albeit somewhat dated and make trite by Americanized versions, - The Cha-Cha-Cha remains a popular rhythm with broad audience appeal. - I've used ``Rico Vacilon'' as a demo. - This file was mostly developed from the patterns in``Latin Rhythms: Mystery Unraveled'' - by Victor Lopez. + The Cha-Cha-Cha remains a popular rhythm with broad audience appeal, + despite the fact that it is somewhat dated and made trite by + Americanized versions. I've used "Rico Vacilon" as a demo. + This file was mostly developed from the patterns in + "Latin Rhythms: Mystery Unraveled" by Victor Lopez. End Author Bob van der Poel +NewSet ArpeggioOctave 7 +NewSet ArpeggioVoice Flute +NewSet ScaleVoice Flute + +Begin DocVar + ArpeggioOctave The Octave setting for the flute arpeggios (default=7) + ArpeggioVoice Voice for the ChaCha1 Arpeggios (default=Flute) + ScaleVoice Voice for the accending scale in ChaCha1Fill (default=Flute) +End + SeqClear Time 4 Timesig 4 4 @@ -121,11 +131,11 @@ DefGroove ChaCha Our basic, non-American, pattern. Groove ChaCha Begin Arpeggio - Voice Flute + Voice $ArpeggioVoice Volume m Articulate 80 SeqRnd On - Octave 7 + Octave $ArpeggioOctave Range 1 Direction Random Harmony Open @@ -138,6 +148,7 @@ End DefGroove ChaCha1 Adds in flute arpeggios. +////////////////////////// ////// Sustained Groove ChaCha @@ -161,6 +172,43 @@ Groove ChaCha1 Arpeggio-Sus Groove ChaChaSus DefGroove ChaCha1Sus Combines the flute and string arpeggios. +/////////////////////////// +//// Fills + +Groove ChaCha +Seqsize 1 + +Drum-Clave Sequence D1234 +//Drum-LGuiro +//Drum-SGuiro +Drum-HConga Sequence { D1234 Shift .5 } +Drum-LConga Sequence { D1234 Shift .75 } +//Drum-Snare +//Drum-HH +//Drum-MTom +//Drum-HTom +Bass Sequence {1 2. 1 120; 3 4 5 120} +Chord Sequence C13 + +DefGroove ChaChaFill A one bar fill. + +Groove ChaChaFill + +Begin Scale + Voice $ScaleVoice + Octave 6 + Volume mf + Sequence { 1 1 90 * 24 } + Articulate 102 + Range 2 + ScaleType Chromatic + Direction Up +End + +DefGroove ChaCha1Fill Fill with accending flute run. Makes a good section introduction. + + +//////////////////////////// ////// Introduction Groove ChaCha @@ -176,10 +224,11 @@ Drum-HH Sequence * * D16 D123 //Drum-MTom Sequence D4 //Drum-HTom Sequence {D4 Shift .5} Bass Sequence * * * B11 -Chord Sequence * * {C4; C4 Shift .5} L1 +Chord Sequence * * C1234 L1 DefGroove ChaChaIntro A plain 4 bar introduction. +///////////////////////// ///// Ending Groove ChaCha @@ -200,3 +249,4 @@ DefGroove ChaChaEnd The End. + diff --git a/mma/lib/stdlib/frenchwaltz.mma b/mma/lib/stdlib/frenchwaltz.mma index 08dac8c..dd78837 100644 --- a/mma/lib/stdlib/frenchwaltz.mma +++ b/mma/lib/stdlib/frenchwaltz.mma @@ -1,7 +1,13 @@ // frenchwaltz -Doc These try to do the "French Cafe" sound. +Begin Doc + These try to do the "French Cafe" sound. The song "Pigalle" works quite well + with this. Note the setting of the BassRegister variable which tries to + emulate the "switches" on a real accordion. In this case we have an accordion + with three reed banks labeled "L", "M" and "H"--this will make large changes + to the accordion um-pa-pa stuff +End Author Bob van der Poel @@ -10,46 +16,169 @@ Time 3 Timesig 3 4 Include stdpats34 +Begin DocVar + BassRegister Sets the bass register, 1=L 2=LM 3=LH 4=LMH 5=M 6=MH 7=H (Default=4). + CSeq Internal, Chord sequence list, + BSeq Internal, Bass sequence list. +End + +NewSet BassRegister 4 + +Begin Chord Define + A1 2 3 90 ; 3 3 90 // chords on 2,3 + A2 2 8. 90 ; 3 3 80 // same, but with 2 a bit draggy + A3 2 8. 70 ; 3 8. 60 // same, but a bit softer to use with bass walk +End + ////////////////////////////////////////////// ///// FrenchWaltz Cheezy 3/4 with accordion SeqSize 8 -// For the left hand chord (the basic accomp. on an -// accordion, we use a combination of a chord and -// bass pattern. The BASS track is a single note on -// beat 1, the CHORD track has full chords on 2, 3. -// Accordion basses are quite limited ... in most cases -// a single octave. So, to duplicate this sound we use -// the SPAN directive for Chord and Bass to limit -// the notes used from C3. +// For the left hand chord (the basic accomp. on an accordion) +// we use a combination of a chord and bass patterns. The BASS +// track is a single note on beat 1, the CHORD track has full +// chords on 2, 3. Accordion basses are quite limited ... in most +// cases a single octave. So, to duplicate this sound we use the +// NOTESPAN directive for Chord and Bass to limit the notes used. +// To get a fuller sound we duplicate the chord and bass tracks +// with a higher pitched register (a musette accordion would have +// the 2nd register slightly de-tuned). + +// Use macros for the sequences so they are easy to dup + +Set Cseq A1 / / A2 A1 / / A3 +Set Bseq B1 B1/5 B1 B1/5 B1 B1/5 B1/5 B123 + +// Create 3 tracks for chord and bass. Each track has same voice, etc. but +// has a different notespan. The notespan range corresponds to the register +// settings on an accordion. Ranges are F# to F (which matches what MMA uses). -Begin Chord - Begin Define - A1 2 3 70 ; 3 3 70 // chords on 2,3 - A2 2 8. 70 ; 3 3 60 // same, but with 2 a bit draggy - A3 2 8. 50 ; 3 8. 50 // same, but a bit softer to use with bass walk - End - Sequence A1 / / A2 A1 / / A3 - Voice Accordion - Octave 4 +Begin Chord-L + Sequence $Cseq Articulate 70 - NoteSpan 48 59 + Octave 4 // This has no effect! + NoteSpan 42 53 Volume mp End -Begin Bass - Voice $_Chord_Voice - Sequence B1 B1/5 B1 B1/5 B1 B1/5 B1/5 B123 +Begin Bass-L + Sequence $Bseq Articulate 60 - Octave $_Chord_Octave - Volume mp - NoteSpan $_Chord_Span + Octave $_Chord-L_Octave + Volume $_Chord-L_Volume + NoteSpan $_Chord-L_Span End -// Chunck/chunck/chunck guitar on 1/2/3 +// Set the voice for Chord-L. We copy this voicing to the other tracks +// so it has be set at least once. Wrap in case this is read a 2nd time. + +StackValue $_Debug + Debug Warnings=Off + Chord-L Voice Accordion + Bass-L Voice Accordion +Debug $_StackValue + + +Begin Chord-M + Copy Chord-L + NoteSpan 54 65 + Sequence $Cseq +End + +Begin Chord-H + Copy Chord-L + NoteSpan 66 77 + Sequence $Cseq +End + +Begin Bass-M + Copy Bass-L + NoteSpan $_Chord-M_Span + Sequence $Bseq +End + +Begin Bass-H + Copy Bass-L + NoteSpan $_Chord-H_Span + Sequence $Bseq +End + +// Setting of chshare and voice is done here in a no-warning +// wrapper. The problem is that if you re-read this file a +// bunch of warnings pop up. + +StackValue $_Debug + Debug Warnings=Off + Chord-M ChShare Chord-L + Chord-H ChShare Chord-L + Bass-L ChShare Chord-L + Bass-M ChShare Chord-L + Bass-H ChShare Chord-L +Debug $_StackValue + +// Now we look at the value in BassRegister and turn off the voices +// we're not using. You might think that you can do with by setting +// empty sequences (nope, we change the seqeunce for other grooves and +// you'd have to do this stuff again); deleting the track (same nope) +// or doing a 'OFF' (nope, on a re-read after a GrooveClear it stays OFF). +// All of these complications come with ChShare :) But turning the +// volume down to nothing does work. + +If Eq $BassRegister 1 + Chord-M Volume Off + Chord-H Volume Off + Chord-L Volume +30 + Bass-M Volume Off + Bass-H Volume Off + Bass-L Volume +30 +Endif + +If Eq $BassRegister 2 + Chord-H Volume Off + Bass-H Volume Off +Endif + +If Eq $BassRegister 3 + Chord-M Volume Off + Bass-M Volume Off +Endif + +If Eq $BassRegister 4 + Chord-L Volume -10 + Chord-M Volume -10 + Chord-H Volume -10 + Bass-L Volume -10 + Bass-M Volume -10 + Bass-H Volume -10 +Endif + +If Eq $BassRegister 5 + Chord-L Volume Off + Chord-H Volume Off + Bass-L Volume Off + Bass-H Volume Off +Endif + +If Eq $BassRegister 6 + Chord-L Volume Off + Bass-L Volume Off +Endif + +If Eq $BassRegister 7 + Chord-L Volume Off + Chord-M Volume Off + Chord-H Volume +20 + Bass-L Volume Off + Bass-M Volume Off + Bass-H Volume +20 +Endif + + +// To add a bit of life to this we get Django in to do +// a very straight strum/strum/strum on his guitar. Begin Chord-Guitar Sequence C123 @@ -62,6 +191,8 @@ Begin Chord-Guitar Articulate 90 End +// And some nice people do simple drums. + Begin Drum-Tam Sequence D23 Tone Tambourine @@ -80,9 +211,10 @@ Begin Drum-Tri Rtime 10 End -DefGroove FrenchWaltz Accordion umm-paa. Ya either love it or hate it! +DefGroove FrenchWaltz Accordion umm-pa-pa. Ya either love it or hate it! +///////////////////////////////////////////////// //////// Sustained strings in the background. Begin Chord-Sus @@ -95,16 +227,17 @@ Begin Chord-Sus Unify On End -DefGroove FrenchWaltzSus Add sustained strings to basic pattern. +DefGroove FrenchWaltzSus Add sustained strings to basic pattern. //////////////////////////////////////////////////// -// Alternate adds a light 1/8th and 1/4 note aprs +// Alternates + +/////// Accordion fills + Groove FrenchWaltz -Chord-Guitar Sequence - - Begin Arpeggio Sequence A6 / / A3 SeqRnd On @@ -121,24 +254,175 @@ End DefGroove FrenchWaltz1 FrenchWaltz with with accordion apreggios. +Begin Scale + Voice $_Arpeggio_Voice + Sequence {1 1 80 * 12 } + Octave 5 + Articulate 66 + Range 2 + Direction Up + Volume m +End + +Chord-L Sequence L1 +Chord-M Sequence L1 +Chord-H Sequence L1 +Bass-L Sequence - +Bass-M Sequence - +Bass-H Sequence - +Chord-Guitar Sequence - + +DefGroove FrenchWaltz1Fill Adds an accending run. + +Groove FrenchWaltz1 Chord-Sus Groove FrenchWaltzSus DefGroove FrenchWaltz1Sus Arpeggios and sustained strings. +Groove FrenchWaltz1Fill +Chord-Sus Groove FrenchWaltzSus +DefGroove FrenchWaltz1FillSus Arpeggios, run and sustained strings. + + +//////////// Piano Fills + + +Groove FrenchWaltz + +Begin Arpeggio + SeqClear + Sequence {1 4 90; 3 4 90} {1 2. 90} + SeqRnd On + Harmony Open + Voice Piano1 + Range 2 + Octave 5 + Direction Down + Volume mp + Rtime 2 +End + +DefGroove FrenchWaltz2 A simple, little counter melody on a piano. + +Begin Scale + Voice $_Arpeggio_Voice + Sequence {1 1 80 * 12 } + Octave 6 + Articulate 60 + Range 2 + Direction Up + Volume mp +End + +Chord-L Sequence L1 +Chord-M Sequence L1 +Chord-H Sequence L1 +Bass-L Sequence - +Bass-M Sequence - +Bass-H Sequence - +Chord-Guitar Sequence - + +DefGroove FrenchWaltz2Fill Add a piano run to the counter melody. + +Groove FrenchWaltz2 +Chord-Sus Groove FrenchWaltzSus +DefGroove FrenchWaltz2Sus Piano counter melody and sustained strings. + +Groove FrenchWaltz2Fill +Chord-Sus Groove FrenchWaltzSus +DefGroove FrenchWaltz2FillSus Piano counter melody and run with sustained strings. + + +/////////////// Violin Fills + + +Groove FrenchWaltz + +Begin Arpeggio + SeqClear + Sequence A1 A3 + Rskip 0 20 + SeqRnd On + Voice Viola + Range 2 + Octave 5 + Direction Up + Volume p + Rtime 2 + Rvolume 10 +End + +DefGroove FrenchWaltz3 A simple, little counter melody on a viola. + +Begin Scale + Voice $_Arpeggio_Voice + Sequence {1 1 80 * 12 } + Octave 5 + Range 2 + Direction Up + Volume mp +End + +Chord-L Sequence L1 +Chord-M Sequence L1 +Chord-H Sequence L1 +Bass-L Sequence - +Bass-M Sequence - +Bass-H Sequence - +Chord-Guitar Sequence - + +DefGroove FrenchWaltz3Fill Add a string run to the counter melody. + +Groove FrenchWaltz3 +Chord-Sus Groove FrenchWaltzSus +DefGroove FrenchWaltz2Sus Viola counter melody and sustained strings. + +Groove FrenchWaltz3Fill +Chord-Sus Groove FrenchWaltzSus +DefGroove FrenchWaltz3FillSus Viola counter melody and run with sustained strings. + +//////////////////////////////////////// +/// Introduction + +Groove FrenchWaltz + +Set Cseq * * * L1 +Set Bseq * * * {1 2 1 50} + +Chord-L Sequence $Cseq +Chord-M Sequence $Cseq +Chord-H Sequence $Cseq +Bass-L Sequence $Bseq +Bass-M Sequence $Bseq +Bass-H Sequence $Bseq +Chord-Guitar Sequence L1 +Drum-Tam Sequence * D1 * D1 +Drum-Tri Sequence D1 / / D123 + +DefGroove FrenchWaltzIntro A 4 bar intro. + ///////////////////////////////// -//// Ending +//// Endings Groove FrenchWaltz Seqsize 4 +Set Cseq A1 / / {1 2 40} +Set Bseq B1 B1/5 B1 {1 2 1 40} + Chord-Guitar Sequence - -Chord Sequence A1 / / {1 2 40} -Bass Sequence B1 B1/5 B1 {1 2 1 40} +Chord-L Sequence $Cseq +Chord-M Sequence $Cseq +Chord-H Sequence $Cseq +Bass-L Sequence $Bseq +Bass-M Sequence $Bseq +Bass-H Sequence $Bseq Drum-Tam Sequence D23 / / D1 Begin Scale SeqClear Sequence S6 S3 S3 {1 2 80} Direction Up + Range 3 Voice Strings Octave 5 Articulate 80 80 80 100 @@ -148,13 +432,12 @@ DefGroove FrenchWaltzEnd A scale with the strings to end \ the FrenchWaltz. The scales run from \ 16, 8, 4 and whole notes. - // Variation Begin Scale Voice Accordion Direction Down - Range 4 + Range 3 Octave 3 End @@ -162,3 +445,4 @@ DefGroove FrenchWaltz1End Same ending as FrenchWaltzEnd but with \ an accordion instead of strings. + diff --git a/mma/lib/stdlib/jazzguitar.mma b/mma/lib/stdlib/jazzguitar.mma new file mode 100644 index 0000000..47bb086 --- /dev/null +++ b/mma/lib/stdlib/jazzguitar.mma @@ -0,0 +1,244 @@ + +// jazzguitar + +Begin Doc + For jazz ballads. This has ONLY a guitar (well, expect for the sustained + versions). Mostly chords, but some + bass and arpeggio is included. The song "Django" is a bit of a demo. +End + +Author Bob van der Poel + +NewSet SustainVoice TremoloStrings + +Begin DocVar + SustainVoice Voice for the sustained versions (default=TremoloStrings). +End + +SeqClear +Time 4 +Timesig 4 4 +Include stdpats + +////////// Additional defines + + +//////////////////////// +// Basic + + +SeqSize 4 + +Begin Chord + Voice JazzGuitar + Articulate 95 + Voicing Mode=Optimal + Volume m + Octave 5 + Sequence C1234 +End + +Begin Bass + Voice $_Chord_Voice + Articulate 105 + Octave 3 + Volume mf + Sequence B13 / / {1 2 1 90; 2 8 3 80; 3 2 5 90} +End + + +DefGroove JazzGuitar A very basic 4 to the bar accompaniment. + +////////// Same, but with walking bass + +Groove JazzGuitar + +Bass Sequence - + +Begin Walk + Voice $_Bass_Voice + Articulate $_Bass_Articulate + Octave $_Bass_Octave + Volume $_Bass_Volume + Sequence W1234 / / W13 + Direction Down +End + +DefGroove JazzGuitarWalk Changes the bass pattern to walking. + +/// Add in arpeggios every 4th bar + +Groove JazzGuitar + +Chord Volume +0 / / -30 /// cut volume for chord on 4th bar + +Begin Arpeggio + Voice $_Chord_Voice + Articulate 140 + Rskip 10 + Octave 5 + Volume mf + Direction Down + Range .9 + Sequence z / / A8 +End + +DefGroove JazzGuitar1 Our basic pattern with arpeggios every 4th bar. + +Groove JazzGuitarWalk + Chord Groove JazzGuitar1 + Arpeggio Groove JazzGuitar1 +DefGroove JazzGuitar1Walk Walking bass with arpeggios every 4th bar. + +/// A bit of syncopation in the chords + +Groove JazzGuitar + +Begin Chord + Sequence {C1234; C24 Shift .66} + Strum 5 + Articulate 80 + Direction Both +End + +DefGroove JazzGuitar2 Basic pattern with more strum and syncopation. + +Groove JazzGuitar2 + Bass Sequence - + Walk Groove JazzGuitarWalk +DefGroove JazzGuitar2Walk The strum pattern with walking bass + +///////// + +Groove JazzGuitar2 + +Chord Volume +0 / / -30 +Begin Arpeggio + Groove JazzGuitar1 + Octave 5 + Sequence z / / {A4; A2 Shift 1.66} +End + +DefGroove JazzGuitar3 Add arpeggios every 4 bars to the syncopated strumming. + +Groove JazzGuitar3 + Bass Sequence - + Walk Groove JazzGuitarWalk +DefGroove JazzGuitar3Walk Aprpeggios and walking bass. + +//////////////////////////// +//// Sustained versions + +Groove JazzGuitar +Begin Chord-Sus + Voice $SustainVoice + Sequence {1 1 96 0 90 0 * 4} + Voicing Mode=Optimal + Octave 5 + Articulate 100 + Unify On + Volume p +End + +DefGroove JazzGuitarSus Sustained strings added to basic pattern. + +Groove JazzGuitar1 +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar1Sus Sustained strings added to JazzGuitar1. + +Groove JazzGuitar2 +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar2Sus Sustained strings added to JazzGuitar2. + +Groove JazzGuitar3 +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar3Sus Sustained strings added to JazzGuitar3 + +Groove JazzGuitarWalk +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitarWalkSus Sustained strings added to JazzGuitarWalk. + +Groove JazzGuitar1Walk +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar1WalkSus Sustained strings added to JazzGuitarWalk1. + +Groove JazzGuitar2Walk +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar2WalkSus Sustained strings added to JazzGuitarWalk2. + +Groove JazzGuitar3Walk +Chord-Sus Groove JazzGuitarSus +DefGroove JazzGuitar3WalkSus Sustained strings added to JazzGuitarWalk3. + +////////////////////////////// +////// Intro + +Groove JazzGuitar + +Begin Chord + Sequence z z z L1 + Strum 15 + Volume mp + Octave 6 + Articulate 150 +End + +Begin Arpeggio + Voice $_Chord_Voice + Volume m + Octave 5 + Direction Up + Range 1.9 + Articulate 120 + Harmony Open + Sequence A8 / / z +End + +Bass Sequence B13 / / {1 1 1 90} + +DefGroove JazzGuitarIntro A 4 bar, arpeggiating introduction. + +/// a 2nd intro. We use the basic pattern, but add a little bass run +/// in the 4th bar. + +Groove JazzGuitar + +Chord Sequence * * * C12 +Bass Sequence * * * {1 4 1+ 90;2 8 5 90; 2.5 4. 3 90; 3 4 1 90; 4 4 1 90 } + + +DefGroove JazzGuitar1Intro A 4 bar intro with a bass run on bar 4. + + +/////////////// +//// Endings + +Groove JazzGuitar +SeqSize 2 + +Begin Chord + Sequence {1 8 90; 1.5 8 80; 2 8 90; 2.5 8 80; 3 4 80; 4 4 70} \ + {1 1 80 70 60 50; 3 1 70 60 50 40} + Direction Up + Strum 0 30 +End + +Begin Bass + Sequence B13 B1 +End + +DefGroove JazzGuitarEnd Soft, 2 bar ending. + + +Groove JazzGuitar +SeqSize 1 + +Begin Chord + Sequence {1 8 90; 1.5 8 84; 2 8 80; 2.5 8 70; 3 2 66} +End + +Begin Bass + Sequence {1 2. 1 90} +End + +DefGroove JazzGuitarEnd1 Soft, 1 bar ending. diff --git a/mma/lib/stdlib/lighttango.mma b/mma/lib/stdlib/lighttango.mma index 56568b0..1290d6c 100644 --- a/mma/lib/stdlib/lighttango.mma +++ b/mma/lib/stdlib/lighttango.mma @@ -149,6 +149,25 @@ DefGroove LightTango1 Change out the accordion for a piano. Chord-Sus Groove LightTangoSus DefGroove LightTango1Sus Add a sustained tone to the piano variant. +//////////////////////// +//// Fill + +Groove LightTango +Seqsize 1 + +// Drum-Kick +Drum-Snare Sequence D1234 +// Drum-PHH +Drum-Tam Sequence - +Drum-Clave Sequence D1234 +Chord-Accordion Sequence L2 +Chord-Guitar Sequence C8 +Bass-Piano Sequence B13 +Bass Sequence B13 + +DefGroove LightTangoFill A one bar fill pattern. + + ///////////////////// /// Introduction diff --git a/mma/lib/stdlib/lullaby.mma b/mma/lib/stdlib/lullaby.mma new file mode 100644 index 0000000..61adb78 --- /dev/null +++ b/mma/lib/stdlib/lullaby.mma @@ -0,0 +1,130 @@ + +// lullaby + +Doc Gentle, soft lullaby in 4. Written for "Good Night". + +Author Bob van der Poel + +Begin DocVar + ChordVoice Voice used in Chord tracks (defaults to JazzGuitar). + ChordOctave Octave for Chord track (default 4) +End + +NewSet ChordVoice JazzGuitar +NewSet ChordOctave 4 + + +SeqClear +Time 4 +Timesig 4 4 +Include stdpats + +///////// Additional Patterns + + +////////// Ballad + +SeqSize 1 + +Begin Chord + Voice $ChordVoice + Volume m + Octave $ChordOctave + Voicing Mode=Optimal + Articulate 110 + Rtime 3 + Rvolume 3 + Sequence {1 4 90 0; 2 4 0 90 0; 3 4 0 0 90 0; 4 4 0 90 0} + Accent 1 20 3 10 +End + +DefGroove Lullaby Just a solo guitar in 4. + + +Begin Bass + Voice JazzGuitar + Volume mp + Octave 2 + Rtime 2 + Rvolume 3 + Articulate 90 + Sequence B13 +End + +DefGroove Lullaby1 Adds in a bit of bass. + +Groove Lullaby + +Begin Walk + Voice JazzGuitar + Volume mp + Octave 3 + Rtime 2 + Rvolume 3 + Articulate 110 + Direction Up + Sequence W8 + Rskip 40 +End + +DefGroove LullabyWalk Adds an 8th note walking bass line. + + +/////////////////// +//// Sustained + +Groove Lullaby + +Begin Chord-Sus + Voice SlowStrings + Octave 5 + Volume p + Voicing Mode=Optimal + Articulate 100 + Unify On + Sequence {1 1 90 0 90 0 * 2} +End + +DefGroove LullabySus Add some sustained strings to our guitar. + +Groove LullabySus +Bass Groove Lullaby1 +DefGroove Lullaby1Sus A bit of bass with the strings. + +Groove LullabySus +Walk Groove LullabyWalk +DefGroove LullabyWalkSus Strings and walking bass. + + +/////////////////// +//// Intro + +Groove Lullaby1Sus + +SeqSize 4 + +Begin Chord + Volume -30 + Sequence * * * {1 1 90 0} +End + +Begin Bass + Volume +20 + Sequence * * * B1 +End + +Begin Chord-Sus + Volume +40 +End + +DefGroove LullabyIntro + + +/////////////////// +//// Ending + +Groove Lullaby + +Chord Sequence {1 1 90 0 * 2} + +DefGroove LullabyEnd Two half notes on the guitar. diff --git a/mma/lib/stdlib/modernjazz.mma b/mma/lib/stdlib/modernjazz.mma index 1cb2887..5b04106 100644 --- a/mma/lib/stdlib/modernjazz.mma +++ b/mma/lib/stdlib/modernjazz.mma @@ -8,6 +8,13 @@ End Author Bob van der Poel +NewSet ArpeggioVoice MutedTrumpet + +Begin DocVar + ApreggioVoice Voice for the alternating apreggios in ModernJazz1 \ + (Default=MutedTrumpet). Also used in Introduction and Ending. +End + SeqClear Time 4 Timesig 4 4 @@ -107,7 +114,7 @@ End DefGroove ModernJazz ModernJazz with just a piano and guitar. Begin Arpeggio - Voice MutedTrumpet + Voice $ArpeggioVoice Octave 5 Range 1 Volume mf @@ -119,7 +126,7 @@ Begin Arpeggio End Begin Bass-Trp - Voice MutedTrumpet + Voice $ArpeggioVoice Octave 5 Volume mf Rvolume 5 @@ -181,7 +188,7 @@ Chord-Guitar Sequence C1 Sync23 C1 L1 Chord-Piano Sequence C24 Sync34 C2 C1 Begin Chord-Trp - Voice MutedTrumpet + Voice $ArpeggioVoice Octave 5 Volume mf Rvolume 5 @@ -200,7 +207,7 @@ SeqSize 2 Arpeggio Sequence - Begin Bass-Trp - Voice MutedTrumpet + Voice $ArpeggioVoice Octave 5 Volume mf Articulate 70 diff --git a/mma/lib/stdlib/popballad.mma b/mma/lib/stdlib/popballad.mma index 98ad7ff..59be468 100644 --- a/mma/lib/stdlib/popballad.mma +++ b/mma/lib/stdlib/popballad.mma @@ -120,7 +120,9 @@ DefGroove PopBallad Plain old Pop Ballad. Groove PopBallad -Drum-HH Sequence - +Begin Drum-HH + Sequence - +End Begin Drum-Ride Tone RideCymbal1 @@ -184,6 +186,80 @@ Drum-Kick Sequence D1234 // Kill kickdrum offbeats Defgroove PopBallad2 A straighter version of the ballad. +///////////// +/// Sustained version + +Groove PopBallad + +Begin Drum-HH + Volume mp + sequence D13 +End + +Begin Drum-Cym + Sequence D1 z z z + Volume p +End + +Begin Drum-Kick + Volume mp +End + +Begin Drum-Snare + Sequence D24 + Volume mp +End + +Begin Drum-Cabasa + Volume m +End + +Begin Drum-Shake + Volume m +End + +// Bass -- no change + +Begin Chord + Octave 5 +End + +// Arpeggio - no change + + +Begin Chord-Sus + Voice TremoloStrings + Sequence { 1 1 90 70 80 0 * 4 } + Voicing Mode=Optimal + Octave 5 + Articulate 100 + Unify On + Rvolume 10 + Volume p +End + +DefGroove PopBalladSus A slightly lighter version, with strings. + +///////////////////// +///////////// Intro + +Groove PopBallad + +Drum-HH Sequence * * * D123 +Drum-Cym Sequence D1 / / z +Drum-Kick Sequence * * * D1 +Drum-Snare Sequence * * * D123 +Drum-Cabasa Sequence * * * z +Drum-Shake Sequence * * * z + +Bass Sequence * * * B1 + +Chord Sequence * * * L1 + +Arpeggio Sequence * * A4 A1 + +DefGroove PopBalladIntro A simple introduction. + /////// Ending diff --git a/mma/lib/stdlib/rockballad.mma b/mma/lib/stdlib/rockballad.mma index 4d83b88..60a7c76 100644 --- a/mma/lib/stdlib/rockballad.mma +++ b/mma/lib/stdlib/rockballad.mma @@ -9,6 +9,14 @@ End Author Bob van der Poel +NewSet SusVoice ChoirAahs +NewSet SusVoiceOctave 4 + +Begin DocVar + SusVoice Voice used for sustained voicing in RockBalladVoice (default=ChoirAahs). + SusVoiceOctave Octave for sustained voices (default=4). +End + SeqClear Time 4 Timesig 4 4 @@ -72,6 +80,13 @@ End DefGroove RockBallad Basic beat with triplet Hi-Hats. +Groove RockBallad + +Chord Sequence C1234 + +DefGroove RockBallad1 Same as the basic pattern, but skips the chord triplet on bar 4. + + ////////////////////////// // Guitar Fill @@ -88,26 +103,33 @@ Begin Arpeggio Articulate 105 End - DefGroove RockBalladFill Add guitar arpeggios. +Groove RockBallad1 +Arpeggio Groove RockBalladFill +DefGroove RockBallad1Fill Guitar apreggio fills without 4th bar triplets. + ///////////////////////////// // Adds some (sustained) voices Groove RockBallad Begin Chord-Sus - Voice ChoirAahs + Voice $SusVoice Sequence { 1 1 90 0 80 0 * 2} // Root and fifth notes only. Voicing mode=optimal Volume p - Octave 4 + Octave $SusVoiceOctave Articulate 100 Unify On End DefGroove RockBalladVoice Adds some cheese with choir voices. +Groove RockBallad1 +Chord-Sus Groove RockBalladVoice +DefGroove RockBallad1Voice + ///////////////////////////// //// Intro @@ -152,3 +174,13 @@ DefGroove RockBalladEnd Ending with a scaling tenor sax. Use Seq 1 \ to 4 for 16ths, 8th, 4th or 1/2 note runs. +Groove RockBallad + +Seqsize 2 + +Chord Sequence C1234 L2 +Bass Sequence B13 B1 +Walk Sequence - + +DefGroove RockBalladEnd1 Simple 2 bar ending. + diff --git a/mma/lib/stdlib/shuffleboggie.mma b/mma/lib/stdlib/shuffleboggie.mma new file mode 100644 index 0000000..ed44c30 --- /dev/null +++ b/mma/lib/stdlib/shuffleboggie.mma @@ -0,0 +1,204 @@ + +// shuffleboggie.mma + +Begin Doc + + A blues-like shuffle beat. Written for Kansas City. + +End + +Author Bob van der Poel + +SeqClear +Time 4 +Timesig 4 4 +Include stdpats + +//////// Additional patterns + + +///////////// + +SeqSize 2 +Begin Drum-Kick + Tone KickDrum1 + Volume mp + Sequence D1234 +End + +Begin Drum-Clap + Tone HandClap + Volume p + Sequence D24 +End + +Begin Drum-Snare + Tone SnareDrum2 + Volume mp + Sequence D24 +End + +Begin Drum-CHH + Tone ClosedHiHat + Volume p + Sequence {D1234; D24 Shift .666} +End + +Begin Drum-OHH + Tone OpenHiHat + Volume mp + Sequence {D1 Shift .666} + RSkip 50 +End + +Begin Chord-Sax + Voice TenorSax + Octave 4 + Voicing Mode=Optimal + Volume p + Articulate 80 + Sequence {1 8. 100 0; 1.66 16 80; 3 8 90 } +End + +Begin Chord-Piano + Voice Piano2 + Octave 5 + Volume mp + Sequence { C1234 Shift .666} + Articulate 60 +End + +Begin Bass-Piano + Voice $_Chord-Piano_Voice + Octave 4 + Volume $_Chord-Piano_Volume + Articulate $_Chord-Piano_Articulate + Sequence {1 1 1 90 * 4} +End + +Begin Chord-Guitar + Voice MutedGuitar + Volume m + Articulate 100 + Octave 5 + Sequence {1 4 90; 2 16 90; 2.666 8 100 0; 3 4 90; 4 16 90; 4.666 8 100 0} +End + +Begin Bass + Voice SlapBass1 + Volume f + Articulate 80 + Octave 3 + Sequence {1 4 1 90; 2 4 3 90; 3 8. 5 90; 4 8. 3 90} +End + + +DefGroove ShuffleBoggie Blues with a shuffle style. + +Groove ShuffleBoggie + +Alltracks Chord Bass Volume -20 + +Begin Arpeggio + Voice CleanGuitar + Octave 5 + Range 1 + Articulate 70 + Harmony Open + Sequence A4 {1 4 90; 2 16 90; 2.666 8 90; 3 4 90; 4 4 16; 4.666 8 90} + SeqRnd On + Rskip 10 + Rtime 20 + Rvolume 20 +End + +DefGroove ShuffleBoggie1 Adds an articulated guitar riff to the basic beat. + + + +///////////////// +/// Sustained + +Groove ShuffleBoggie + +Alltracks Chord Bass Volume -30 + +Begin Chord-Sus + Voice Strings + Sequence { 1 1 90 0 50 0 * 4 } { 1 1 50 0 90 0 * 4 } + SeqRnd On + Voicing Mode=Optimal + Rvolume 10 + Articulate 100 + Unify On + Volume m + Octave 5 +End + +DefGroove ShuffleBoggieSus Blues with violins. Sort of odd, but we can call them fiddles! + + +///////////// +/// Introduction + +Groove ShuffleBoggie + +Drum-Kick Sequence * D1 +Drum-Clap Sequence * D1 +Drum-Snare Sequence * D1 +Drum-CHH Sequence * D16 +Drum-OHH Sequence - + +Chord-Sax Sequence * {1 2 90} + +Chord-Piano Sequence * C1 +Bass-Piano Sequence - +Chord-Guitar Sequence * C1 + +Bass Sequence * {1 1 1 90} + + +DefGroove ShuffleBoggieIntro A two bar intro. Short, loud and sweet. + +Groove ShuffleBoggie +SeqSize 4 + +Drum-Kick Sequence * * * D1 +Drum-Clap Sequence * * * D1 +Drum-Snare Sequence * * * D1 +Drum-CHH Sequence * * * D16 +Drum-OHH Sequence - + +Chord-Sax Sequence * * * {1 2 90} + +Chord-Piano Sequence * * * C1 +Bass-Piano Sequence - +Chord-Guitar Sequence * * * C1 + +Bass Sequence * * * {1 1 1 90} + + +DefGroove ShuffleBoggieIntro4 A four bar intro. + +///////////// +/// Ending + +Groove ShuffleBoggie + + +Drum-Kick Sequence * D123 +Drum-Clap Sequence * D123 +Drum-Snare Sequence * D13 +Drum-CHH Sequence * z +Drum-OHH Sequence - + +Chord-Sax Sequence * C13 + +Chord-Piano Sequence * C123 +Bass-Piano Sequence - +Chord-Guitar Sequence * C123 + +Bass Sequence * B13 + + +DefGroove ShuffleBoggieEnd Very simple ending, hits on 1, 2 and 3 of last bar. \ No newline at end of file diff --git a/mma/lib/stdlib/slowcountry.mma b/mma/lib/stdlib/slowcountry.mma index 6c63cba..16f2b27 100644 --- a/mma/lib/stdlib/slowcountry.mma +++ b/mma/lib/stdlib/slowcountry.mma @@ -16,10 +16,7 @@ Time 4 // All these patterns are 4/4 Timesig 4 4 Include stdpats -Begin Chord - Define C13'4 1 2 90; 3 4 90 0; 3.5 8. 0 0 90 0; 4 4 90 -End /////////////////////////// /// SlowCountry @@ -40,10 +37,10 @@ Begin Chord Voice JazzGuitar Define CL4 1 2 80 60 ; 4 4 80 60 Sequence CL4 L2 CL4 L2 + Articulate 90 80 90 80 Volume mf Voicing Mode=Optimal - Articulate 95 - Strum 15 + Strum 10 15 10 15 Accent 1 10 3 5 RVolume 10 Octave 4 @@ -56,7 +53,7 @@ Begin Bass-Fill Define F1 3 4. 1 90; 3.5 4 5 90 Define F2 4.5 8 1 90 Sequence F1 F2 F1 z - Volume mp + Volume p End // Toggle between bass and walk for the bass line. diff --git a/mma/lib/stdlib/softshoe.mma b/mma/lib/stdlib/softshoe.mma index 27e523b..4ca8017 100644 --- a/mma/lib/stdlib/softshoe.mma +++ b/mma/lib/stdlib/softshoe.mma @@ -10,6 +10,14 @@ End Author Bob van der Poel +Begin DocVar + ChordVoice Voice used in Chord tracks (defaults to Piano2). +End + +If NDef ChordVoice + Set ChordVoice Piano2 +Endif + SeqClear Time 4 // All these patterns are 4/4 Timesig 4 4 @@ -68,7 +76,7 @@ Begin Walk End Begin Chord - Voice Piano2 + Voice $ChordVoice Volume mp Articulate 110 110 80 70 Octave 5 @@ -84,10 +92,10 @@ Begin Arpeggio Voice Clarinet Sequence {A4 Shift .5; A2} A8 A4 {A2 Shift .5} SeqRnd On - Harmony Open + Harmony OpenAbove Articulate 80 Octave 5 - Range 2 + Range 1.8 Direction Up Rskip 50 Volume p diff --git a/mma/lib/yamaha/.mmaDB b/mma/lib/yamaha/.mmaDB new file mode 100644 index 0000000000000000000000000000000000000000..c41497ce0a49c36e18fd1076b82c1720331c75f9 GIT binary patch literal 253 zcmX}ky9xp^5QSmy>;3WuS+=p+AXc`MOq76TVMz)L3qi3`If$j;qq{}c?l64+WLYNe z_cJRYr4$r=u`|w;42 zc|vO$dIz#DC$vMdwflWegic7T^JP(8yP to continue (anything else will terminate): ") -echo Done. \ No newline at end of file + if a: + sys.exit(1) + + return + + +# Simple python script to install mma from tarball +# This should be fixed to be more versatile. Volunteers? + +# Before we do anything, make sure we have an up-to-date python. + +pyMaj=2 +pyMin=4 + +if sys.version_info[0] < pyMaj or sys.version_info[1] < pyMin: + print + print "You need a more current version of Python to run MMA and this install script." + print "We're looking for something equal or greater than version %s.%s" % \ + (pyMaj,pyMin) + print "Current Python version is ", sys.version + print + sys.exit(0) + + +# Banner. Check to make sure user has root permissions. + +print """ +This script will install mma, the standard library and the +python modules using symbolic links to the current directory. +""" + +try: + u=os.getuid() +except: + u=1 + +if u: + okay("""You do not appear to be running this script as 'root' user. +Continuing will probably cause all kinds of strange errors +and a generally unsatisfactory experience. But, we can try... +""") + +dir = "/usr/local/share/mma" +exe = "/usr/local/bin/mma" + +if os.path.exists(dir): + okay("""The directory %s currently exists. Proceeding will overwrite +with a new link. YOU MAY LOSE DATA.""" % dir) + +if os.path.exists(exe): + okay("""The file %s currently exists. Proceeding will remove this +file with a new link. YOU MAY LOSE DATA.""" % exe) + +okay("""Okay, I'm ready to create the links. I will create 2 links: + - The main distribution and library at %s + - The callable executable at %s +""" % (dir, exe) ) + +os.system("ln -sf `pwd` %s" % dir) +os.system("ln -sf `pwd`/mma.py %s" % exe) + +print "Everything seems to be okay. We suggest you first update the database" +print "with the command mma -G." +print "Have Fun!" \ No newline at end of file diff --git a/mma/mma.py b/mma/mma.py index a2425e4..50092bf 100755 --- a/mma/mma.py +++ b/mma/mma.py @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Bob van der Poel +Bob van der Poel """ diff --git a/mma/text/ANNOUNCE b/mma/text/ANNOUNCE index 9131c73..35403eb 100644 --- a/mma/text/ANNOUNCE +++ b/mma/text/ANNOUNCE @@ -1,20 +1,21 @@ -Version 1.0-RC2 of MMA - Musical MIDI Accompaniment - is now +Version 1.1 of MMA - Musical MIDI Accompaniment - is now available for downloading. Included in this release: - Improved support for windows path names. + Addition of ARIA tracks for auto-generated melodies, - A number of packaging issues resolved. + Fixed solo/harmony volumes, - Inclusion of mklibdoc.py for updating of lib docs from user contributed files. + Chord fixes, - Fractional RANGE settings for arpeggio and scale tracks. + New commands: NEWSET, DOCVAR, GROOVECLEAR, -This is our second version 1 release candidate. Please let me know -if anything is broken before we release the real 1.0! + -0 sync command line switch, + + Many library additions/enhancements, + + Minor bug fixes. -Please note the new web and email addresses. The old ones still work, -but not for long. Update your records. MMA is a accompaniment generator -- it creates midi tracks for a soloist to perform with. User supplied files contain diff --git a/mma/text/CHANGES-1.0 b/mma/text/CHANGES-1.0 new file mode 100644 index 0000000..96f6b71 --- /dev/null +++ b/mma/text/CHANGES-1.0 @@ -0,0 +1,55 @@ + +A new track, ARIA, has been added. This lets mma create melodies (sort of). + +Reorganized the solo extraction routine and harmony. This is now generating the + correct velocities for the harmony notes. + +Changed a number of chords and descriptions to match more standardized usage. Mostly in + 9ths and 11ths. Added some new chords and aliases. The descriptions are more detailed + as to exceptions. Please refer to the document chords.pdf for details. + +I've started to add things like: + + If Ndef ChordVoice + Set ChordVoice Piano2 + Endif + + to style files. This makes it much easier to change the feel of a style from + within a song file. See the softshoe lib file and the song L-O-V-E for a + simple example. + +To help in documenting the above, a new documentation command DOCVAR has been added. + You should have a DOCVAR for each user variable you use in a library file. + +It is sometimes useful to clear out current Groove definitions. So + the command GrooveClear has been added. + +Added NEWSET command. This is just like SET, but ONLY has an effect if the variable currently + does NOT have a value. So: + + NEWSet Foo something + + and + + If NDef Foo + Set Foo Something + Endif + + are identical. + +Added a SYNCRONIZATION command line flag. If you have a "-0" in the command line + MMA will add a very brief on/off event at the start of each midi track it + generates. You might find this helpful when lining up generated tracks in + multi-track editor. + +Added a mini-how-to text file on TIMIDITY. + +Added a split track program: util/timsplit.py. + + + + + + + + diff --git a/mma/text/CHANGES-1.0.rc1 b/mma/text/CHANGES-1.0.rc1 index 4bcb6b1..0a946fe 100644 --- a/mma/text/CHANGES-1.0.rc1 +++ b/mma/text/CHANGES-1.0.rc1 @@ -26,3 +26,5 @@ The install has changed a bit. I've renamed the old install script to cp-install The base distribution now includes the html documentation. + +October 15, 2006 -- released 1.0-RC2 diff --git a/mma/text/CHANGES-1.0.rc2 b/mma/text/CHANGES-1.0.rc2 new file mode 100644 index 0000000..efb3719 --- /dev/null +++ b/mma/text/CHANGES-1.0.rc2 @@ -0,0 +1,24 @@ + +Both ln-install and cp-install have been updated a bit. They now check + for the proper version of Python being installed and attempt to + verify that the user has root permissions. I'm not sure if the + check will always work (ie, on non-Unix systems) so it is wrapped + in try/except ... hopefully this will end one set of "can't install" + emails I get. + +In an effort to get the command line options back to reality, I have deleted + the following: -Ddm, -Dda, -Dim, -Dia, -Dcm, -Dca, -Dn. These options just + did some intermediate doc prep and should not be a part of MMA proper. + The program util/mmatabs.py creates the same data and is part of the + distribution. + +Changed mklibdoc.py to generate entries in alphabetic order. + +Fixed error reporting bug in parser. Constructs like "z*" would crash the + compiler. + +Changed TABs in source code to spaces. Please, if you decide to make + changes the proper-indent-for-python-according-to-bob is 4 spaces. + +November 13, 2006 +Released Version 1.0 --- bring out the funny hats and champagne! \ No newline at end of file diff --git a/mma/text/INSTALL b/mma/text/INSTALL index ca37f35..49d1370 100644 --- a/mma/text/INSTALL +++ b/mma/text/INSTALL @@ -20,15 +20,16 @@ MMA consists of several parts. They should be installed as follows: There are 2 install scripts you can use. -The first and recommended one is a shell script called ln-install. +The first and recommended one is a python script called ln-install. This simply creates the symbolic link /usr/local/share/mma pointing to the current directory where the uncompressed tar file you downloaded exists. I have used the link method for years now and it works fine. The only problem you have with this is that you must not delete or move the files from the tarball. -ln-install just has one line of code, a ln line. You must be root for this -to work: on a Linux system the command: +ln-install has only 2 important lines of code: both create a single +symbolic link. You must be root for this to work: on a Linux system +the command: su -c './ln-install' @@ -82,7 +83,7 @@ installing. Just issue the command './mma someMMAfile'. If you run the install script the existing /usr/local/bin/mma will be overwritten and your existing /usr/local/share/mma directory will be -renamed to /usr/local/share/mma-old. You will received prompts for +renamed to /usr/local/share/mma-old. You will receive prompts for this before action is taken. However, if you already have a backup directory you will need to delete this by hand. This just a bit of safety so I don't get blamed to deleting stuff off your (or my) hard diff --git a/mma/text/README b/mma/text/README index 0b0c3ce..4c6cad5 100644 --- a/mma/text/README +++ b/mma/text/README @@ -15,7 +15,7 @@ shortcomings. However, don't let the term BETA dissuade you from trying the program! It does produce very useful backing tracks! -Comments, etc. appreciated: bvdp@xplornet.com +Comments, etc. appreciated: bob@mellowood.ca Bob van der Poel, Feb/2002 diff --git a/mma/text/TIMIDITY b/mma/text/TIMIDITY new file mode 100644 index 0000000..6a73368 --- /dev/null +++ b/mma/text/TIMIDITY @@ -0,0 +1,98 @@ + +Using MMA files with the Timidity MIDI player. + +The program timidity is pretty neat. It lets people who don't have a +real, external sequencer (or a sequencer built in to a sound card) play +MIDI files though the computer sound system. Most distributions already +have this program installed. This file attempts to show a few tricks +I've learned. It is not a timidity how to or primer. + +Begin by making sure that you have timidity installed. Typing something like + + timidity + +from the command line should bring up a copyright message like: + + TiMidity++ version 2.13.2 -- MIDI to WAVE converter and player + Copyright (C) 1999-2004 Masanao Izumo + Copyright (C) 1995 Tuukka Toivonen + .............. + + +If you get a message with "command not found" ... then you'll have +to find and install timidity first. Check the docs and repositories +for your distribution. + +Now, try it with a real file: + + timidity somefile.mid + +should play the MIDI file specified though your computer sound system. +If it doesn't, stop and figure it out. Read the manual, etc. + +Timidity works by using something called a soundfont. Using this it +converts each MIDI sound instruction into an audio signal. Don't worry +about how it does that ... but, remember that quality of the generated +sound relies on the quality for the soundfont. The default distributions +I've seen have some pretty crappy sounds. + +So, upgrade the sounds by installing a better font. I've installed something +called Airfont 340.sf2 and it sounds good. I'll not give a link here (since +they do move around), but if you Google for "airfont + 340 + sf2" you should +find it. The file is about 80 MEG, so be patient. + +To get timidity to use an sf2 file you have to do 2 things: + + 1. Put the file somewhere that timidity can find it. In most cases + moving the file to /usr/share/timidity should do the trick. + + 2. Update the timidity config file. In my case I had to change 2 files: + + i. In /usr/share/timidity create the file timidity.cfg. It + has a single line: + + soundfont "Airfont 380.sf2" order=0 + + the quotes are there since the file name has a space in it. + + ii. In /etc/timidity create the link: + + cd /etc/timidity; ln -s /usr/share/timidity/timidity.cfg + +Of course, you'll have to do the above as root. + + +You can use timidity to create a wav file directly from a MMA midi. This +file can be used in a program like audacity. Simple: + + timidity -Ow -ooutfile.wav somefile.mid + +It is fun to split the MIDI tracks into separate audio tracks. That +way you can change, for example, the volume for the bass part only +in a program like audacity. Again, timidity is your friend. + +For this to work, you need to have a dummy sequence point in each +MMA MIDI track. When you generate the file, use the -0 option: + + mma -0 somefile.mma + +will generate somefile.mid with a "tick" at the start of all the tracks. +Now, check to see what tracks were created: + + mma -c somefile.mma + +Assuming that you have MIDI data on tracks 10, 15 and 16: + + for a in 10 15 16;do timidity -Ow -Q0 -Q-$a -o$a.wav;done + +A little program, timsplit.py, which does all the above for you +has been included in the the MMA distribution in the util directory. +Read the file README.timsplit for details. + +Have fun, + +Bvdp, March/2007 + + + + diff --git a/mma/text/TODO b/mma/text/TODO index 242d3cc..142827e 100644 --- a/mma/text/TODO +++ b/mma/text/TODO @@ -3,6 +3,3 @@ In anticipation of a real-soon-now 1.0 release more eg files need to be written to test more features. Fix -Dk to show option keywords. - -Move all text file to 'text' for distribution. Ensure no duplicate filenames since MAC is -case-INsensitive. \ No newline at end of file diff --git a/mma/util/README.mmatabs b/mma/util/README.mmatabs new file mode 100644 index 0000000..8cc21af --- /dev/null +++ b/mma/util/README.mmatabs @@ -0,0 +1,11 @@ + +Short usage file for mmatabs.py. + +This program is used to create the tables used in the MMA reference manual. +The program includes constant tables from the main MMA modules and creates +a series of latex files. Each file has a '.AUTO' extension. + +Really only useful in maintaining the docs ... but you're welcome to it. + +bvdp, October 2006. + diff --git a/mma/util/README.timsplit b/mma/util/README.timsplit new file mode 100644 index 0000000..97fcbf6 --- /dev/null +++ b/mma/util/README.timsplit @@ -0,0 +1,16 @@ + +Short usage file for timsplit.py. + +This program is used to create a set of wav tracks from a MMA +input file. You need MMA, the input file and timidity. The command: + + timsplit.py somefile.mma + +will create a MIDI file (the name is hardcoded to outfile.mid) and +then create a wav file for each track using timidity. + +Conversion takes a few minutes, depending on the soundfont you're using +and the size of the MIDI file. Be patient. + +bvdp, March 2007. + diff --git a/mma/util/mklibdoc.py b/mma/util/mklibdoc.py index 3c79e11..a952472 100755 --- a/mma/util/mklibdoc.py +++ b/mma/util/mklibdoc.py @@ -10,21 +10,21 @@ libpath = '' docpath = '' for p in installdir: - a = os.path.join(p, 'lib', '') - if os.path.isdir(a): - libpath=a - docpath = os.path.join(p, 'docs', 'html', 'lib') - break + a = os.path.join(p, 'lib', '') + if os.path.isdir(a): + libpath=a + docpath = os.path.join(p, 'docs', 'html', 'lib') + break if not libpath: - print "Can't find the MMA library!" - print "Please check your installation and/or change the search path in this program." - sys.exit(1) + print "Can't find the MMA library!" + print "Please check your installation and/or change the search path in this program." + sys.exit(1) try: - os.mkdir(docpath) + os.mkdir(docpath) except: - pass + pass index = [] links = [] @@ -32,81 +32,81 @@ links = [] print "Processing library files" def dodir(dir): - """ Process files in directory. """ + """ Process files in directory. """ - global index, links - newdirs = [] + global index, links + newdirs = [] - olib = os.path.join(docpath, dir) - if not os.path.isdir(olib): - try: - os.mkdir(olib) - except: - print "Can't create directory", olib - sys.exit(1) + olib = os.path.join(docpath, dir) + if not os.path.isdir(olib): + try: + os.mkdir(olib) + except: + print "Can't create directory", olib + sys.exit(1) - links.append("
  • %s

  • " % (dir, dir.title())) + links.append("
  • %s

  • " % (dir, dir.title())) - if dir.lower() == "stdlib": - index.append("

    These grooves can be used from a program just by using their name.

    ") + if dir.lower() == "stdlib": + index.append("

    These grooves can be used from a program just by using their name.

    ") - index.append("" % dir) - index.append("

    %s

    " % dir.title() ) + index.append("" % dir) + index.append("

    %s

    " % dir.title() ) - index.append("
      ") + index.append("
        ") - for f in os.listdir(libpath + dir): - this = os.path.join(libpath, dir, f) + for f in sorted(os.listdir(libpath + dir)): + this = os.path.join(libpath, dir, f) - if os.path.isdir(this): - newdirs.append(os.path.join(dir, f)) - continue + if os.path.isdir(this): + newdirs.append(os.path.join(dir, f)) + continue - if this.endswith('.mma'): - htmlfname = os.path.join(dir, f.replace('.mma' , '.html')) - htmldate = 0 - htmlout = os.path.join(docpath, htmlfname) - try: - htmldate = os.path.getmtime(htmlout) - except: - pass + if this.endswith('.mma'): + htmlfname = os.path.join(dir, f.replace('.mma' , '.html')) + htmldate = 0 + htmlout = os.path.join(docpath, htmlfname) + try: + htmldate = os.path.getmtime(htmlout) + except: + pass - libdate = 0 - try: - libdate = os.path.getmtime(this) - except: - print "NO, NO, NO --- let Bob know about this!" - pass # shouldn't ever happen! + libdate = 0 + try: + libdate = os.path.getmtime(this) + except: + print "NO, NO, NO --- let Bob know about this!" + pass # shouldn't ever happen! - if libdate < htmldate: - print "Skipping:", this + if libdate < htmldate: + print "Skipping:", this - else: - if htmldate == 0: - print "Creating:", htmlfname - else: - print "Updating:", htmlfname + else: + if htmldate == 0: + print "Creating:", htmlfname + else: + print "Updating:", htmlfname - err = os.system("mma -Dxh -w -n %s > %s" % (this, htmlout) ) - if err: - print "ERROR Creating %s" % htmlout - print " %s" % err - try: - os.remove(htmlout) - except: - pass - continue + err = os.system("mma -Dxh -w -n %s > %s" % (this, htmlout) ) + if err: + print "ERROR Creating %s" % htmlout + print " %s" % err + try: + os.remove(htmlout) + except: + pass + continue - index.append("
      • %s
      • " % (htmlfname, os.path.join(dir, f))) + index.append("
      • %s
      • " % (htmlfname, os.path.join(dir, f))) - index.append("
      ") + index.append("
    ") - if dir.lower() == "stdlib": - index.append('

    Use the following grooves with a "use" directive.

    ') + if dir.lower() == "stdlib": + index.append('

    Use the following grooves with a "use" directive.

    ') - for d in newdirs: - dodir(d) + for d in newdirs: + dodir(d) ############################## @@ -115,17 +115,17 @@ a = os.listdir(libpath) dirs = [] for b in a: - if os.path.isdir(libpath + b): - dirs.append(b) + if os.path.isdir(libpath + b): + dirs.append(b) dirs.sort() if dirs.count("stdlib"): - dirs.remove("stdlib") - dirs.insert(0, "stdlib") + dirs.remove("stdlib") + dirs.insert(0, "stdlib") for dir in dirs: - dodir(dir) + dodir(dir) out = file(os.path.join(docpath, 'index.html'), "w") @@ -179,15 +179,17 @@ information from the each library file:
  • The file description from the "Doc Note" directive. +
  • Any user variables documented in "DocVar" directives. +
  • Each groove description: This is the optional text following a DefGroove directive. -
      -
    • The sequence size. This is extracted from the current groove +
        +
      • The sequence size. This is extracted from the current groove information and was set with the SeqSize directive. It is displayed in a small box after the groove description. -
      • A "summary" of the voices used in the groove. Note that a +
      • A "summary" of the voices used in the groove. Note that a different voice or MIDI note is possible for each bar in the sequence size; however, this listing only lists the selection for the first bar. @@ -196,8 +198,8 @@ information from the each library file:

      If you find that you don't have some of the grooves listed below in your distribution - you need to run the program mklibdoc.py to update these docs. Not all style files are - distributed in the default MMA distribution. + you need to run the program mklibdoc.py to update these docs. Not all style files are + distributed in the default MMA distribution.


      Index

      @@ -205,10 +207,10 @@ information from the each library file: """) if links: - out.write("
        ") - out.write("\n".join(links)) - out.write("
      ") - out.write("
      ") + out.write("
        ") + out.write("\n".join(links)) + out.write("
      ") + out.write("
      ") out.write( "\n".join(index)) out.write(""" diff --git a/mma/util/mma-renum.py b/mma/util/mma-renum.py new file mode 100755 index 0000000..fbdb18b --- /dev/null +++ b/mma/util/mma-renum.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +# Renumber a mma song file. Just take any lines +# which start with a number and do those sequenially. + +import sys, os + + +def usage(): + print "Mma-renum, (c) Bob van der Poel" + print "Re-numbers a mma song file and" + print " cleans up chord tabbing." + print "Overwrites existing file!" + print + sys.exit(1) + +if len(sys.argv[1:]) != 1: + print "mma-rnum: requires 1 filename argument." + usage() + +filename = sys.argv[1] +tempfile = filename + ".temp" + +if filename[0] == '-': + usage() + +if not os.path.exists(filename): + error("Can't access the file '%s'" % filename) + +try: + inpath = open(filename, 'r') +except: + usage() + +try: + outpath = open( tempfile, 'w') +except: + error("Can't open scratchfile '%s', error '%s'" % (tempfile, sys.exc_info()[0]) ) + +linenum = 1 + +for l in inpath: + l=l.rstrip() + s = l.split() + if s: + try: # only modify lines starting with a number + x=int(s[0]) + l='%-5s' % linenum + linenum += 1 + for a in s[1:]: + l += "%-4s " % a + except: + pass + outpath.write(l + "\n") + +inpath.close() +outpath.close() + +try: + os.remove(filename) +except: + error("Cannot delete '%s', new file '%s' remains", (filename, tempfile) ) + +try: + os.rename(tempfile, filename) +except: + error("Cannot rename '%s' to '%s'." (tempfile, filename) ) + + + + + diff --git a/mma/util/mmatabs.py b/mma/util/mmatabs.py new file mode 100755 index 0000000..ef85698 --- /dev/null +++ b/mma/util/mmatabs.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +# create tex files of the mma midi constants + +import sys, os, commands + +sys.path.insert(0, "/usr/local/share/mma/MMA/") +from miditables import * +from chordtable import chords + +err, version = commands.getstatusoutput( "mma -v") +if err: + print "Can't get MMA version ... strange error!" + sys.ex + +def dodrums(order): + """ Print LaTex table of drum names. """ + + notenames = ['E\\flat', 'E', 'F', 'G\\flat', 'G', 'A\\flat', + 'A', 'B\\flat', 'B', 'C', 'D\\flat', 'D'] * 5 + + n=zip( drumNames, range(27,len(drumNames)+27), notenames ) + + if order == "a": + for a,v,m in sorted(n): + outfile.write ("\\insline{%s} {%s$^{%s}$}\n" % (a, v, m )) + + else: + for a,v,m in n: + outfile.write ("\\insline{%s} {%s$^{%s}$}\n" % (v, a, m)) + +def docrtls(order): + """ Print LaTex table of MIDI controller names. """ + + n=zip( ctrlNames, range(len(ctrlNames)) ) + + if order == "a": + for a,v in sorted(n): + outfile.write ("\\insline{%s} {%02x}\n" % (a, v)) + + else: + for a,v in n: + outfile.write("\\insline{%02x} {%s}\n" % (v, a)) + +def doinsts(order): + """ Print LaTex table of instrument names. """ + + n=zip( voiceNames, range(len(voiceNames)) ) + if order == "a": + for a,v in sorted(n): + a=a.replace('&', '\&') + outfile.write("\\insline{%s} {%s}\n" % (a, v)) + + else: + for a,v in n: + a=a.replace('&', '\&') + outfile.write( "\\insline{%s} {%s}\n" % (v, a)) + +def dochords(): + """ Print out a list of chord names and docs in LaTex. """ + + for n in sorted(chords.keys()): + nm=n.replace("#", '$\\sharp$') + nm=nm.replace('b', '$\\flat$') + outfile.write( "\\insline{%s}{%s}\n" % (nm, chords[n][2]) ) + + +for a,f,o in ( + ('m', docrtls, 'ctrlmidi.AUTO'), + ('a', docrtls, 'ctrlalpha.AUTO'), + ('m', dodrums, 'drumsmidi.AUTO'), + ('a', dodrums, 'drumsalpha.AUTO'), + ('m', doinsts, 'instmidi.AUTO'), + ('a', doinsts, 'instalpha.AUTO') ): + outfile = file(o, 'w') + f(a) + outfile.close() + +outfile = file("chordnames.AUTO", 'w') +dochords() +outfile.close() + diff --git a/mma/util/mup2mma.py b/mma/util/mup2mma.py new file mode 100755 index 0000000..f98c86b --- /dev/null +++ b/mma/util/mup2mma.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python + +""" mup2mma extracts chords from a MUP music notation file and + creates a MMA file. For this to work the MUP file must use + the macro "C" for chord. In my MUP files I have the following: + + define C bold (11) chord above all: @ + + This script just checks all input lines and assumes that anything + starting with "C" is a chord line. + + Additional "features": + + Lines in the form "// TEMPO: xx" generate a Tempo entry + "time =" lines are parsed for common time signatures + repeats are inserted as comment lines + + 0.3 - added options: + -m add melody lines + -l add lyrics + -o overwrite + + 0.4 - reformatted output + + 0.5 - corrected melody/lyric notation. + + bvdp, Dec/2004 + +""" + +import os +import sys +import commands +import getopt + +# Useful functions + +def error(m=''): + print "Error: %s" % m + sys.exit(1) + +def usage(): + print "mup2mma - (c) Bob van der Poel" + print "Extract MMA data from MUP file." + print "Options:" + print " -o overwrite existing MMA file" + print " -m extract melody data" + print " -l extract lyric data" + print " -v print version" + sys.exit(0) + +# Global variables + +Version = '0.5' + +overwrite = 0 # set if overwrite of old mma file okay +doLyric = 0 # set if we want lyrics output +doMelody = 0 # set if we want melody output + + +# Parse command line, open files + + +try: + opts, args = getopt.gnu_getopt(sys.argv[1:], "omlv") +except getopt.GetoptError: + usage() + +for o,a in opts: + if o == '-o': + overwrite = 1 + elif o == '-l': + doLyric = 1 + elif o == '-m': + doMelody = 1 + elif o == '-v': + print Version + sys.exit(0) + else: + usage() + +if len(args) != 1: + error("Exactly 1 filename is required.") + +infile = args[0] + +outfile = os.path.basename(infile) +if outfile.endswith('.mup'): + outfile=outfile[:-4] +title=outfile.replace("-", ' ').title() +outfile += ".mma" + +try: + bars = file(infile) +except: + error("Can't open input file '%s'." % infile) + +if os.path.exists(outfile) and not overwrite: + error("File '%s' already exists." % outfile) + +try: + out=file(outfile, "w") +except: + error("Can't open output file '%s'." % outfile) + +# Input and output files open, start processing + +out.write( "// %s\n\n" % title) + +bnum = 1 + +donebar = 0 +melody = '' +lyric = '' +chordList=[] + +for b in bars: + b=b.strip() + if b=='': # skip empty lines + continue + + if b.startswith("// TEMPO:"): + out.write("Tempo %s\n\n" % b.split()[2]) + continue + + # Parse out time sig from MUP + + ck = b.split("=") + + if len(ck) and ck[0].strip() == 'time': + ts=ck[1].strip() + if ts in ('common', '4/4'): + beats = 4 + posStep = 1 + + elif ts in ('cut', '2/4', '2/2'): + beats = 2 + posStep = .5 + + elif ts=='3/4': + beats = 3 + posStep = 1 + + elif ts=='6/8': + beats = 6 + posStep = 1 + + elif ts=='12/8': + beats = 12 + posStep = 1 + else: + error("Uknown time sig, %s" % b) + + # Parse line number from MUP + + if b.startswith('// #') or b.startswith('//# '): + bnum = b[4:] + + # Parse out melody, lyric and chords. + # Melody must be a line starting with "M:" + # Lyric must be a line starting with "L:" + # Chord must be a line starting with "C " + + key = b.split()[0] + + + if key == 'M:' and doMelody: + melody = b.split(' ', 1)[1] + + elif key == 'L:' and doLyric: + lyric = b.split(' ', 1)[1] + + elif key == 'C': + ch = b[2:] + ch=ch.replace ('"', ' ') + ch=ch.replace('&', 'b') + ch = ch[:-1] + ch=ch.split(';') + + chordList = [] + pos = 1.0 + + for c in ch: + c = c.split() + off = c[0] + + # Strip out printing offset from chord. Since the position + # has been split off, we just strip out everything after the + # inital '['. If this doesn't work, then the MUP is wrong as well + # eg: 1.5[-5] becomes 1.5 + + if off.count('['): + off=off[:off.index('[')] + + count = float(off) + + while pos < count: + chordList.append('/') + pos += posStep + + chord=c[1] + if chord.upper()=="TACET" or chord.upper()=='N.C': + chord = 'z' + + chord = chord.replace('^', 'M') + chord = chord.replace('o', 'dim') + chord = chord.replace('\\(dim)', 'dim') + + chordList.append(chord ) + pos += posStep + + + elif key in ('bar', 'repeatend', 'endbar', 'dblbar', '(dblbar)', + 'repeatstart', 'repeatboth' ): + + out.write('%-4s' % bnum) + + if not chordList: + chordList = ['/'] + for a in chordList: + out.write((' %6s' % a).rstrip()) + chordList = [] + + if doMelody and melody: + out.write((' { %s }' % melody).rstrip()) + melody = '' + + if doLyric and lyric: + out.write((' [ %s ]' % lyric).rstrip()) + lyric = '' + + out.write('\n') + + + if key == 'repeatend': + out.write( "\n// RepeatEnd\n\n") + if key == 'repeatboth': + out.write( "\n// RepeatEnd\n\n") + out.write( "// Repeat\n\n") + if key == "repeatstart" or key=='(dblbar)': + out.write( "\n// Repeat\n\n") + + rpt = b.split()[1:] + + if len(rpt) and rpt[0] == "ending": + out.write( '\n// RepeatEnding\n\n') + + else: + pass # Just ignore other MUP stuff + +out.write('\n') +out.close() + + + + diff --git a/mma/util/timsplit.py b/mma/util/timsplit.py new file mode 100755 index 0000000..d4ba992 --- /dev/null +++ b/mma/util/timsplit.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +# Create a set of wav files from MMA using timidity. + +import sys, os, commands + + +def usage(): + print "timsplit, (c) Bob van der Poel" + print "Create multi-track wav files using" + print " MMA files and timidity." + print + sys.exit(0) + +if len(sys.argv[1:]) != 1: + print "timsplit: requires 1 filename argument." + usage() + +filename = sys.argv[1] + +status, txt = commands.getstatusoutput("mma -c %s" % filename) + +if status: + print "timsplit error", status + print txt + sys.exit(1) + +# Get the track list + +ch=[] +for a in txt.split('\n'): + a=a.strip().split() + try: + ch.append(int(a[0])) + except: + pass + +ch.sort() +print "Found channels:", +for a in ch: + print a, +print + +# Create midi file + +status = os.system("mma -0 %s -foutfile.mid" % filename) + +if status: + sys.exit(1) + +# Create wav tracks with timidity + +for a in ch: + os.system("timidity -Ow -Q0 -Q-%s -o%s.wav outfile.mid" % (a,a) ) +