Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/City
diff options
context:
space:
mode:
Diffstat (limited to 'City')
-rwxr-xr-xCity/City.py110
-rwxr-xr-xCity/CsHelpers.py194
-rwxr-xr-xCity/CsSched.py143
-rwxr-xr-xCity/Images/Bass.pngbin0 -> 2349 bytes
-rwxr-xr-xCity/Images/Chords.pngbin0 -> 1935 bytes
-rwxr-xr-xCity/Images/Drums.pngbin0 -> 3094 bytes
-rwxr-xr-xCity/Images/Lead.pngbin0 -> 2233 bytes
-rwxr-xr-xCity/Images/Mic.pngbin0 -> 2290 bytes
-rwxr-xr-xCity/Images/Video.pngbin0 -> 2793 bytes
-rwxr-xr-xCity/Images/camera-busy.svg15
-rwxr-xr-xCity/Images/camera-external.svg15
-rw-r--r--City/Images/jam2jamXO_2.pngbin0 -> 37883 bytes
-rwxr-xr-xCity/Images/media-playback-pause.svg9
-rwxr-xr-xCity/Images/media-playback-start.svg15
-rwxr-xr-xCity/OrcBuilder.py342
-rwxr-xr-xCity/Parameters.py128
-rw-r--r--City/Scenes/Blues/AudioFiles/BassAudio/BassC2[41-48-50].aifbin0 -> 101158 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/BassAudio/BassC3[59-60-62].aifbin0 -> 103186 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/BassAudio/BassC4[70-72-78].aifbin0 -> 100678 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/BassAudio/BassF#2[51-54-58].aifbin0 -> 100048 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC4[70-72-73].aifbin0 -> 72482 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC5[82-84-90].aifbin0 -> 72654 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE3[63-64-65].aifbin0 -> 72798 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE4[74-76-77].aifbin0 -> 72236 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/DrumsAudio/C1_kick_drum.aifbin0 -> 12670 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/DrumsAudio/D1_snare_drum.aifbin0 -> 15168 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aifbin0 -> 6302 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/DrumsAudio/Tamborine 22 16 Mono.aifbin0 -> 21174 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/B2_guitar.aifbin0 -> 50070 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/B3_guitar.aifbin0 -> 50412 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/E2_guitar.aifbin0 -> 51016 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/E3_guitar.aifbin0 -> 50324 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/E4_guitar.aifbin0 -> 49942 bytes
-rw-r--r--City/Scenes/Blues/AudioFiles/LeadAudio/E5_guitar.aifbin0 -> 51070 bytes
-rw-r--r--City/Scenes/Blues/Blues_Data.txt4
-rw-r--r--City/Scenes/Blues/MidiFiles/Bass.midbin0 -> 738 bytes
-rw-r--r--City/Scenes/Blues/MidiFiles/Chords.midbin0 -> 990 bytes
-rw-r--r--City/Scenes/Blues/MidiFiles/Drums.midbin0 -> 3593 bytes
-rw-r--r--City/Scenes/Blues/MidiFiles/Lead.midbin0 -> 906 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/BassAudio/Dance1Bass[28-36-39]mn_000.aifbin0 -> 72074 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/BassAudio/Dance1Bass[40-48-51]mn_000.aifbin0 -> 68930 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/BassAudio/Dance1Bass[52-60-63]mn_000.aifbin0 -> 70106 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[100-108-111]mn_000.aifbin0 -> 252726 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[64-72-75]mn_000.aifbin0 -> 252710 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[76-84-87]mn_000.aifbin0 -> 252726 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[88-96-99]mn_000.aifbin0 -> 252726 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/DrumsAudio/Dance1909kick7[36-36-36].aifbin0 -> 23554 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/DrumsAudio/Dance1909snare3[38-38-38].aifbin0 -> 16590 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/DrumsAudio/Dance1SHAKER_1[46-46-46].aifbin0 -> 4660 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/DrumsAudio/Dance1closedhat11[39-39-39].aifbin0 -> 10838 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/DrumsAudio/Dance1openedhat4[42-42-42].aifbin0 -> 28466 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[28-36-39]_001_001mn_000.aifbin0 -> 32160 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[40-48-51]_001_001mn_000.aifbin0 -> 32428 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[52-60-63]_001_001mn_000.aifbin0 -> 32684 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[64-72-75]_001_001mn_000.aifbin0 -> 31904 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[76-84-87]_001_001mn_000.aifbin0 -> 32428 bytes
-rwxr-xr-xCity/Scenes/City/AudioFiles/LeadAudio/keys-good[88-96-99]_001_001mn_000.aifbin0 -> 31904 bytes
-rw-r--r--City/Scenes/City/City_Data.txt8
-rwxr-xr-xCity/Scenes/City/MidiFiles/Bass.midbin0 -> 335 bytes
-rwxr-xr-xCity/Scenes/City/MidiFiles/Chords.midbin0 -> 1075 bytes
-rwxr-xr-xCity/Scenes/City/MidiFiles/Drums.midbin0 -> 1952 bytes
-rwxr-xr-xCity/Scenes/City/MidiFiles/Lead.midbin0 -> 635 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/BassAudio/BassC2[41-48-50].aifbin0 -> 101158 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/BassAudio/BassC3[59-60-62].aifbin0 -> 103186 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/BassAudio/BassC4[70-72-78].aifbin0 -> 100678 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/BassAudio/BassF#2[51-54-58].aifbin0 -> 100048 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/ChordsAudio/epnoC4[70-72-73].aifbin0 -> 72482 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/ChordsAudio/epnoC5[82-84-90].aifbin0 -> 72654 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/ChordsAudio/epnoE3[63-64-65].aifbin0 -> 72798 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/ChordsAudio/epnoE4[74-76-77].aifbin0 -> 72236 bytes
-rwxr-xr-xCity/Scenes/Country/AudioFiles/DrumsAudio/C#1_rim_shot.aifbin0 -> 9447 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/DrumsAudio/C1_kick_drum.aifbin0 -> 12739 bytes
-rwxr-xr-xCity/Scenes/Country/AudioFiles/DrumsAudio/D1_snare_drum.aifbin0 -> 15236 bytes
-rwxr-xr-xCity/Scenes/Country/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aifbin0 -> 6371 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/B2_guitar.aifbin0 -> 50070 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/B3_guitar.aifbin0 -> 50412 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/E2_guitar.aifbin0 -> 51016 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/E3_guitar.aifbin0 -> 50324 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/E4_guitar.aifbin0 -> 49942 bytes
-rw-r--r--City/Scenes/Country/AudioFiles/LeadAudio/E5_guitar.aifbin0 -> 51070 bytes
-rw-r--r--City/Scenes/Country/Country_Data.txt5
-rwxr-xr-xCity/Scenes/Country/MidiFiles/Bass.midbin0 -> 1307 bytes
-rwxr-xr-xCity/Scenes/Country/MidiFiles/Chords.midbin0 -> 1357 bytes
-rwxr-xr-xCity/Scenes/Country/MidiFiles/Drums.midbin0 -> 3164 bytes
-rwxr-xr-xCity/Scenes/Country/MidiFiles/Lead.midbin0 -> 1085 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/BassAudio/BassC2[41-48-50].aifbin0 -> 101130 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/BassAudio/BassC3[59-60-62].aifbin0 -> 103158 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/BassAudio/BassC4[70-72-78].aifbin0 -> 100650 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/BassAudio/BassF#2[51-54-58].aifbin0 -> 100020 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C4 22 16 mono.aifbin0 -> 20982 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C5 22 16 mono.aifbin0 -> 20364 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G3 22 16 mono.aifbin0 -> 21540 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G4 22 16 mono.aifbin0 -> 19980 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C#3 22 16 Mono.aifbin0 -> 7190 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C3 22 16 Mono.aifbin0 -> 5530 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo D3 22 16 Mono.aifbin0 -> 4432 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/ClosedhatF#1.aifbin0 -> 5096 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Kick-C1.aifbin0 -> 14366 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Shaker 22 16 Mono.aifbin0 -> 13018 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/Snare-D1.aifbin0 -> 30086 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/DrumsAudio/TambF#2.aifbin0 -> 27936 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets A4 22 16 mono.aifbin0 -> 28164 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets C4 22 16 mono.aifbin0 -> 31100 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets E3 22 16 mono.aifbin0 -> 31846 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets F4 22 16 mono.aifbin0 -> 31886 bytes
-rw-r--r--City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets G3 22 16 mono.aifbin0 -> 32132 bytes
-rw-r--r--City/Scenes/Latin/Latin_Data.txt3
-rw-r--r--City/Scenes/Latin/MidiFiles/Bass.midbin0 -> 614 bytes
-rw-r--r--City/Scenes/Latin/MidiFiles/Chords.midbin0 -> 764 bytes
-rw-r--r--City/Scenes/Latin/MidiFiles/Drums.midbin0 -> 2919 bytes
-rw-r--r--City/Scenes/Latin/MidiFiles/Lead.midbin0 -> 844 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/BassAudio/BassC2[41-48-50].aifbin0 -> 101158 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/BassAudio/BassC3[59-60-62].aifbin0 -> 103186 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/BassAudio/BassC4[70-72-78].aifbin0 -> 100678 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/BassAudio/BassF#2[51-54-58].aifbin0 -> 100048 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC4[70-72-73].aifbin0 -> 72482 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC5[82-84-90].aifbin0 -> 72654 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE3[63-64-65].aifbin0 -> 72798 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE4[74-76-77].aifbin0 -> 72236 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/DrumsAudio/ClosedhatF#1.aifbin0 -> 5096 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/DrumsAudio/Kick-C1.aifbin0 -> 14366 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/DrumsAudio/OpenhatA#1.aifbin0 -> 112568 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/DrumsAudio/Snare-D1.aifbin0 -> 30086 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/DrumsAudio/TambF#2.aifbin0 -> 27936 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/B2_guitar.aifbin0 -> 50070 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/B3_guitar.aifbin0 -> 50412 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/E2_guitar.aifbin0 -> 51016 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/E3_guitar.aifbin0 -> 50324 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/E4_guitar.aifbin0 -> 49942 bytes
-rw-r--r--City/Scenes/Reggae/AudioFiles/LeadAudio/E5_guitar.aifbin0 -> 51070 bytes
-rw-r--r--City/Scenes/Reggae/MidiFiles/Bass.midbin0 -> 484 bytes
-rw-r--r--City/Scenes/Reggae/MidiFiles/Chords.midbin0 -> 947 bytes
-rw-r--r--City/Scenes/Reggae/MidiFiles/Drums.midbin0 -> 1638 bytes
-rw-r--r--City/Scenes/Reggae/MidiFiles/Lead.midbin0 -> 764 bytes
-rw-r--r--City/Scenes/Reggae/Reggae_Data.txt3
-rwxr-xr-xCity/Tracks.py512
-rwxr-xr-xCity/__init__.py0
-rwxr-xr-xCity/midiImport.py379
-rwxr-xr-xCity/setup.py4
139 files changed, 1889 insertions, 0 deletions
diff --git a/City/City.py b/City/City.py
new file mode 100755
index 0000000..766206d
--- /dev/null
+++ b/City/City.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+"""
+Turn all of this into executable functions
+Then move it to run.py
+"""
+
+from CsHelpers import *
+import CsSched, Parameters, OrcBuilder, Tracks
+import random
+
+class ScenePlayer( SceneData ):
+ def __init__(self, scene_name = 'City', key = 'A', mode = 'minor', tempo = 120, defaults = {}):
+ SceneData.__init__(self, scene_name)
+ self.tempo = tempo
+ self.Csynth = CsSched.Csound()
+ self.TimeQueue = CsSched.Sched()
+ self.Params = Parameters.Perimeter()
+ self.orc = OrcBuilder.OrcConstructor()
+ self.makeOrc()
+ self.cs = CsSched.CsoundPerformer(self.TimeQueue, self.orc, self.Csynth.csound)
+ self.Params.csoundChannels(self.cs)
+ self.loadTracks(key, mode)
+ self.setParameters(defaults)
+ def setParameters(self, pdict):
+ "dict is a dictionary in the form: {Instrument:{parameter:value}}"
+ for i in pdict:
+ for p in pdict[i]:
+ print "setting: ", p,i,pdict[i][p]
+ self.Params.setValue(p,i,pdict[i][p])
+ def makeOrc(self, sr = 22050, ksmps = 128):
+ orc = self.orc
+ orc.sr = sr
+ orc.ksmps = ksmps
+ lookuptabs = [OrcBuilder.orcLoadSamples(orc, self.Csynth, instr+"Lookup", eval("self."+instr+"AudioPath")) for instr in INAMES]
+ ftabs = [OrcBuilder.FtableBreakPoint("rvbc1", -558, -594, -638, -678, -711, -745, -778, -808, 0.8, 0.79, 0.78, 0.77, 0.76, 0.75, 0.74, 0.73),
+ OrcBuilder.FtableBreakPoint("rvbc2", -517, -540, -656, -699, -752, -799, -818, -841, 0.8, 0.79, 0.78, 0.77, 0.76, 0.75, 0.74, 0.73),
+ OrcBuilder.FtableBreakPoint("rvba1", -278, -220, -170, -122, 0.4, 0.52, 0.64, 0.76),
+ OrcBuilder.FtableBreakPoint("rvba2", -333, -263, -166, -105, 0.5, 0.52, 0.64, 0.76)]
+ orc.insertftables(*ftabs)
+ volumechans = self.commonChannels("Volume", 0.8)
+ timbrechans = self.commonChannels("Timbre", 0.5)
+ orc.insertChannels(*volumechans)
+ orc.insertChannels(*timbrechans)
+ setlevels = OrcBuilder.OrcSetLevelInstrument()
+ setlevels.effect = True
+ mixerout = OrcBuilder.OrcMixoutInstrument()
+ mixerout.effect = True
+ samplerbody = """
+ idur = p3
+ iamp = p4 * (0dbfs / 127)
+ kcps init cpsmidinn(p5)
+ isamp table p5, %s
+ a1 loscil iamp, kcps, isamp
+ a1 dcblock a1
+ kdeclick linseg 0, 0.008, 1, idur - 0.05 - 0.008, 1, 0.05, 0
+ a1 = a1 * kdeclick """
+ timbrebody = ("""
+ idur = p3
+ ires = 5.75
+ kfco expcurve %s + 0.01, 17
+ kfco = kfco * """ + str(orc.sr*0.5 * 0.45) + """ + 1200
+ a2 rezzy a1, kfco, ires
+ a1 balance a2, a1
+ a1 = a1 * 0.2 + a2 * 0.4
+ """)
+ SamplerInstruments, TimbreInstruments = [OrcBuilder.OrcInstrument(i+'Sampler') for i in INAMES], [OrcBuilder.OrcInstrument(i+'Timbre') for i in INAMES]
+ for Si, Ti in zip(SamplerInstruments, TimbreInstruments):
+ Si.insertLine(samplerbody % [x for x in [n.varname() for n in lookuptabs] if x.__contains__(Si.name[:-7])][0])
+ Ti.insertLine(timbrebody % [y for y in [j.varname() for j in timbrechans] if y.__contains__(Ti.name[:-6])][0])
+ Si.routeOut('a1', Ti, setlevels, [c for c in [v.varname() for v in volumechans] if c.__contains__(Si.name[:-7])][0])
+ Ti.routeOut('a1', mixerout, setlevels)
+ Ti.routeIn('a1')
+ Ti.effect = True
+ orc.appendInstruments(Si, Ti)
+ orc.appendInstruments(mixerout)
+ orc.prependInstrument(setlevels)
+ return True
+ def commonChannels(self, chnName, default):
+ "returns a list of channel objects for INAMES"
+ return OrcBuilder.orcChannelMaker(INAMES, chnName, init = default)
+ def loadTracks(self, key, mode):
+ "see sc below"
+ self.scale = Tracks.Scale(key, mode)
+ midifiles = ResourceList(self.MidiFilePath, ".mid")
+ for m in midifiles:
+ score = Tracks.Midi2Score(self.MidiFilePath + "/" + m)
+ track = score.midiTrack2ScoreTrack(score.getTrack(0))
+ if m.startswith('Lead'):
+ self.leadtrack = track
+ elif m.startswith('Bass'):
+ self.basstrack = track
+ elif m.startswith('Chords'):
+ self.chordstrack = track
+ elif m.startswith('Drums'):
+ self.drumstrack = track
+ else:
+ raise ValueError, "Can't match MIDI file %s to instrument" %m
+
+def makePlayer(scene):
+ "create and return a player"
+ player = Tracks.beatDebugPlayer(scene.cs, scene.TimeQueue, scene.Params, scene.scale)
+ player.setBPM(scene.tempo)
+ lead = scene.orc.nameNumber['LeadSampler']
+ bass = scene.orc.nameNumber['BassSampler']
+ chords = scene.orc.nameNumber['ChordsSampler']
+ drums = scene.orc.nameNumber['DrumsSampler']
+ player.beatInstrumentMap(1, Lead = [scene.leadtrack, lead], Bass = [scene.basstrack,bass],
+ Chords = [scene.chordstrack, chords], Drums = [scene.drumstrack, drums])
+ return player
+
diff --git a/City/CsHelpers.py b/City/CsHelpers.py
new file mode 100755
index 0000000..800dae1
--- /dev/null
+++ b/City/CsHelpers.py
@@ -0,0 +1,194 @@
+#! /usr/bin/env python
+""" This file should be imported by all other files, so-as to defined cross-module global variables."""
+print "loading CsHelpers"
+import os,sys
+import pygame
+pygame.mixer.quit()
+
+platform = "undefined"
+
+try:
+ import olpcgames
+ import olpcgames.util
+ if olpcgames.ACTIVITY:
+ platform = "Sugar"
+except ImportError:
+ pass
+
+if platform == "undefined":
+ if sys.platform.startswith('darwin'):
+ platform = 'MacOSX'
+ elif sys.platform.startswith('win'):
+ platform = "Win32"
+ else: pass
+
+def modulePath():
+ "returns a string of the current path used for python modules"
+ if __name__ == '__main__':
+ return os.getcwd()
+ else: return os.path.dirname(os.path.abspath(__file__))
+
+ModulePath = modulePath()
+InstrumentPath = ModulePath + "/CsInstruments"
+ImagePath = ModulePath + "/Images"
+ScenePath = ModulePath + "/Scenes"
+
+PNAMES = ["Pitch", "Volume", "Timbre", "Tempo", "Length", "Density"]
+INAMES = ["Drums", "Lead", "Chords", "Bass"]
+SCENENAMES = [dir for dir in os.listdir(ScenePath) if os.path.isdir(ScenePath + '/' + dir)]
+
+class SceneData( object ):
+ def __init__(self, scene_name):
+ self.scene_name = scene_name
+ self.scene_path = ScenePath + "/" + scene_name
+ self.MidiFilePath = self.scene_path + "/MidiFiles"
+ self.AudioPath = self.scene_path + "/AudioFiles"
+ self.BassAudioPath = self.AudioPath + "/BassAudio"
+ self.LeadAudioPath = self.AudioPath + "/LeadAudio"
+ self.ChordsAudioPath = self.AudioPath + "/ChordsAudio"
+ self.DrumsAudioPath = self.AudioPath + "/DrumsAudio"
+
+class beatCluster( object ):
+ "An object which calculates a beat/time line, based on recorded beat time values"
+ def __init__(self, tempo_factor, beatlimit):
+ self.times = []
+ self.beat_id = 0
+ self.beatlimit = beatlimit
+ self.tempo_factor = tempo_factor
+ self.modulo_offset = 0
+ def beat2Time(self, beat):
+ "returns a time value based on a beat"
+ t = self._average_time()
+ bdiff = beat - self.beat_id
+ tdiff = bdiff * self.tempo_factor
+ result = t + tdiff
+ return result
+ def time2Beat(self, time):
+ "returns a beat value, when given a time"
+ t = self._average_time()
+ mtime = (time - self.modulo_offset) % (self.beat2Time(self.beatlimit) - self.modulo_offset) + self.modulo_offset
+ tdiff = mtime - t
+ bdiff = (tdiff * (1/self.tempo_factor))
+ b = self.beat_id + bdiff
+ return b % self.beatlimit
+ def _average_time(self):
+ return sum(self.times) / len(self.times)
+ def addTime(self, beat, time):
+ "store times"
+ if not self.times:
+ self.beat_id = beat
+ self.times.append(time)
+ self.modulo_offset = self.beat2Time(0)
+ else:
+ bdiff = beat - self.beat_id
+ tdiff = bdiff * self.tempo_factor
+ mtime = (time - self.modulo_offset) % (self.beat2Time(self.beatlimit) - self.modulo_offset) + self.modulo_offset
+ result = mtime - tdiff
+ self.times.append(result)
+ def __len__(self):
+ return len(self.times)
+
+
+
+class beatEstimator( object ):
+ "An object to collect beat and time values, and estimate when the next beat should be received"
+ def __init__(self, tempo_factor, tolerance, beatlimit):
+ self.beat_groups = []
+ self.tempo_factor = tempo_factor
+ self.tolerance = tolerance
+ self.beatlimit = beatlimit
+ def addBeat(self, beat, time):
+ "records the time a beat was received, and either adds it to an existing cluster or creates a new cluster, provide"
+ if not self.beat_groups:
+ bc = beatCluster(self.tempo_factor, self.beatlimit)
+ bc.addTime(beat, time)
+ self.beat_groups.append(bc)
+ else:
+ bt, bc = self.beat_match(time, True) # beatCluster.time2Beat(time). returns the expected beat of largest beatcluster, and the beatcluster itself
+ if abs(bt- beat) < self.tolerance: #where tolerance refers to a fractio of the beat.
+ print "adding to optimal beat cluster"
+ bc.addTime(beat, time)
+ else: #check the other beats
+ for b in filter(lambda xb: xb != bc, self.beat_groups):
+ otherbt = b.time2Beat(time)
+ if abs(otherbt - beat) < self.tolerance:
+ print "adding to other beat"
+ b.addTime(beat, time)
+ break
+ else:
+ print "creating new beat cluster"
+ # if no match, append a new beat
+ newbc = beatCluster(self.tempo_factor, self.beatlimit)
+ newbc.addTime(beat, time)
+ self.beat_groups.append(newbc)
+ def beat_match(self, time, include_reference = False):
+ "returns the expected time of the beat, referenced from the optimal beat"
+ optimal_bc = self.beat_groups[0]
+ for lb in self.beat_groups:
+ if len(lb) >= len(optimal_bc): optimal_bc = lb
+ if include_reference:
+ return (optimal_bc.time2Beat(time), optimal_bc)
+ else:
+ return optimal_bc.time2Beat(time)
+
+
+
+def getInstruments(*names):
+ "concatenate Instruments from the Instrument Path"
+ result = ""
+ for i in names:
+ Instrument = open(InstrumentPath + "/" + i, 'r')
+ result += Instrument.read() + '\n'
+ return result
+
+def limit(n, low, hi):
+ "set lower and upp bounds for values"
+ if n < low: return low
+ elif n > hi: return hi
+ else:
+ return n
+
+def rescale(n, oldmin, oldmax, newmin, newmax):
+ oldrange = float(oldmax) - oldmin
+ newrange = float(newmax) - newmin
+ oldsize = float(n) - oldmin
+ return (newrange / oldrange) * oldsize + newmin
+
+
+def ResourceList(path, suffix):
+ "returns a list of files in the directory"
+ return [f for f in os.listdir(path) if f[-len(suffix):] == suffix and f[0] != '.']
+
+
+def removeillegals(s):
+ "removes illegal csound characters from names"
+ result = ''
+ for i in s:
+ if i.isalnum() or i == '_':
+ result += i
+ return result
+
+
+def aselect(lst, *indices):
+ result = []
+ for i in range(len(lst)):
+ if i not in indices:
+ result.append(lst[i])
+ return result
+
+def select(lst, *indices):
+ result = []
+ for i in range(len(lst)):
+ if i in indices:
+ result.append(lst[i])
+ return result
+
+
+
+if __name__ == '__main__':
+ print ResourceList(InstrumentPath, ".orc")
+ print ResourceList(MidiFilePath, ".mid")
+
+
+
+
diff --git a/City/CsSched.py b/City/CsSched.py
new file mode 100755
index 0000000..14e5588
--- /dev/null
+++ b/City/CsSched.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+import csnd, heapq
+from CsHelpers import *
+
+class Csound:
+ "precompiles a csound object"
+ def __init__(self):
+ self.csound = csnd.CppSound()
+ self.csound.setPythonMessageCallback()
+ self.csound.PreCompile()
+ def __repr__(self):
+ return "Precompiled Csound object"
+
+
+class Sched:
+ def __init__(self):
+ self.queue = []
+ def schedEvent(self, time, func, *args):
+ heapq.heappush(self.queue, (time, func, args))
+ def getTime(self):
+ if self:
+ return self.queue[0][0]
+ else:
+ return False
+ def getFunc(self):
+ if len(self) == 0:
+ return False
+ else:
+ return self.queue[0][1]
+ def getArgs(self):
+ if len(self) == 0:
+ return False
+ else:
+ return self.queue[0][2]
+ def __len__(self):
+ return len(self.queue)
+ def __repr__(self):
+ return str(self.queue)
+
+class CsoundChan:
+ "a container for Csound channel data"
+ #type is either Audio, Control, or String
+ #Dirction = INput or Output
+ #subType = interger, linear or exponential
+ #default = default value
+ #minval = suggested minimum
+ #maxval == suggested maximum
+ pass
+
+
+
+def channels(csound):
+ "returns a list of Input and output software bus channels"
+ Chanlist = csnd.CsoundChannelList(csound)
+ result = []
+ for ndx in range(Chanlist.Count()):
+ ch = CsoundChan()
+ ch.name = Chanlist.Name(ndx)
+ if Chanlist.IsAudioChannel(ndx):
+ ch.type = "Audio"
+ elif Chanlist.IsControlChannel(ndx):
+ ch.type = "Control"
+ elif Chanlist.IsStringChannel(ndx):
+ ch.type = "String"
+ else: pass
+ if Chanlist.IsInputChannel(ndx) and Chanlist.IsOutputChannel(ndx):
+ ch.direction = "bidirectional"
+ elif Chanlist.IsInputChannel(ndx):
+ ch.direction = "input"
+ elif Chanlist.IsOutputChannel(ndx):
+ ch.direction = "output"
+ else: pass
+ if Chanlist.SubType(ndx) > 0:
+ tmp = ['integer', 'linear', 'exponential']
+ ch.subtype = (tmp[Chanlist.SubType(ndx) - 1])
+ ch.default = (Chanlist.DefaultValue(ndx))
+ ch.minval = (Chanlist.MinValue(ndx))
+ ch.maxval = (Chanlist.MaxValue(ndx))
+ result.append(ch)
+ Chanlist.Clear()
+ return result
+
+
+
+class CsoundPerformer:
+ def pollScheduler(self, schedObj):
+ st = schedObj.getTime()
+ if st:
+ t = self.perfTime()
+ if t >= st:
+ obj = heapq.heappop(schedObj.queue)
+ (obj[1] (*obj[2]))
+ def __init__(self, schedObj, orcObj, *cs):
+ "SchedObj is a Csound timer instance, orcObJ is a CsOrcConstructor Object"
+ self.Timer = csnd.CsoundTimer()
+ self.schedObj = schedObj
+ self.orcObj = orcObj
+ if len(cs) == 0:
+ cs = Csound()
+ self.csound = Csound.csound
+ else: self.csound = cs[0]
+ self.csound.setOrchestra(orcObj.exportOrc())
+ self.csound.setScore(orcObj.sco)
+ self.time = 0
+ if platform == "Sugar":
+ self.csound.setCommand("csound -b256 -B2048 -+rtaudio=alsa -odac --expression-opt --sched=1 -d -m0 /tmp/tmp.orc /tmp/tmp.sco")
+ else:
+ self.csound.setCommand("csound -b256 -B2048 -odac --expression-opt -d -m0 /tmp/tmp.orc /tmp/tmp.sco")
+ self.csound.exportForPerformance()
+ self.csound.compile()
+ self.Channels = channels(self.csound)
+ self.perf = csnd.CsoundPerformanceThread(self.csound)
+ self.perf.Play()
+ self.perf.SetProcessCallback(self.pollScheduler, schedObj)
+ def perfTime(self):
+ return self.Timer.GetRealTime()
+ def Stop(self):
+ self.perf.Stop()
+ #self.perf.Join()
+ self.csound.Cleanup()
+ def setChannelValue(self, channame, value):
+ self.csound.SetChannel(channame, value)
+ def getChannelValue(self, channame):
+ return self.csound.GetChannel(channame)
+ def getChannelList(self):
+ return csnd.CsoundChannelList(self.csound)
+ def getChannelNames(self):
+ chlst = self.getChannelList()
+ return [chlst.Name(ch) for ch in range(chlst.Count())]
+ def playParams(self, ins, start, dur, *params):
+ "send score message to Csound with parameter values"
+ if start < 0: start = 0
+ s = ' '.join(map(str, (['i', ins, start, dur] + [str(n) for n in params])))
+ self.perf.InputMessage(s)
+ def playNote(self, ins, note):
+ "send score message to Csound using a note object"
+ start = note[0]
+ dur = note[1]
+ params = note[2:]
+ self.perf.InputMessage(' '.join(['i', str(ins),str(start),str(dur)]+[str(n) for n in params]))
+
+
diff --git a/City/Images/Bass.png b/City/Images/Bass.png
new file mode 100755
index 0000000..31507d9
--- /dev/null
+++ b/City/Images/Bass.png
Binary files differ
diff --git a/City/Images/Chords.png b/City/Images/Chords.png
new file mode 100755
index 0000000..f4d4660
--- /dev/null
+++ b/City/Images/Chords.png
Binary files differ
diff --git a/City/Images/Drums.png b/City/Images/Drums.png
new file mode 100755
index 0000000..7a8ee0a
--- /dev/null
+++ b/City/Images/Drums.png
Binary files differ
diff --git a/City/Images/Lead.png b/City/Images/Lead.png
new file mode 100755
index 0000000..6ebc70a
--- /dev/null
+++ b/City/Images/Lead.png
Binary files differ
diff --git a/City/Images/Mic.png b/City/Images/Mic.png
new file mode 100755
index 0000000..34fa1bd
--- /dev/null
+++ b/City/Images/Mic.png
Binary files differ
diff --git a/City/Images/Video.png b/City/Images/Video.png
new file mode 100755
index 0000000..c5c25ca
--- /dev/null
+++ b/City/Images/Video.png
Binary files differ
diff --git a/City/Images/camera-busy.svg b/City/Images/camera-busy.svg
new file mode 100755
index 0000000..6c79d17
--- /dev/null
+++ b/City/Images/camera-busy.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#ffffff">
+ <!ENTITY fill_color "#000000">
+]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="camera-external">
+ <g display="inline">
+ <g>
+ <polygon fill="&fill_color;" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 "/>
+ </g>
+ <g>
+ <polygon fill="none" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 " stroke="&stroke_color;" stroke-width="3.5"/>
+ </g>
+ </g>
+ <path d="M20.601,26.441c0,3.67,2.979,6.648,6.65,6.648 c3.667,0,6.646-2.979,6.646-6.648c0-3.668-2.979-6.652-6.646-6.652C23.581,19.789,20.601,22.775,20.601,26.441z" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/>
+ <rect display="inline" fill="&stroke_color;" height="4.193" width="6.287" x="38.099" y="18.418"/>
+</g></svg> \ No newline at end of file
diff --git a/City/Images/camera-external.svg b/City/Images/camera-external.svg
new file mode 100755
index 0000000..54d9c86
--- /dev/null
+++ b/City/Images/camera-external.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#ffffff">
+]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="camera-external">
+ <g display="inline">
+ <g>
+ <polygon fill="&fill_color;" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 "/>
+ </g>
+ <g>
+ <polygon fill="none" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 " stroke="&stroke_color;" stroke-width="3.5"/>
+ </g>
+ </g>
+ <path d="M20.601,26.441c0,3.67,2.979,6.648,6.65,6.648 c3.667,0,6.646-2.979,6.646-6.648c0-3.668-2.979-6.652-6.646-6.652C23.581,19.789,20.601,22.775,20.601,26.441z" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/>
+ <rect display="inline" fill="&stroke_color;" height="4.193" width="6.287" x="38.099" y="18.418"/>
+</g></svg> \ No newline at end of file
diff --git a/City/Images/jam2jamXO_2.png b/City/Images/jam2jamXO_2.png
new file mode 100644
index 0000000..893b4c2
--- /dev/null
+++ b/City/Images/jam2jamXO_2.png
Binary files differ
diff --git a/City/Images/media-playback-pause.svg b/City/Images/media-playback-pause.svg
new file mode 100755
index 0000000..aa4a585
--- /dev/null
+++ b/City/Images/media-playback-pause.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="media-playback-pause">
+ <g display="inline">
+ <path d="M27.499,0C12.311,0,0,12.313,0,27.5C0,42.688,12.311,55,27.499,55C42.686,55,55,42.688,55,27.5 C55,12.313,42.686,0,27.499,0z M27.497,52.646c-13.826,0-25.033-11.209-25.035-25.033C2.463,13.787,13.67,2.577,27.497,2.574 c13.826,0.003,25.035,11.213,25.039,25.038C52.531,41.437,41.322,52.646,27.497,52.646z" fill="&fill_color;"/>
+ <path d="M27.496,5C15.068,5,4.997,15.076,4.997,27.5c0,12.427,10.071,22.5,22.499,22.5 c12.428,0,22.5-10.073,22.5-22.5C49.996,15.076,39.924,5,27.496,5z M25.938,35.443h-5.801V19.741h5.801V35.443z M34.855,35.443 h-5.803V19.741h5.803V35.443z" fill="&fill_color;"/>
+ </g>
+</g></svg> \ No newline at end of file
diff --git a/City/Images/media-playback-start.svg b/City/Images/media-playback-start.svg
new file mode 100755
index 0000000..e2e0051
--- /dev/null
+++ b/City/Images/media-playback-start.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="media-playback-start">
+ <g display="inline">
+ <g>
+ <g>
+ <g>
+ <path d="M27.496,5.051C15.036,5.07,4.952,15.155,4.93,27.618C4.952,40.08,15.036,50.164,27.496,50.185 c12.465-0.021,22.549-10.104,22.568-22.566C50.045,15.155,39.961,5.07,27.496,5.051z M21.551,37.977v-20.31l17.961,10.155 L21.551,37.977z" fill="&fill_color;"/>
+ </g>
+ </g>
+ <path d="M27.498,0C12.311,0,0,12.313,0,27.5C0,42.688,12.311,55,27.498,55C42.686,55,55,42.688,55,27.5 C55,12.313,42.686,0,27.498,0z M27.496,52.646c-13.826,0-25.033-11.209-25.035-25.033C2.463,13.787,13.67,2.577,27.496,2.574 c13.826,0.003,25.035,11.213,25.039,25.038C52.531,41.437,41.322,52.646,27.496,52.646z" fill="&fill_color;"/>
+ </g>
+ </g>
+</g></svg> \ No newline at end of file
diff --git a/City/OrcBuilder.py b/City/OrcBuilder.py
new file mode 100755
index 0000000..776cc9e
--- /dev/null
+++ b/City/OrcBuilder.py
@@ -0,0 +1,342 @@
+#!/usr/bin/env python
+
+import csnd, sys
+from CsHelpers import *
+
+
+class Ftable:
+ def __init__(self):
+ self.start = 0
+ self.num = 0
+ self.size = 8192
+ self.gen = 10
+ self.name = "sine"
+ self.args = [10,1]
+ def varname(self):
+ return "gi_"+self.name
+ def __repr__(self):
+ head = [self.varname(), 'ftgen', str(self.num)+', ']
+ args = [str(self.start), str(self.size), str(self.gen)] + map(str, self.args)
+ return ' '.join(head) + ', '.join(args)
+
+class FtableBreakPoint(Ftable):
+ "constructs a Gen 2 ftable"
+ def __init__(self, name, *args, **num):
+ Ftable.__init__(self)
+ self.name = name
+ self.gen = -2
+ self.size = (2**i for i in xrange(2,100) if 2**i >= len(args)).next()
+ self.args = args
+ if num.has_key('num'): self.num = num['num']
+
+class FtableSample(Ftable):
+ "loads samples into GEN 1, and optional basepitch storage"
+ def __init__(self, pathname, *basepit, **num):
+ Ftable.__init__(self)
+ self.gen = -1
+ filename = pathname.rpartition('/')[-1]
+ ndx = filename.find('.')
+ if ndx != -1:
+ self.name = removeillegals(filename[0:ndx])
+ else: self.name = removeillegals(filename)
+ self.size = 0
+ self.args = ['"'+pathname+'"', 0, 0, 0]
+ if len(basepit) > 0:
+ self.basePitch = basepit[0]
+ if num.has_key('num'): self.num = num['num']
+
+class FtableLookup(Ftable):
+ def __init__(self, name, skew, *sampletables, **num):
+ "uses GEN17 to make an x,y lookup table suitable for mid pitch lookup. GEN17"
+ #skew calculates the point at which the next table is lookup up.
+ #pitnamedict is a dictionary of {basepitches:samplenames,...}
+ Ftable.__init__(self)
+ pitnamedict = {}
+ for s in sampletables:
+ pitnamedict[s.basePitch] = s.varname()
+ sorted = []
+ for key in pitnamedict:
+ sorted.append([key, pitnamedict[key]])
+ sorted.sort()
+ args = []
+ for i in range(len(sorted)):
+ if i == 0:
+ args.append(i)
+ args.append(sorted[i][1])
+ else:
+ args.append(int(round (sorted[i][0] - (sorted[i][0] - sorted[i-1][0]) * skew)))
+ args.append(sorted[i][1])
+ self.gen = -17
+ self.name = name
+ self.size = 128
+ self.args = args
+ if num.has_key('num'): self.num = num['num']
+
+class OrcChan:
+ def __init__(self, name, direction, rate, init):
+ self.name = name
+ self.direction = direction
+ self.rate = rate
+ self.initval = init
+ def mode(self):
+ return (1 if self.direction == 'input' else (2 if self.direction == 'output' else 3))
+ def varname(self):
+ return 'g'+('a' if self.rate == 'audio' else ('k' if self.rate == 'control' else ('S' if self.rate == 'string' else 'i')))+'_'+self.name
+ def initline(self):
+ return self.varname() + '\t' + 'init' + '\t' + str(self.initval)
+ def __repr__(self):
+ final = self.varname() + ' '+'chnexport'+' \"'+self.name+'\", '+str(self.mode())+('\n'+self.initline() if (self.rate == 'audio' or self.rate == 'string') else ',2,1,0,1'+ '\n'+self.initline())
+ return final
+
+def orcChannelMaker(insnames, parameter, direction = "input", rate = "control", init = 1):
+ "a simple function to generate numerous channels of the same type"
+ result = []
+ for i in insnames:
+ name = i+parameter
+ o = OrcChan(name, direction, rate, init)
+ result.append(o)
+ return result
+
+#Not cognisant of scoreline parameter variables at this stage.
+class OrcInstrument:
+ def __init__(self, name='undefined'):
+ self.name = name
+ self.lines = []
+ self.effect = False #if true, then an 'always on' scoreline is automatically added.
+ def header(self):
+ return ["instr \t$"+self.name+"\n"]
+ def varname(self):
+ return "$"+self.name
+ def insertLine(self, line):
+ self.lines.append(line)
+ def routeOut(self, asendvar, outINS, SetLvlIns, gkvarname = 1, *chan):
+ "SO, gkvarname is 1 by default, but should be the gkvariable if going to mixout"
+ SetLvlIns.setLevel(self, outINS, gkvarname)
+ self.insertLine("\tMixerSend "+asendvar+", p1, "+outINS.varname()+", "+str((chan[0] if len(chan)>0 else 0)))
+ def routeIn(self, ainvar, *chan):
+ self.lines.insert(0, ainvar+" MixerReceive "+"p1,"+str((chan[0] if len(chan)>0 else 0)))
+ def __repr__(self):
+ result = self.header() + self.lines
+ return "\n".join(result) + '\n\nendin\n'
+
+class OrcSetLevelInstrument(OrcInstrument):
+ def __init__(self):
+ OrcInstrument.__init__(self)
+ self.name = "mixerSetLevels"
+ self.routemap = {}
+ def setLevel(self, sendINS, bussINS, gkvarname):
+ self.routemap[sendINS.name] = bussINS.name
+ self.insertLine("\t MixerSetLevel "+sendINS.varname()+", "+bussINS.varname()+", "+str(gkvarname)+"\n") #change this to the gkvariable name
+ def mixout(self, ainvar, *chan):
+ "sends output of an instrument to a mixer buss"
+ self.insertLine("\tMixerSend "+ainvar+", p1, "+"$output, "+str((chan[0] if len(chan)>0 else 0)))
+
+
+class OrcMixoutInstrument(OrcInstrument):
+ def __init__(self):
+ OrcInstrument.__init__(self)
+ self.name = "output"
+ self.routeIn("am")
+ self.insertLine("""
+ am eqfil am, 900, 200, 0.2
+ a3 nreverb am, 0.12, 1, 0, 8, gi_rvbc1, 4, gi_rvba1
+ a4 nreverb am, 0.12, 1, 0, 8, gi_rvbc2, 4, gi_rvba2
+ a3 = am + a3*0.23
+ a4 = am + a4*0.23
+ outs a3, a4
+ ;outs am, am
+ MixerClear
+ """)
+
+
+
+class OrcConstructor:
+ def __init__(self):
+ self.orc = ""
+ self.sco = "f0 28800 \n"
+ self.sr = 44100
+ self.ksmps = 100
+ self.nchnls = 2
+ self.dbfs = 1
+ self.macros = []
+ self.ftabs = []
+ self.chans = []
+ self.instruments = []
+ self.csline = []
+ self.nameNumber = {}
+ self.insertftables(Ftable()) #insert a sine by default
+ def insertLines(self, lines):
+ self.csline.append(lines)
+ def insertInsnums(self, Instruments):
+ insnumgen = (i for i in xrange(1, 100))
+ for i in Instruments:
+ num = insnumgen.next()
+ self.nameNumber[i.name] = num
+ self.macros.append("#define "+i.name+" #"+str(num)+"#")
+ if i.effect:
+ self.sco = self.sco + "i%s 0 -1 \n" %num
+ def insertftables(self, *tabs):
+ "inserts Orcfunction tables using Ftable objects"
+ for t in tabs:
+ self.ftabs.append(t)
+ def insertChannels(self, *OrcChans):
+ "inserts a Orcchannel objects into a Csound orc"
+ for c in OrcChans:
+ self.chans.append(c)
+ def appendInstruments(self, *CsIns):
+ for i in CsIns:
+ self.instruments.append(i)
+ def prependInstrument(self, CsIns):
+ "inserts an instrument at the front of the orchestra"
+ self.instruments.insert(0, CsIns)
+ def exportOrc(self):
+ self.insertInsnums(self.instruments)
+ header = [x+y for x,y in zip(['sr = ', 'ksmps = ', 'nchnls = ', '0dbfs = '], map(str,[self.sr, self.ksmps, self.nchnls, self.dbfs]))]
+ insnums = self.macros
+ ftabs = map(str, self.ftabs)
+ lines = map(str, self.csline)
+ chans = map(str, self.chans)
+ Ins = map(str, self.instruments)
+ result = header + insnums + ftabs + chans + lines + Ins
+ return '\n'.join(result)
+ def __repr__(self):
+ return "CSound orchestra object" + str(self.__dict__)
+
+class sndInfo:
+ def __init__(self, path, *csd):
+ "query information of an audio file at path. csd is a precompiled csound instance"
+ if len(csd) == 0:
+ cs = Csound()
+ self.cs = Csound.csound
+ else: self.cs = csd[0] #can pass a precompiled csound as an argument
+ self.contents = ''
+ args = csnd.CsoundArgVList()
+ args.Append('sndinfo')
+ args.Append('-i')
+ args.Append(path)
+ old_stdout = sys.stdout
+ sys.stdout = self
+ err = self.cs.RunUtility('sndinfo', args.argc(), args.argv())
+ sys.stdout = old_stdout
+ self._lines()
+ header = [l for l in self.lines if l.__contains__('\tsrate')]
+ self.header = header[0].split(',')
+ def write(self, c):
+ self.contents += c
+ def _lines(self):
+ self.lines = self.contents.splitlines()
+ def sr(self):
+ srl = [c for c in self.header[0] if c.isdigit()]
+ return int(''.join(srl))
+ def chans(self):
+ if self.header[1].__contains__('monaural'):
+ return 1
+ else: return 2
+ def type(self):
+ return self.header[2]
+ def duration(self):
+ s = self.header[3]
+ return float(''.join([n for n in s if n.isdigit() or n == '.']))
+ def findNoteAttribute(self, attr):
+ result = 0
+ for i in self.lines:
+ if i.startswith(attr, 2):
+ result = int(''.join([n for n in i if n.isdigit()]))
+ return result
+ def BaseNote(self):
+ "return the Base Note"
+ return self.findNoteAttribute('Base')
+
+def orcLoadSamples(orc, Cs, fnlookupname, *paths):
+ "Inserts Gen1 ftables for samples located in paths, and an associated GEN17 midi pitch lookup table based on base pitch in soundfile into orc"
+ sfns = []
+ for p in paths:
+ for f in ResourceList(p,'.aif'):
+ snd = sndInfo(p+'/'+f, Cs.csound)
+ bn = snd.BaseNote()
+ fn = FtableSample(p+'/'+f, bn)
+ orc.insertftables(fn)
+ sfns.append(fn)
+ flookup = FtableLookup(fnlookupname, 0.3, *sfns)
+ orc.insertftables(flookup)
+ return flookup
+
+if __name__ == '__main__':
+ print "running OrcBuilder as __main__"
+
+ from CsSched import *
+ Csynth = Csound()
+ TimeQueue = Sched()
+
+ #Create a csound orchestra
+ orc = OrcConstructor()
+ orc.sr = 22050
+ orc.ksmps = 256
+
+ #Function tables
+ lookuptabs = [orcLoadSamples(orc, Csynth, instr+"Lookup", eval(instr+"AudioPath")) for instr in INAMES]
+ ftabs = [FtableBreakPoint("rvbc1", -558, -594, -638, -678, -711, -745, -778, -808, 0.8, 0.79, 0.78, 0.77, 0.76, 0.75, 0.74, 0.73),
+ FtableBreakPoint("rvbc2", -517, -540, -656, -699, -752, -799, -818, -841, 0.8, 0.79, 0.78, 0.77, 0.76, 0.75, 0.74, 0.73),
+ FtableBreakPoint("rvba1", -278, -220, -170, -122, 0.4, 0.52, 0.64, 0.76),
+ FtableBreakPoint("rvba2", -333, -263, -166, -105, 0.5, 0.52, 0.64, 0.76)]
+ orc.insertftables(*ftabs)
+
+ #Control Channels: Should conform to the Parameter naming convention already in use.
+ volumechans = orcChannelMaker(INAMES, "Volume")
+ timbrechans = orcChannelMaker(INAMES, "Timbre", init = 0.5)
+ orc.insertChannels(*volumechans)
+ orc.insertChannels(*timbrechans)
+ #timbrechans[0].varname()
+
+ #Instruments
+ #first, establish a setlevel instrument
+ setlevels = OrcSetLevelInstrument()
+ setlevels.effect = True
+ #then work backwards.
+ #A mixer:
+ mixerout = OrcMixoutInstrument()
+ mixerout.effect = True
+
+ #sampler instruments
+ samplerbody = """
+ idur = p3
+ iamp = p4 * (0dbfs / 127)
+ kcps init cpsmidinn(p5)
+ isamp table p5, %s
+ a1 loscil iamp, kcps, isamp
+ a1 dcblock a1
+ kdeclick linseg 0, 0.001, 1, idur - 0.03 - 0.001, 1, 0.03, 0
+ a1 = a1 * kdeclick
+ """
+ #timbre instruments
+ #be aware that samplerates lower than 22050 tend to blow up the rezzy filter
+ #at this level of resonance.
+ timbrebody = ("""
+ idur = p3
+ ires = 4.75
+ kfco expcurve %s, 14
+ kfco = kfco * """ + str(orc.sr*0.5 * 0.65 + 200) + """
+
+ a1 rezzy a1, kfco, ires
+ """)
+
+ SamplerInstruments, TimbreInstruments = [OrcInstrument(i+'Sampler') for i in INAMES], [OrcInstrument(i+'Timbre') for i in INAMES]
+
+ #it would be nice to abstract this one, but it's quite complex. Maybe later.
+ for Si, Ti in zip(SamplerInstruments, TimbreInstruments):
+ Si.insertLine(samplerbody % [x for x in [n.varname() for n in lookuptabs] if x.__contains__(Si.name[:-7])][0])
+ Ti.insertLine(timbrebody % [y for y in [j.varname() for j in timbrechans] if y.__contains__(Ti.name[:-6])][0])
+ Si.routeOut('a1', Ti, setlevels)
+ Ti.routeOut('a1', mixerout, setlevels)
+ Ti.routeIn('a1')
+ Ti.effect = True
+ orc.appendInstruments(Si, Ti)
+
+
+ #finally, add the mixer and level instruments
+ orc.appendInstruments(mixerout)
+ orc.prependInstrument(setlevels)
+ #get numbers from names:
+ #orc.nameNumber['BassSampler']
+ print orc.exportOrc()
+
diff --git a/City/Parameters.py b/City/Parameters.py
new file mode 100755
index 0000000..000405e
--- /dev/null
+++ b/City/Parameters.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+"""Describes an object for storing parameter values.
+All Controllers should write to this object.
+All Readers should read from the object"""
+
+import random
+from CsHelpers import * #import global names and functions
+
+class Instrument():
+ def __init__(self, name, x = 0, y = 0, w = 0, h = 0):
+ self.name = name
+ self.lastRect = pygame.Rect(x,y,w,h)
+ self.Rect = pygame.Rect(x,y,w,h)
+ self.image = None
+ self.active_image = None
+ self.inactive_image = None
+ self.Touch = False
+ self.active = False
+ def loadImage(self, path, *scale):
+ img = pygame.image.load(path)
+ if scale:
+ img = pygame.transform.scale(img, (img.get_width() * scale[0], img.get_height() * scale[-1]))
+ img = img.convert_alpha()
+ self.active_image = img
+ self.Rect.size = img.get_size()
+ self.lastRect.size = img.get_size()
+ imgcopy = self.active_image.copy()
+ imgcopy.fill((255,5,55) , None, pygame.BLEND_MIN)
+ imgcopy.fill((75,75,75) , None, pygame.BLEND_ADD)
+ self.inactive_image = imgcopy
+ self.deactivate()
+ def activate(self):
+ self.image = self.active_image
+ self.active = True
+ self.Touch = True
+ def deactivate(self):
+ self.image = self.inactive_image
+ self.active = False
+ self.Touch = True
+ def x(self):
+ return self.Rect[0]
+ def y(self):
+ return self.Rect[1]
+ def lastCtr(self):
+ return self.lastRect.center
+ def ctr(self):
+ return self.Rect.center
+ def __setattr__(self, attr, value):
+ if attr == 'x':
+ self.lastRect[0] = self.Rect[0]
+ self.Rect[0] = value
+ self.Touch = True
+ elif attr == 'y':
+ self.lastRect[1] = self.Rect[1]
+ self.Rect[1] = value
+ self.Touch = True
+ elif attr == 'ctr':
+ self.lastRect[0] = self.Rect[0]
+ self.lastRect[1] = self.Rect[1]
+ self.Rect.center = value
+ self.Touch = True
+ else:
+ self.__dict__[attr] = value
+ def __repr__(self):
+ return ''.join(map(str, [self.name, " Instrument at location ", (self.x(), self.y())]))
+
+
+class Parameter():
+ def __init__(self, name):
+ self.name = name
+ self.Instrumentvalues = [[Instrument(ins), 0.5] for ins in INAMES]
+ self.state = False
+ self.active = False
+ self.correspondant = None
+ def getValue(self, insname):
+ for ndx in range(len(self.Instrumentvalues)):
+ if self.Instrumentvalues[ndx][0].name == insname:
+ return self.Instrumentvalues[ndx][1]
+ def setValue(self, ins, val):
+ ndx = [i[0].name for i in self.Instrumentvalues].index(ins)
+ self.Instrumentvalues[ndx][1] = val
+ def __repr__(self):
+ return self.name
+
+class Perimeter():
+ def __init__(self):
+ self.data = {}
+ for n in PNAMES:
+ self.data[n] = Parameter(n)
+ csoundChannels = []
+ def csoundChannels(self, cs):
+ self.csound = cs
+ self.csoundChannels = cs.Channels
+ def getValue(self, name, instrument):
+ return self.data[name].getValue(instrument)
+ def setValue(self, name, instrument, value):
+ if name == 'Tempo':
+ for i in self.data['Tempo'].Instrumentvalues:
+ i[1] = value
+ else:
+ self.data[name].setValue(instrument, value)
+ namelen = len(name)
+ if len(self.csoundChannels) > 0:
+ for ch in self.csoundChannels:
+ param = ch.name[-namelen:]
+ if param == name:
+ ins = ch.name[:-len(param)]
+ if (ins == instrument and
+ (ch.direction == "input" or "bidirectional") and
+ ch.type == "Control"):
+ self.csound.setChannelValue(ch.name, value)
+ def getPlist(self):
+ "returns a list of all parameters"
+ return self.data.values()
+ def getPdict(self):
+ return self.data
+
+
+if __name__ == '__main__':
+ P = Perimeter()
+ print "Value for Drum density is :", P.getValue('Density', 'Drums')
+ print "setting new value"
+ P.setValue('Density', 'Drums', 0.75)
+ print "Value for Drum density is :", P.getValue('Density', 'Drums')
+ c = check(P)
+ c.setp(0.9)
+ c.getp()
+
diff --git a/City/Scenes/Blues/AudioFiles/BassAudio/BassC2[41-48-50].aif b/City/Scenes/Blues/AudioFiles/BassAudio/BassC2[41-48-50].aif
new file mode 100644
index 0000000..3e3fd98
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/BassAudio/BassC2[41-48-50].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/BassAudio/BassC3[59-60-62].aif b/City/Scenes/Blues/AudioFiles/BassAudio/BassC3[59-60-62].aif
new file mode 100644
index 0000000..bd3ab7f
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/BassAudio/BassC3[59-60-62].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/BassAudio/BassC4[70-72-78].aif b/City/Scenes/Blues/AudioFiles/BassAudio/BassC4[70-72-78].aif
new file mode 100644
index 0000000..f9ec61b
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/BassAudio/BassC4[70-72-78].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/BassAudio/BassF#2[51-54-58].aif b/City/Scenes/Blues/AudioFiles/BassAudio/BassF#2[51-54-58].aif
new file mode 100644
index 0000000..c099d56
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/BassAudio/BassF#2[51-54-58].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
new file mode 100644
index 0000000..475ac71
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
new file mode 100644
index 0000000..f89023c
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
new file mode 100644
index 0000000..fd1a6c5
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
new file mode 100644
index 0000000..b4d5964
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/DrumsAudio/C1_kick_drum.aif b/City/Scenes/Blues/AudioFiles/DrumsAudio/C1_kick_drum.aif
new file mode 100644
index 0000000..cedbae3
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/DrumsAudio/C1_kick_drum.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/DrumsAudio/D1_snare_drum.aif b/City/Scenes/Blues/AudioFiles/DrumsAudio/D1_snare_drum.aif
new file mode 100644
index 0000000..4ff68d0
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/DrumsAudio/D1_snare_drum.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif b/City/Scenes/Blues/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif
new file mode 100644
index 0000000..ef60aac
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/DrumsAudio/Tamborine 22 16 Mono.aif b/City/Scenes/Blues/AudioFiles/DrumsAudio/Tamborine 22 16 Mono.aif
new file mode 100644
index 0000000..6b6f85f
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/DrumsAudio/Tamborine 22 16 Mono.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/B2_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/B2_guitar.aif
new file mode 100644
index 0000000..9a06c2f
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/B2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/B3_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/B3_guitar.aif
new file mode 100644
index 0000000..a229b76
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/B3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/E2_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/E2_guitar.aif
new file mode 100644
index 0000000..0df7f1e
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/E2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/E3_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/E3_guitar.aif
new file mode 100644
index 0000000..e8f5be5
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/E3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/E4_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/E4_guitar.aif
new file mode 100644
index 0000000..9909889
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/E4_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/AudioFiles/LeadAudio/E5_guitar.aif b/City/Scenes/Blues/AudioFiles/LeadAudio/E5_guitar.aif
new file mode 100644
index 0000000..f1f7076
--- /dev/null
+++ b/City/Scenes/Blues/AudioFiles/LeadAudio/E5_guitar.aif
Binary files differ
diff --git a/City/Scenes/Blues/Blues_Data.txt b/City/Scenes/Blues/Blues_Data.txt
new file mode 100644
index 0000000..6542e85
--- /dev/null
+++ b/City/Scenes/Blues/Blues_Data.txt
@@ -0,0 +1,4 @@
+Tempo = 65
+Key = E
+Mode = minor
+
diff --git a/City/Scenes/Blues/MidiFiles/Bass.mid b/City/Scenes/Blues/MidiFiles/Bass.mid
new file mode 100644
index 0000000..16967a5
--- /dev/null
+++ b/City/Scenes/Blues/MidiFiles/Bass.mid
Binary files differ
diff --git a/City/Scenes/Blues/MidiFiles/Chords.mid b/City/Scenes/Blues/MidiFiles/Chords.mid
new file mode 100644
index 0000000..139be9d
--- /dev/null
+++ b/City/Scenes/Blues/MidiFiles/Chords.mid
Binary files differ
diff --git a/City/Scenes/Blues/MidiFiles/Drums.mid b/City/Scenes/Blues/MidiFiles/Drums.mid
new file mode 100644
index 0000000..576167d
--- /dev/null
+++ b/City/Scenes/Blues/MidiFiles/Drums.mid
Binary files differ
diff --git a/City/Scenes/Blues/MidiFiles/Lead.mid b/City/Scenes/Blues/MidiFiles/Lead.mid
new file mode 100644
index 0000000..b7636d6
--- /dev/null
+++ b/City/Scenes/Blues/MidiFiles/Lead.mid
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[28-36-39]mn_000.aif b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[28-36-39]mn_000.aif
new file mode 100755
index 0000000..e221a95
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[28-36-39]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[40-48-51]mn_000.aif b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[40-48-51]mn_000.aif
new file mode 100755
index 0000000..24e322b
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[40-48-51]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[52-60-63]mn_000.aif b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[52-60-63]mn_000.aif
new file mode 100755
index 0000000..e1d53b1
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/BassAudio/Dance1Bass[52-60-63]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[100-108-111]mn_000.aif b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[100-108-111]mn_000.aif
new file mode 100755
index 0000000..6e23d16
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[100-108-111]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[64-72-75]mn_000.aif b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[64-72-75]mn_000.aif
new file mode 100755
index 0000000..74cf041
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[64-72-75]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[76-84-87]mn_000.aif b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[76-84-87]mn_000.aif
new file mode 100755
index 0000000..f8bf860
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[76-84-87]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[88-96-99]mn_000.aif b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[88-96-99]mn_000.aif
new file mode 100755
index 0000000..ce5fb0b
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/ChordsAudio/Dance1Pad[88-96-99]mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909kick7[36-36-36].aif b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909kick7[36-36-36].aif
new file mode 100755
index 0000000..e4cce2d
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909kick7[36-36-36].aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909snare3[38-38-38].aif b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909snare3[38-38-38].aif
new file mode 100755
index 0000000..1107cc5
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1909snare3[38-38-38].aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/DrumsAudio/Dance1SHAKER_1[46-46-46].aif b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1SHAKER_1[46-46-46].aif
new file mode 100755
index 0000000..fb698d7
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1SHAKER_1[46-46-46].aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/DrumsAudio/Dance1closedhat11[39-39-39].aif b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1closedhat11[39-39-39].aif
new file mode 100755
index 0000000..9754819
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1closedhat11[39-39-39].aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/DrumsAudio/Dance1openedhat4[42-42-42].aif b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1openedhat4[42-42-42].aif
new file mode 100755
index 0000000..ee4a48a
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/DrumsAudio/Dance1openedhat4[42-42-42].aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[28-36-39]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[28-36-39]_001_001mn_000.aif
new file mode 100755
index 0000000..79724da
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[28-36-39]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[40-48-51]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[40-48-51]_001_001mn_000.aif
new file mode 100755
index 0000000..5f204a5
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[40-48-51]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[52-60-63]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[52-60-63]_001_001mn_000.aif
new file mode 100755
index 0000000..ed4257e
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[52-60-63]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[64-72-75]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[64-72-75]_001_001mn_000.aif
new file mode 100755
index 0000000..d1bd254
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[64-72-75]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[76-84-87]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[76-84-87]_001_001mn_000.aif
new file mode 100755
index 0000000..27ef6f3
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[76-84-87]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/AudioFiles/LeadAudio/keys-good[88-96-99]_001_001mn_000.aif b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[88-96-99]_001_001mn_000.aif
new file mode 100755
index 0000000..50d5b10
--- /dev/null
+++ b/City/Scenes/City/AudioFiles/LeadAudio/keys-good[88-96-99]_001_001mn_000.aif
Binary files differ
diff --git a/City/Scenes/City/City_Data.txt b/City/Scenes/City/City_Data.txt
new file mode 100644
index 0000000..525850e
--- /dev/null
+++ b/City/Scenes/City/City_Data.txt
@@ -0,0 +1,8 @@
+Tempo = 120
+Key = A
+Mode = minor
+Volume = 1
+Pitch = 0.6
+Timbre = 0.7
+
+
diff --git a/City/Scenes/City/MidiFiles/Bass.mid b/City/Scenes/City/MidiFiles/Bass.mid
new file mode 100755
index 0000000..9cf6010
--- /dev/null
+++ b/City/Scenes/City/MidiFiles/Bass.mid
Binary files differ
diff --git a/City/Scenes/City/MidiFiles/Chords.mid b/City/Scenes/City/MidiFiles/Chords.mid
new file mode 100755
index 0000000..7fac8ce
--- /dev/null
+++ b/City/Scenes/City/MidiFiles/Chords.mid
Binary files differ
diff --git a/City/Scenes/City/MidiFiles/Drums.mid b/City/Scenes/City/MidiFiles/Drums.mid
new file mode 100755
index 0000000..ea7a047
--- /dev/null
+++ b/City/Scenes/City/MidiFiles/Drums.mid
Binary files differ
diff --git a/City/Scenes/City/MidiFiles/Lead.mid b/City/Scenes/City/MidiFiles/Lead.mid
new file mode 100755
index 0000000..206f2ea
--- /dev/null
+++ b/City/Scenes/City/MidiFiles/Lead.mid
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/BassAudio/BassC2[41-48-50].aif b/City/Scenes/Country/AudioFiles/BassAudio/BassC2[41-48-50].aif
new file mode 100644
index 0000000..3e3fd98
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/BassAudio/BassC2[41-48-50].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/BassAudio/BassC3[59-60-62].aif b/City/Scenes/Country/AudioFiles/BassAudio/BassC3[59-60-62].aif
new file mode 100644
index 0000000..bd3ab7f
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/BassAudio/BassC3[59-60-62].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/BassAudio/BassC4[70-72-78].aif b/City/Scenes/Country/AudioFiles/BassAudio/BassC4[70-72-78].aif
new file mode 100644
index 0000000..f9ec61b
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/BassAudio/BassC4[70-72-78].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/BassAudio/BassF#2[51-54-58].aif b/City/Scenes/Country/AudioFiles/BassAudio/BassF#2[51-54-58].aif
new file mode 100644
index 0000000..c099d56
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/BassAudio/BassF#2[51-54-58].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
new file mode 100644
index 0000000..475ac71
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
new file mode 100644
index 0000000..f89023c
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
new file mode 100644
index 0000000..fd1a6c5
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
new file mode 100644
index 0000000..b4d5964
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/DrumsAudio/C#1_rim_shot.aif b/City/Scenes/Country/AudioFiles/DrumsAudio/C#1_rim_shot.aif
new file mode 100755
index 0000000..beea298
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/DrumsAudio/C#1_rim_shot.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/DrumsAudio/C1_kick_drum.aif b/City/Scenes/Country/AudioFiles/DrumsAudio/C1_kick_drum.aif
new file mode 100644
index 0000000..2b00005
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/DrumsAudio/C1_kick_drum.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/DrumsAudio/D1_snare_drum.aif b/City/Scenes/Country/AudioFiles/DrumsAudio/D1_snare_drum.aif
new file mode 100755
index 0000000..cee687f
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/DrumsAudio/D1_snare_drum.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif b/City/Scenes/Country/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif
new file mode 100755
index 0000000..543d2e6
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/DrumsAudio/F#1_closed_hi_hat.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/B2_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/B2_guitar.aif
new file mode 100644
index 0000000..9a06c2f
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/B2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/B3_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/B3_guitar.aif
new file mode 100644
index 0000000..a229b76
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/B3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/E2_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/E2_guitar.aif
new file mode 100644
index 0000000..0df7f1e
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/E2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/E3_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/E3_guitar.aif
new file mode 100644
index 0000000..e8f5be5
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/E3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/E4_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/E4_guitar.aif
new file mode 100644
index 0000000..9909889
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/E4_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/AudioFiles/LeadAudio/E5_guitar.aif b/City/Scenes/Country/AudioFiles/LeadAudio/E5_guitar.aif
new file mode 100644
index 0000000..f1f7076
--- /dev/null
+++ b/City/Scenes/Country/AudioFiles/LeadAudio/E5_guitar.aif
Binary files differ
diff --git a/City/Scenes/Country/Country_Data.txt b/City/Scenes/Country/Country_Data.txt
new file mode 100644
index 0000000..4dcdc4e
--- /dev/null
+++ b/City/Scenes/Country/Country_Data.txt
@@ -0,0 +1,5 @@
+Tempo = 120
+Key = E
+Mode = major
+
+
diff --git a/City/Scenes/Country/MidiFiles/Bass.mid b/City/Scenes/Country/MidiFiles/Bass.mid
new file mode 100755
index 0000000..335ce31
--- /dev/null
+++ b/City/Scenes/Country/MidiFiles/Bass.mid
Binary files differ
diff --git a/City/Scenes/Country/MidiFiles/Chords.mid b/City/Scenes/Country/MidiFiles/Chords.mid
new file mode 100755
index 0000000..9b2b819
--- /dev/null
+++ b/City/Scenes/Country/MidiFiles/Chords.mid
Binary files differ
diff --git a/City/Scenes/Country/MidiFiles/Drums.mid b/City/Scenes/Country/MidiFiles/Drums.mid
new file mode 100755
index 0000000..1457736
--- /dev/null
+++ b/City/Scenes/Country/MidiFiles/Drums.mid
Binary files differ
diff --git a/City/Scenes/Country/MidiFiles/Lead.mid b/City/Scenes/Country/MidiFiles/Lead.mid
new file mode 100755
index 0000000..52b61fd
--- /dev/null
+++ b/City/Scenes/Country/MidiFiles/Lead.mid
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/BassAudio/BassC2[41-48-50].aif b/City/Scenes/Latin/AudioFiles/BassAudio/BassC2[41-48-50].aif
new file mode 100644
index 0000000..f510c60
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/BassAudio/BassC2[41-48-50].aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/BassAudio/BassC3[59-60-62].aif b/City/Scenes/Latin/AudioFiles/BassAudio/BassC3[59-60-62].aif
new file mode 100644
index 0000000..e1c38ad
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/BassAudio/BassC3[59-60-62].aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/BassAudio/BassC4[70-72-78].aif b/City/Scenes/Latin/AudioFiles/BassAudio/BassC4[70-72-78].aif
new file mode 100644
index 0000000..1c3d78d
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/BassAudio/BassC4[70-72-78].aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/BassAudio/BassF#2[51-54-58].aif b/City/Scenes/Latin/AudioFiles/BassAudio/BassF#2[51-54-58].aif
new file mode 100644
index 0000000..ab7abe4
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/BassAudio/BassF#2[51-54-58].aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C4 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C4 22 16 mono.aif
new file mode 100644
index 0000000..28f851c
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C4 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C5 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C5 22 16 mono.aif
new file mode 100644
index 0000000..58d58e2
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ C5 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G3 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G3 22 16 mono.aif
new file mode 100644
index 0000000..d4a8320
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G3 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G4 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G4 22 16 mono.aif
new file mode 100644
index 0000000..6aad12c
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/ChordsAudio/Organ G4 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C#3 22 16 Mono.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C#3 22 16 Mono.aif
new file mode 100644
index 0000000..d63f7c1
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C#3 22 16 Mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C3 22 16 Mono.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C3 22 16 Mono.aif
new file mode 100644
index 0000000..546e609
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo C3 22 16 Mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo D3 22 16 Mono.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo D3 22 16 Mono.aif
new file mode 100644
index 0000000..e947c9a
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Bongo D3 22 16 Mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/ClosedhatF#1.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/ClosedhatF#1.aif
new file mode 100644
index 0000000..f170804
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/ClosedhatF#1.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Kick-C1.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Kick-C1.aif
new file mode 100644
index 0000000..7204bf6
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Kick-C1.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Shaker 22 16 Mono.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Shaker 22 16 Mono.aif
new file mode 100644
index 0000000..cb70adf
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Shaker 22 16 Mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/Snare-D1.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/Snare-D1.aif
new file mode 100644
index 0000000..de03f64
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/Snare-D1.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/DrumsAudio/TambF#2.aif b/City/Scenes/Latin/AudioFiles/DrumsAudio/TambF#2.aif
new file mode 100644
index 0000000..0eb9de9
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/DrumsAudio/TambF#2.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets A4 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets A4 22 16 mono.aif
new file mode 100644
index 0000000..df3c59a
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets A4 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets C4 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets C4 22 16 mono.aif
new file mode 100644
index 0000000..918da75
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets C4 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets E3 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets E3 22 16 mono.aif
new file mode 100644
index 0000000..7f8ffd9
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets E3 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets F4 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets F4 22 16 mono.aif
new file mode 100644
index 0000000..9e5bb5f
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets F4 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets G3 22 16 mono.aif b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets G3 22 16 mono.aif
new file mode 100644
index 0000000..15f0639
--- /dev/null
+++ b/City/Scenes/Latin/AudioFiles/LeadAudio/Trumpets G3 22 16 mono.aif
Binary files differ
diff --git a/City/Scenes/Latin/Latin_Data.txt b/City/Scenes/Latin/Latin_Data.txt
new file mode 100644
index 0000000..b9f739c
--- /dev/null
+++ b/City/Scenes/Latin/Latin_Data.txt
@@ -0,0 +1,3 @@
+Tempo = 164
+Key = F
+Mode = major
diff --git a/City/Scenes/Latin/MidiFiles/Bass.mid b/City/Scenes/Latin/MidiFiles/Bass.mid
new file mode 100644
index 0000000..cbc12a4
--- /dev/null
+++ b/City/Scenes/Latin/MidiFiles/Bass.mid
Binary files differ
diff --git a/City/Scenes/Latin/MidiFiles/Chords.mid b/City/Scenes/Latin/MidiFiles/Chords.mid
new file mode 100644
index 0000000..d27fb73
--- /dev/null
+++ b/City/Scenes/Latin/MidiFiles/Chords.mid
Binary files differ
diff --git a/City/Scenes/Latin/MidiFiles/Drums.mid b/City/Scenes/Latin/MidiFiles/Drums.mid
new file mode 100644
index 0000000..4ab7c9c
--- /dev/null
+++ b/City/Scenes/Latin/MidiFiles/Drums.mid
Binary files differ
diff --git a/City/Scenes/Latin/MidiFiles/Lead.mid b/City/Scenes/Latin/MidiFiles/Lead.mid
new file mode 100644
index 0000000..407d400
--- /dev/null
+++ b/City/Scenes/Latin/MidiFiles/Lead.mid
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/BassAudio/BassC2[41-48-50].aif b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC2[41-48-50].aif
new file mode 100644
index 0000000..3e3fd98
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC2[41-48-50].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/BassAudio/BassC3[59-60-62].aif b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC3[59-60-62].aif
new file mode 100644
index 0000000..bd3ab7f
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC3[59-60-62].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/BassAudio/BassC4[70-72-78].aif b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC4[70-72-78].aif
new file mode 100644
index 0000000..f9ec61b
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/BassAudio/BassC4[70-72-78].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/BassAudio/BassF#2[51-54-58].aif b/City/Scenes/Reggae/AudioFiles/BassAudio/BassF#2[51-54-58].aif
new file mode 100644
index 0000000..c099d56
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/BassAudio/BassF#2[51-54-58].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
new file mode 100644
index 0000000..475ac71
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC4[70-72-73].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
new file mode 100644
index 0000000..f89023c
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoC5[82-84-90].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
new file mode 100644
index 0000000..fd1a6c5
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE3[63-64-65].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
new file mode 100644
index 0000000..b4d5964
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/ChordsAudio/epnoE4[74-76-77].aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/DrumsAudio/ClosedhatF#1.aif b/City/Scenes/Reggae/AudioFiles/DrumsAudio/ClosedhatF#1.aif
new file mode 100644
index 0000000..f170804
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/DrumsAudio/ClosedhatF#1.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/DrumsAudio/Kick-C1.aif b/City/Scenes/Reggae/AudioFiles/DrumsAudio/Kick-C1.aif
new file mode 100644
index 0000000..7204bf6
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/DrumsAudio/Kick-C1.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/DrumsAudio/OpenhatA#1.aif b/City/Scenes/Reggae/AudioFiles/DrumsAudio/OpenhatA#1.aif
new file mode 100644
index 0000000..4f5f0b4
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/DrumsAudio/OpenhatA#1.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/DrumsAudio/Snare-D1.aif b/City/Scenes/Reggae/AudioFiles/DrumsAudio/Snare-D1.aif
new file mode 100644
index 0000000..de03f64
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/DrumsAudio/Snare-D1.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/DrumsAudio/TambF#2.aif b/City/Scenes/Reggae/AudioFiles/DrumsAudio/TambF#2.aif
new file mode 100644
index 0000000..0eb9de9
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/DrumsAudio/TambF#2.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/B2_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/B2_guitar.aif
new file mode 100644
index 0000000..9a06c2f
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/B2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/B3_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/B3_guitar.aif
new file mode 100644
index 0000000..a229b76
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/B3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/E2_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/E2_guitar.aif
new file mode 100644
index 0000000..0df7f1e
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/E2_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/E3_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/E3_guitar.aif
new file mode 100644
index 0000000..e8f5be5
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/E3_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/E4_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/E4_guitar.aif
new file mode 100644
index 0000000..9909889
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/E4_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/AudioFiles/LeadAudio/E5_guitar.aif b/City/Scenes/Reggae/AudioFiles/LeadAudio/E5_guitar.aif
new file mode 100644
index 0000000..f1f7076
--- /dev/null
+++ b/City/Scenes/Reggae/AudioFiles/LeadAudio/E5_guitar.aif
Binary files differ
diff --git a/City/Scenes/Reggae/MidiFiles/Bass.mid b/City/Scenes/Reggae/MidiFiles/Bass.mid
new file mode 100644
index 0000000..be414ec
--- /dev/null
+++ b/City/Scenes/Reggae/MidiFiles/Bass.mid
Binary files differ
diff --git a/City/Scenes/Reggae/MidiFiles/Chords.mid b/City/Scenes/Reggae/MidiFiles/Chords.mid
new file mode 100644
index 0000000..1feebaa
--- /dev/null
+++ b/City/Scenes/Reggae/MidiFiles/Chords.mid
Binary files differ
diff --git a/City/Scenes/Reggae/MidiFiles/Drums.mid b/City/Scenes/Reggae/MidiFiles/Drums.mid
new file mode 100644
index 0000000..bf2f5be
--- /dev/null
+++ b/City/Scenes/Reggae/MidiFiles/Drums.mid
Binary files differ
diff --git a/City/Scenes/Reggae/MidiFiles/Lead.mid b/City/Scenes/Reggae/MidiFiles/Lead.mid
new file mode 100644
index 0000000..2a0d2be
--- /dev/null
+++ b/City/Scenes/Reggae/MidiFiles/Lead.mid
Binary files differ
diff --git a/City/Scenes/Reggae/Reggae_Data.txt b/City/Scenes/Reggae/Reggae_Data.txt
new file mode 100644
index 0000000..cc23d84
--- /dev/null
+++ b/City/Scenes/Reggae/Reggae_Data.txt
@@ -0,0 +1,3 @@
+Tempo = 164
+Key = G
+Mode = major
diff --git a/City/Tracks.py b/City/Tracks.py
new file mode 100755
index 0000000..de9e3d9
--- /dev/null
+++ b/City/Tracks.py
@@ -0,0 +1,512 @@
+#!/usr/bin/env python
+"""
+This module defines Notes, Scores, Beats and Players and a convenience class for midi file parsing.
+TEST THIS PLAYER!
+"""
+
+#Note has no instrument number
+#This is determined by the Track
+ONSETINDEX = 0
+DURINDEX = 1
+VELINDEX = 2
+PITINDEX = 3
+
+
+import bisect, random, math, logging, thread
+from midiImport import *
+from CsHelpers import *
+
+log = logging.getLogger( 'City run' )
+log.setLevel( logging.DEBUG )
+
+
+class Note:
+ def __init__(self, note = [0,0,0,0]):
+ self.data = note[:]
+ self.index = 0
+ def __repr__(self):
+ return 'Note: '+' '.join(map(str,(self.data)))
+ def __getitem__(self,index):
+ return self.data[index]
+ def __setitem__(self,index, value):
+ self.data[index] = value
+ def __getslice__(self,a,b):
+ return self.data[a:b]
+ def __len__(self):
+ return len(self.data)
+ def onset(self):
+ return self[ONSETINDEX]
+ def duration(self):
+ return self[DURINDEX]
+ def velocity(self):
+ return self[VELINDEX]
+ def pitch(self):
+ return self[PITINDEX]
+ def setOnset(self, val):
+ self[ONSETINDEX] = val
+ def setDuration(self, val):
+ self[DURINDEX] = val
+ def setVelocity(self, val):
+ self[VELINDEX] = val
+ def setPitch(self, val):
+ self[PITINDEX] = val
+ def offTime(self):
+ return self.duration() + self.onset()
+
+
+class Track:
+ def __init__(self, data = []):
+ "A Track can be initialised with a list of notes"
+ self.data = data[:]
+ self.index = 0
+ self.instrument = 1
+ def setInstrument(self, num):
+ self.instrument = num
+ def addNote(self, note):
+ index = bisect.bisect_left(self.data, [note[ONSETINDEX]])
+ self.data.insert(index, note)
+ def __delitem__(self, index):
+ del(self.data[index])
+ def __getitem__(self, index):
+ if len(self) == 0:
+ return False
+ else:
+ return self.data[index]
+ def __getslice__(self, a,b):
+ return Track(self.data[a:b])
+ def __len__(self):
+ return len(self.data)
+ def resetIterator(self, ndx = 0):
+ self.index = ndx
+ def findNoteAtTime(self, time):
+ return bisect.bisect_left([n.data for n in self.data], [time])
+ def getNoteAtTime(self, time):
+ return self.data[self.findNoteAtTime(time)]
+ def getParameter(self, ndx):
+ return [i[ndx] for i in self.data]
+ def getOnsets(self):
+ return self.getParameter(ONSETINDEX)
+ def getDurations(self):
+ return self.getParameter(DURINDEX)
+ def getVelocities(self):
+ return self.getParameter(VELINDEX)
+ def getPitches(self):
+ return self.getParameter(PITINDEX)
+ def modParameter(self, pndx, mult):
+ "a bit of a hack, while I try and work out tempo"
+ for n in self:
+ n[pndx] *= mult
+ def __repr__(self):
+ return 'Track :' + str(self.data)
+
+
+class Beat(Track):
+ def __init__(self, beatnum, offset = 0, data = Track()):
+ "Beat can be initialised with an existing track. The track is automatically sliced"
+ self.data = data.data[:]
+ self.index = 0
+ self.instrument = 1
+ self.offset = offset
+ self.beatnum = beatnum
+ def setBeatNum(self, beatnum):
+ self.beatnum = beatnum
+ def setOffset(self, beatnum):
+ self.offset = offset
+ def nudgeParameter(self, parameter, shiftAmount):
+ "returns a new beat with onsets shifted by shiftAmount"
+ newbeat = Beat(self.beatnum)
+ for i in self.data:
+ newp = i[parameter] + shiftAmount
+ newl = []
+ for p in range(len(i)):
+ if p == parameter:
+ newl.append(newp)
+ else: newl.append(i[p])
+ newNote = Note(newl)
+ newbeat.addNote(newNote)
+ return newbeat
+ def relativeOnsets(self, start = 0):
+ shift = -self[0].onset() - self.offset
+ return self.nudgeParameter(ONSETINDEX, shift + start)
+ def __repr__(self):
+ return 'Beat ' + str(self.beatnum) + ':' + str(self.data)
+
+def beat(track, time, beatlen, beatnum):
+ "beat function extracts a beat object from a track, and assigns it a 'beat' number"
+ ndx = track.findNoteAtTime(time)
+ result = Beat(beatnum)
+ if ndx >= len(track): return result
+ timeOffset = track[ndx].onset() - time
+ if timeOffset > beatlen:
+ return result
+ else:
+ for n in track[ndx: ]:
+ if n.onset() < track[ndx].onset() + beatlen:
+ result.addNote(n)
+ else: break
+ return result
+
+class Midi2Score:
+ def __init__(self, path):
+ midiData = MidiFile()
+ midiData.open(path)
+ midiData.read()
+ midiData.close()
+ self.midiData = midiData
+ self.ticksPerBeat = midiData.ticksPerQuarterNote
+ def numTracks(self):
+ return len(self.midiData.tracks)
+ def getTrack(self, ndx):
+ return self.midiData.tracks[ndx]
+ def time2beats(self,time):
+ return float(time) / self.ticksPerBeat
+ def findNO(self, noff, nlst):
+ pitlst = [n.pitch() for n in reversed(nlst)]
+ return (len(pitlst) - 1) - pitlst.index(noff.pitch)
+ def midiTrack2Notes(self, track):
+ "returns a list of notes from a track"
+ result = []
+ for event in track.events:
+ if event.type == "NOTE_ON":
+ result.append(Note([self.time2beats(event.time), 0, event.velocity, event.pitch]))
+ elif event.type == "NOTE_OFF":
+ ndx = self.findNO(event, result)
+ dur = self.time2beats(event.time) - result[ndx].onset()
+ result[ndx].setDuration(dur)
+ else:
+ pass
+ return result
+ def midiTrack2ScoreTrack(self, mtrack):
+ "returns a Track object from a midi file"
+ notelist = self.midiTrack2Notes(mtrack)
+ return Track(notelist)
+
+
+class Scale:
+ "a class for manipulating pitch data"
+ def __init__(self, keyname, modality):
+ "where keyname is a letter and modality is a string e.g. Scale('C#','minor'))"
+ self.key = keyname
+ self.modality = modality
+ self.chromatic = range(12, 109)
+ self.keyMap = {'C':0, 'C#':1,'D':2, 'D#':3, 'E':4, 'F':5, 'F#':6, 'G':7, 'G#':8,'A':9,'A#':10, 'B':11}
+ self.scale = self.Scalemap(self.Mode(keyname, modality))
+ self.subscale = self.Scalemap(self.Mode(keyname, "subscale"))
+ def Scalemap(self, scale):
+ lim = True
+ oct = 0
+ result = []
+ stop = len(self.chromatic)
+ while lim:
+ for i in scale:
+ ndx = i + oct * 12
+ if ndx >= stop:
+ lim = False
+ break
+ else:
+ result.append(self.chromatic[ndx])
+ oct += 1
+ return result
+ def Transpose(self, incr, mode):
+ result = [(n + incr) % 12 for n in mode]
+ result.sort()
+ return result
+ def Mode(self, key, name):
+ if name == "chromatic":
+ return range(12)
+ elif name == "major":
+ return self.Transpose(self.keyMap[key], [0,2,4,5,7,9,11])
+ elif name == "minor":
+ return self.Transpose(self.keyMap[key], [0,2,3,5,7,8,10])
+ elif name == "minor pentatonic":
+ return self.Transpose(self.keyMap[key], [0,2,3,5,7,8])
+ elif name == "subscale":
+ return self.Transpose(self.keyMap[key], [0,2,5,7])
+ else: return []
+ def pitchMap(self, pitch, subscale = False):
+ "Integers only. Given a pitch, recalculates a new pitch within the key and scale"
+ if subscale:
+ scale = self.subscale
+ else:
+ scale = self.scale
+ if pitch in scale:
+ return pitch
+ else:
+ pup = pitch + 1
+ pdown = pitch - 1
+ result = None
+ for i in xrange(len(scale)):
+ if pup in scale:
+ result = pup
+ break
+ elif pdown in scale:
+ result = pdown
+ break
+ else:
+ pup += 1
+ pdown -= 1
+ return result
+ def basePit(self, strack):
+ "return the lowest tonic note in the track"
+ tonics = filter(lambda x: x % 12 == self.keyMap[self.key], strack.getPitches())
+ if tonics:
+ return min(tonics)
+ else:
+ return self.keyMap[self.key] + 48
+
+
+class beatDebugPlayer:
+ "This player expects beats to be relative to zero already"
+ TRACKDATA_NDX = 0
+ INSNUM_NDX = 1
+ def __init__(self, cssynth, timer, perimeter, scaleObj):
+ "params is the parameter object"
+ print "THREAD ID: PLAYER INIT" , thread.get_ident()
+ self.cs = cssynth
+ self.beat = 0
+ self.scoreTracks = {}
+ self.drumPitches = []
+ self.trackMap = {}
+ self.activity = {}
+ self.timer = timer
+ self.perimeter = perimeter
+ self.scale = scaleObj
+ self.basepits = {}
+ self.tempoMult = 1 #the tempo() method changes this
+ self.den = 0
+ self.beatlimit = 0
+ self.sendSync = False
+ self.loop_idcounter = 1
+ self.mutelist = []
+ self.picture_cycle = []
+ self.frozen = False
+ self.mute_all = False
+ def pause(self):
+ self.mute_all = True
+ def oldpause(self, *lid):
+ if lid and self.activity.has_key(lid[0]):
+ self.activity[lid[0]] = 'Pause'
+ return True
+ else:
+ #if no loop id is specified, or the id is just plain wrong, try and stop the last loop added set to play.
+ for k in sorted(self.activity.keys(), reverse = True):
+ if self.activity[k] == 'Play':
+ self.activity[k] = 'Pause'
+ return True
+ else:
+ return False
+ def Stop(self):
+ self.activity = 'Stop'
+ self.resetBeat()
+ self.cs.Stop()
+ def Cease(self, *lid):
+ if lid and self.activity.has_key(lid[0]):
+ self.activity[lid[0]] = 'Cease'
+ return True
+ else:
+ for k in sorted(self.activity.keys(), reverse = True):
+ if self.activity[k] == 'Play' or self.activity[k] == 'Pause':
+ self.activity[k] = 'Cease'
+ log.info("Ceasing loop id %s" %k)
+ return True
+ else:
+ return False
+ def resume(self):
+ self.mute_all = False
+ def oldresume(self, *lid):
+ if lid and self.activity.has_key(lid[0]):
+ self.activity[lid[0]] = 'Play'
+ return True
+ else:
+ for k in sorted(self.activity.keys(), reverse = True):
+ if self.activity[k] == 'Pause':
+ self.activity[k] = 'Play'
+ print "resuming id ", k
+ return True
+ else:
+ return False
+ def resetBeat(self, *num):
+ if num:
+ self.beat = num[0]
+ else:
+ self.beat = 0
+ def Track2beatList(self, Strack, beatlen, tracklen):
+ "return a list of beats from the track, reletavised to zero"
+ result = []
+ for i in range(tracklen):
+ if i > len(Strack) - 1:
+ result.append(Beat(i))
+ else:
+ result.append(beat(Strack, i, beatlen - 0.01, i))
+ return [(b.relativeOnsets(b[0].onset() % 1) if b[0] else b) for b in result]
+ def beatInstrumentMap(self, beatlength, **kargs):
+ "kargs is a dictionary. Assign beatlists to Csound instruments kbeats. Keys = 5"
+ for key in kargs:
+ strack = kargs[key][self.TRACKDATA_NDX]
+ self.scoreTracks[key] = strack
+ if key == 'Drums':
+ self.drumPitches = sorted(list(set(self.scoreTracks["Drums"].getPitches())))
+ tracklen = int(sorted(list(set(self.scoreTracks["Drums"].getOnsets())))[-1])
+ while tracklen % 4:
+ tracklen += 1
+ kargs[key][self.TRACKDATA_NDX] = self.Track2beatList(strack, beatlength, tracklen)
+ self.basepits[key] = self.scale.basePit(strack)
+ self.trackMap = kargs
+ self.beatlimit = self.beatLimit()
+ def getInstrument(self, trackname):
+ "Get an Instrument associated with the track"
+ return self.trackMap[trackname][self.INSNUM_NDX]
+ def getBeatData(self, trackname):
+ "The following three functions ought to be improved"
+ return self.trackMap[trackname][self.TRACKDATA_NDX]
+ def beatLists(self):
+ "return a list of all the trackdata"
+ return [self.getBeatData(keyname) for keyname in self.trackMap.keys()]
+ def beatLimit(self):
+ return len(self.beatLists()[0])
+ def setBPM(self, bpm):
+ "tempomult * 1 = 120bpm. Turns out ticksPerQuarter in midiImport.py always returns 480 "
+ print "bpm, " ,bpm, bpm / 120.0
+ self.tempoMult = (60.0 / bpm)
+ def tempo(self):
+ "sets current tempo"
+ print "tempo"
+ tempoparam = self.perimeter.getValue('Tempo', 'Drums') #Only look at one parameter, since tempo is global.
+ self.tempoMult = 1/(tempoparam + 1.5)
+ def articulate(self, insname):
+ if insname == 'Drums':
+ return 1
+ else:
+ pval = self.perimeter.getValue('Length', insname) + 0.5
+ if pval < 1:
+ return pval
+ else:
+ return rescale(pval, 1, 1.5, 1, 6)
+ def noteChecker(self, keyname, t, modulo, varGreaterThan, varLessThan):
+ dval = self.density(keyname)
+ densval = (dval + (random.uniform(-.112, .112)) if dval != 1 or 0 else (0.99 if dval == 1 else 0.01))
+ return (True if t % modulo == 0 and varGreaterThan <= limit(densval, 0, 1) < varLessThan else False)
+ def density(self, insname):
+ "could introduce some randomness here"
+ if insname == "Keys":
+ regions = [0, 1, 0.75, 2]
+ else:
+ regions = [0, 0.5, 0.5, 1, 0.75, 2]
+ val = 1 - self.perimeter.getValue('Density', insname)
+ valnew = rescale(val, 0, 1, 0, len(regions) - 1)
+ valnew -= random.uniform(0, 0.6)
+ if valnew < 0: valnew = 0
+ return regions[int(round(valnew))]
+ def pitchCalc(self, insname, pitch, onset):
+ "Calculate a new pitch based on the old"
+ pitchparam = self.perimeter.getValue('Pitch', insname)
+ if pitchparam > 0.4 and pitchparam < 0.6:
+ return pitch
+ if insname == 'Drums':
+ l = self.drumPitches
+ if pitchparam <= 0.4:
+ if pitch in l[0:int(math.ceil(len(l) * (pitchparam + 0.01) * 2))]:
+ return pitch
+ else:
+ return False
+ elif pitchparam >= 0.6:
+ if pitch in l[int(math.floor((len(l) - 1) * (pitchparam - 0.5) * 2)):len(l)]:
+ return pitch
+ else: return False
+ else:
+ return False
+ else:
+ basepit = self.basepits[insname]
+ pitchparam = self.perimeter.getValue('Pitch', insname)
+ newpitch = basepit + (pitch - basepit) * pitchparam * 2
+ if onset % 1 == 0:
+ return self.scale.pitchMap(int(round(newpitch)), True)
+ else:
+ return self.scale.pitchMap(int(round(newpitch)))
+ def freeze(self):
+ "stop access to all input into the player, usually done when reloading a scene"
+ self.cs.perf.SetProcessCallback(lambda: None, None)
+ for lids in self.activity:
+ self.activity[lids] = 'Cease'
+ self.frozen = True
+ print "frozen = ", self.frozen
+ def playBeat(self, time, beatnum):
+ if self.frozen: return None
+ if self.sendSync:
+ self.timer.schedEvent(time, olpcgames.mesh.broadcast, "Beat|%s" %beatnum)
+ self.sendSync = False
+ if self.picture_cycle:
+ activity = self.picture_cycle[0]
+ pics = activity.snap_store
+ updated = self.picture_cycle[1]
+ if not pics:
+ pass
+ elif updated:
+ ndx = len(pics) - 1
+ activity.feedbackgroundImage = pics[ndx]
+ else:
+ ndx = beatnum % len(pics)
+ activity.feedbackgroundImage = pics[ndx]
+ self.picture_cycle[1] = False
+ for keyname in [i for i in self.trackMap.keys() if i not in self.mutelist]:
+ ins = self.getInstrument(keyname)
+ beatCollect = self.getBeatData(keyname)[beatnum]
+ if beatCollect:
+ for note in beatCollect:
+ den = self.density(keyname)
+ pitch = self.pitchCalc(keyname, note[PITINDEX], note[ONSETINDEX])
+ if not pitch:
+ pass
+ elif den == 0:
+ self.cs.playParams(ins, (note[ONSETINDEX] * self.tempoMult) + (time - self.cs.perfTime()),
+ (note[DURINDEX] * self.articulate(keyname) if keyname == 'Drums' or keyname == 'Keys'
+ else note[DURINDEX] * self.tempoMult * self.articulate(keyname)),
+ note[VELINDEX],
+ pitch)
+ elif (note[ONSETINDEX] + beatCollect.beatnum) % den == 0:
+ self.cs.playParams(ins, (note[ONSETINDEX] * self.tempoMult) + (time - self.cs.perfTime()),
+ max(note[DURINDEX] * self.tempoMult, (den * 0.8) * 0.5) * self.articulate(keyname),
+ note[VELINDEX],
+ pitch)
+ else:
+ pass
+ def playLoop(self, time, reset_beat = False, loop_ID = False):
+ if self.frozen: return None
+ elif loop_ID:
+ lid = loop_ID
+ else:
+ lid = self.loop_idcounter
+ self.activity.update({lid:'Play'})
+ self.loop_idcounter += 1
+ if reset_beat:
+ self.beat = reset_beat
+ #self.tempo() # was used to dynamically calculate tempo. Now disabled.
+ if self.mute_all:
+ self.timer.schedEvent(time + 0.5 * self.tempoMult, self.playLoop, time + 1 * self.tempoMult, False, lid)
+ elif self.activity[lid] == 'Play':
+ self.playBeat(time, self.beat)
+ self.beat = (self.beat + 1) % self.beatlimit
+ self.timer.schedEvent(time, self.playLoop, time + (1 * self.tempoMult), False, lid)
+ elif self.activity[lid] == 'Pause':
+ self.timer.schedEvent(time + 0.5 * self.tempoMult, self.playLoop, time + 1 * self.tempoMult, False, lid)
+ elif self.activity[lid] == 'Cease':
+ pass
+ else:
+ self.resume()
+
+
+if __name__ == '__main__':
+ print "running test code for Tracks.py \n"
+ mpath = raw_input("enter a path to a midi file :")
+ mfile = Midi2Score(mpath)
+ print "just reading track one for now..."
+
+
+
+
+
+
+
+
+
+
diff --git a/City/__init__.py b/City/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/City/__init__.py
diff --git a/City/midiImport.py b/City/midiImport.py
new file mode 100755
index 0000000..2473343
--- /dev/null
+++ b/City/midiImport.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python
+"""
+Will Ware
+Dec 6 2001, 10:41 pm
+http://groups.google.com/group/alt.sources/msg/0c5fc523e050c35e
+
+midi.py -- MIDI classes and parser in Python
+Placed into the public domain in December 2001 by Will Ware
+Python MIDI classes: meaningful data structures that represent MIDI events
+and other objects. You can read MIDI files to create such objects, or
+generate a collection of objects and use them to write a MIDI file.
+Helpful MIDI info:
+http://crystal.apana.org.au/ghansper/midi_introduction/midi_file_form...
+http://www.argonet.co.uk/users/lenny/midi/mfile.html
+"""
+import sys, string, types, exceptions
+debugflag = 0
+
+def showstr(str, n=16):
+ for x in str[:n]:
+ print ('%02x' % ord(x)),
+ print
+
+def getNumber(str, length):
+ # MIDI uses big-endian for everything
+ sum = 0
+ for i in range(length):
+ sum = (sum << 8) + ord(str[i])
+ return sum, str[length:]
+
+def getVariableLengthNumber(str):
+ sum = 0
+ i = 0
+ while 1:
+ x = ord(str[i])
+ i = i + 1
+ sum = (sum << 7) + (x & 0x7F)
+ if not (x & 0x80):
+ return sum, str[i:]
+
+def putNumber(num, length):
+ # MIDI uses big-endian for everything
+ lst = [ ]
+ for i in range(length):
+ n = 8 * (length - 1 - i)
+ lst.append(chr((num >> n) & 0xFF))
+ return string.join(lst, "")
+
+def putVariableLengthNumber(x):
+ lst = [ ]
+ while 1:
+ y, x = x & 0x7F, x >> 7
+ lst.append(chr(y + 0x80))
+ if x == 0:
+ break
+ lst.reverse()
+ lst[-1] = chr(ord(lst[-1]) & 0x7f)
+ return string.join(lst, "")
+
+class EnumException(exceptions.Exception):
+ pass
+
+class Enumeration:
+ def __init__(self, enumList):
+ lookup = { }
+ reverseLookup = { }
+ i = 0
+ uniqueNames = [ ]
+ uniqueValues = [ ]
+ for x in enumList:
+ if type(x) == types.TupleType:
+ x, i = x
+ if type(x) != types.StringType:
+ raise EnumException, "enum name is not a string: " + x
+ if type(i) != types.IntType:
+ raise EnumException, "enum value is not an integer: " + i
+ if x in uniqueNames:
+ raise EnumException, "enum name is not unique: " + x
+ if i in uniqueValues:
+ raise EnumException, "enum value is not unique for " + x
+ uniqueNames.append(x)
+ uniqueValues.append(i)
+ lookup[x] = i
+ reverseLookup[i] = x
+ i = i + 1
+ self.lookup = lookup
+ self.reverseLookup = reverseLookup
+ def __add__(self, other):
+ lst = [ ]
+ for k in self.lookup.keys():
+ lst.append((k, self.lookup[k]))
+ for k in other.lookup.keys():
+ lst.append((k, other.lookup[k]))
+ return Enumeration(lst)
+ def hasattr(self, attr):
+ return self.lookup.has_key(attr)
+ def has_value(self, attr):
+ return self.reverseLookup.has_key(attr)
+ def __getattr__(self, attr):
+ if not self.lookup.has_key(attr):
+ raise AttributeError
+ return self.lookup[attr]
+ def whatis(self, value):
+ return self.reverseLookup[value]
+
+channelVoiceMessages = Enumeration([("NOTE_OFF", 0x80),
+ ("NOTE_ON", 0x90),
+ ("POLYPHONIC_KEY_PRESSURE", 0xA0),
+ ("CONTROLLER_CHANGE", 0xB0),
+ ("PROGRAM_CHANGE", 0xC0),
+ ("CHANNEL_KEY_PRESSURE", 0xD0),
+ ("PITCH_BEND", 0xE0)])
+channelModeMessages = Enumeration([("ALL_SOUND_OFF", 0x78),
+ ("RESET_ALL_CONTROLLERS", 0x79),
+ ("LOCAL_CONTROL", 0x7A),
+ ("ALL_NOTES_OFF", 0x7B),
+ ("OMNI_MODE_OFF", 0x7C),
+ ("OMNI_MODE_ON", 0x7D),
+ ("MONO_MODE_ON", 0x7E),
+ ("POLY_MODE_ON", 0x7F)])
+metaEvents = Enumeration([("SEQUENCE_NUMBER", 0x00),
+ ("TEXT_EVENT", 0x01),
+ ("COPYRIGHT_NOTICE", 0x02),
+ ("SEQUENCE_TRACK_NAME", 0x03),
+ ("INSTRUMENT_NAME", 0x04),
+ ("LYRIC", 0x05),
+ ("MARKER", 0x06),
+ ("CUE_POINT", 0x07),
+ ("MIDI_CHANNEL_PREFIX", 0x20),
+ ("MIDI_PORT", 0x21),
+ ("END_OF_TRACK", 0x2F),
+ ("SET_TEMPO", 0x51),
+ ("SMTPE_OFFSET", 0x54),
+ ("TIME_SIGNATURE", 0x58),
+ ("KEY_SIGNATURE", 0x59),
+ ("SEQUENCER_SPECIFIC_META_EVENT", 0x7F)])
+
+# runningStatus appears to want to be an attribute of a MidiTrack. But
+# it doesn't seem to do any harm to implement it as a global.
+runningStatus = None
+class MidiEvent:
+ def __init__(self, track):
+ self.track = track
+ self.time = None
+ self.channel = self.pitch = self.velocity = self.data = None
+ def __cmp__(self, other):
+ # assert self.time != None and other.time != None
+ return cmp(self.time, other.time)
+ def __repr__(self):
+ r = ("<MidiEvent %s, t=%s, track=%s, channel=%s" %
+ (self.type,
+ repr(self.time),
+ self.track.index,
+ repr(self.channel)))
+ for attrib in ["pitch", "data", "velocity"]:
+ if getattr(self, attrib) != None:
+ r = r + ", " + attrib + "=" + repr(getattr(self, attrib))
+ return r + ">"
+ def read(self, time, str):
+ global runningStatus
+ self.time = time
+ # do we need to use running status?
+ if not (ord(str[0]) & 0x80):
+ str = runningStatus + str
+ runningStatus = x = str[0]
+ x = ord(x)
+ y = x & 0xF0
+ z = ord(str[1])
+ if channelVoiceMessages.has_value(y):
+ self.channel = (x & 0x0F) + 1
+ self.type = channelVoiceMessages.whatis(y)
+ if (self.type == "PROGRAM_CHANGE" or
+ self.type == "CHANNEL_KEY_PRESSURE"):
+ self.data = z
+ return str[2:]
+ else:
+ self.pitch = z
+ self.velocity = ord(str[2])
+ channel = self.track.channels[self.channel - 1]
+ if (self.type == "NOTE_OFF" or
+ (self.velocity == 0 and self.type == "NOTE_ON")):
+ channel.noteOff(self.pitch, self.time)
+ elif self.type == "NOTE_ON":
+ channel.noteOn(self.pitch, self.time, self.velocity)
+ return str[3:]
+ elif y == 0xB0 and channelModeMessages.has_value(z):
+ self.channel = (x & 0x0F) + 1
+ self.type = channelModeMessages.whatis(z)
+ if self.type == "LOCAL_CONTROL":
+ self.data = (ord(str[2]) == 0x7F)
+ elif self.type == "MONO_MODE_ON":
+ self.data = ord(str[2])
+ return str[3:]
+ elif x == 0xF0 or x == 0xF7:
+ self.type = {0xF0: "F0_SYSEX_EVENT",
+ 0xF7: "F7_SYSEX_EVENT"}[x]
+ length, str = getVariableLengthNumber(str[1:])
+ self.data = str[:length]
+ return str[length:]
+ elif x == 0xFF:
+ if not metaEvents.has_value(z):
+ print "Unknown meta event: FF %02X" % z
+ sys.stdout.flush()
+ raise "Unknown midi event type"
+ self.type = metaEvents.whatis(z)
+ length, str = getVariableLengthNumber(str[2:])
+ self.data = str[:length]
+ return str[length:]
+ raise "Unknown midi event type"
+ def write(self):
+ sysex_event_dict = {"F0_SYSEX_EVENT": 0xF0,
+ "F7_SYSEX_EVENT": 0xF7}
+ if channelVoiceMessages.hasattr(self.type):
+ x = chr((self.channel - 1) +
+ getattr(channelVoiceMessages, self.type))
+ if (self.type != "PROGRAM_CHANGE" and
+ self.type != "CHANNEL_KEY_PRESSURE"):
+ data = chr(self.pitch) + chr(self.velocity)
+ else:
+ data = chr(self.data)
+ return x + data
+ elif channelModeMessages.hasattr(self.type):
+ x = getattr(channelModeMessages, self.type)
+ x = (chr(0xB0 + (self.channel - 1)) +
+ chr(x) +
+ chr(self.data))
+ return x
+ elif sysex_event_dict.has_key(self.type):
+ str = chr(sysex_event_dict[self.type])
+ str = str + putVariableLengthNumber(len(self.data))
+ return str + self.data
+ elif metaEvents.hasattr(self.type):
+ str = chr(0xFF) + chr(getattr(metaEvents, self.type))
+ str = str + putVariableLengthNumber(len(self.data))
+ return str + self.data
+ else:
+ raise "unknown midi event type: " + self.type
+
+"""
+register_note() is a hook that can be overloaded from a script that
+imports this module. Here is how you might do that, if you wanted to
+store the notes as tuples in a list. Including the distinction
+between track and channel offers more flexibility in assigning voices.
+import midi
+notelist = [ ]
+def register_note(t, c, p, v, t1, t2):
+ notelist.append((t, c, p, v, t1, t2))
+midi.register_note = register_note
+"""
+def register_note(track_index, channel_index, pitch, velocity,
+ keyDownTime, keyUpTime):
+ pass
+
+class MidiChannel:
+ """A channel (together with a track) provides the continuity connecting
+ a NOTE_ON event with its corresponding NOTE_OFF event. Together, those
+ define the beginning and ending times for a Note."""
+ def __init__(self, track, index):
+ self.index = index
+ self.track = track
+ self.pitches = { }
+ def __repr__(self):
+ return "<MIDI channel %d>" % self.index
+ def noteOn(self, pitch, time, velocity):
+ self.pitches[pitch] = (time, velocity)
+ def noteOff(self, pitch, time):
+ if self.pitches.has_key(pitch):
+ keyDownTime, velocity = self.pitches[pitch]
+ register_note(self.track.index, self.index, pitch, velocity,
+ keyDownTime, time)
+ del self.pitches[pitch]
+ # The case where the pitch isn't in the dictionary is illegal,
+ # I think, but we probably better just ignore it.
+
+class DeltaTime(MidiEvent):
+ type = "DeltaTime"
+ def read(self, oldstr):
+ self.time, newstr = getVariableLengthNumber(oldstr)
+ return self.time, newstr
+ def write(self):
+ str = putVariableLengthNumber(self.time)
+ return str
+
+class MidiTrack:
+ def __init__(self, index):
+ self.index = index
+ self.events = [ ]
+ self.channels = [ ]
+ self.length = 0
+ for i in range(16):
+ self.channels.append(MidiChannel(self, i+1))
+ def read(self, str):
+ time = 0
+ assert str[:4] == "MTrk"
+ length, str = getNumber(str[4:], 4)
+ self.length = length
+ mystr = str[:length]
+ remainder = str[length:]
+ while mystr:
+ delta_t = DeltaTime(self)
+ dt, mystr = delta_t.read(mystr)
+ time = time + dt
+ self.events.append(delta_t)
+ e = MidiEvent(self)
+ mystr = e.read(time, mystr)
+ self.events.append(e)
+ return remainder
+ def write(self):
+ time = self.events[0].time
+ # build str using MidiEvents
+ str = ""
+ for e in self.events:
+ str = str + e.write()
+ return "MTrk" + putNumber(len(str), 4) + str
+ def __repr__(self):
+ r = "<MidiTrack %d -- %d events\\n" % (self.index, len(self.events))
+ for e in self.events:
+ r = r + " " + `e` + "\\n"
+ return r + " >"
+
+class MidiFile:
+ def __init__(self):
+ self.file = None
+ self.format = 1
+ self.tracks = [ ]
+ self.ticksPerQuarterNote = None
+ self.ticksPerSecond = None
+ def open(self, filename, attrib="rb"):
+ if filename == None:
+ if attrib in ["r", "rb"]:
+ self.file = sys.stdin
+ else:
+ self.file = sys.stdout
+ else:
+ self.file = open(filename, attrib)
+ def __repr__(self):
+ r = "<MidiFile %d tracks\\n" % len(self.tracks)
+ for t in self.tracks:
+ r = r + " " + `t` + "\\n"
+ return r + ">"
+ def close(self):
+ self.file.close()
+ def read(self):
+ self.readstr(self.file.read())
+ def readstr(self, str):
+ assert str[:4] == "MThd"
+ length, str = getNumber(str[4:], 4)
+ assert length == 6
+ format, str = getNumber(str, 2)
+ self.format = format
+ assert format == 0 or format == 1 # dunno how to handle 2
+ numTracks, str = getNumber(str, 2)
+ division, str = getNumber(str, 2)
+ if division & 0x8000:
+ framesPerSecond = -((division >> 8) | -128)
+ ticksPerFrame = division & 0xFF
+ assert ticksPerFrame == 24 or ticksPerFrame == 25 or \
+ ticksPerFrame == 29 or ticksPerFrame == 30
+ if ticksPerFrame == 29: ticksPerFrame = 30 # drop frame
+ self.ticksPerSecond = ticksPerFrame * framesPerSecond
+ else:
+ self.ticksPerQuarterNote = division & 0x7FFF
+ for i in range(numTracks):
+ trk = MidiTrack(i)
+ str = trk.read(str)
+ self.tracks.append(trk)
+ def write(self):
+ self.file.write(self.writestr())
+ def writestr(self):
+ division = self.ticksPerQuarterNote
+ # Don't handle ticksPerSecond yet, too confusing
+ assert (division & 0x8000) == 0
+ str = "MThd" + putNumber(6, 4) + putNumber(self.format, 2)
+ str = str + putNumber(len(self.tracks), 2)
+ str = str + putNumber(division, 2)
+ for trk in self.tracks:
+ str = str + trk.write()
+ return str
+
diff --git a/City/setup.py b/City/setup.py
new file mode 100755
index 0000000..94950e1
--- /dev/null
+++ b/City/setup.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+if __name__ == "__main__":
+ bundlebuilder.start("City")