class SFM(object): # pitch registers transpositionSemitones = 0 octaveNumber = 3 # tempo registers tempo = 60 currentBeatValue = 60.0/tempo currentBeat = 0 totalDuration = 0.0 # dynamics registers crescendoSpeed = 1.1 currentCrescendoSpeed = crescendoSpeed crescendoBeatsRemaining = 0.0 maximumAmplitude = 0.0 # tuple registers duration = 60.0/tempo amplitude = 1.0 decay = 1.0 # I/O input = "" ######################################################### # initialize Note, Rhythm, and Dynamics objects def __init__(self, SCALE): NOTES, FREQ_DICT = SCALE self.note = Note(NOTES, FREQ_DICT) self.rhythm = Rhythm() self.dynamics = Dynamics() self.equalizerFactor = { } self.equalizerFactor[-0.1] = 1.0 self.equalizerFactor[220] = 1.0 self.equalizerFactor[440] = 0.7 self.equalizerFactor[880] = 0.35 self.equalizerFactor[1760] = 0.15 self.equalizerFactor[3520] = 0.15 self.equalizerFactor[7040] = 0.15 self.equalizerFactor[14080] = 0.15 self.equalizerFactor[28160] = 0.15 self.equalizerFactor[56320] = 0.15 self.equalizerBreakPoints = [-0.1, 220, 440, 880, 1760, 3520, 7040, 14080, 28160, 56320] # self.tempo = 60 # self.currentBeatValue = 60.0/self.tempo # self.octaveNumber = 3 def equalize(self, freq): a, b = interval(freq, self.equalizerBreakPoints) f = mapInterval(freq, a,b, self.equalizerFactor[a], self.equalizerFactor[b]) # print freq, a, b, f return f # return tuple as string given frequency, # duration, decay, and amplitude def _tuple(self, freq, duration): output = `freq` output += " "+`duration` a = self.amplitude a = a*self.equalize(freq) output += " "+`a` output += " "+`self.decay` return output # return tuple as string from frequency of token # and root and suffix of token def tuple(self, freq, root, suffix): if suffix.find(",") > -1: thisDuration = self.duration*(1 - self.rhythm.breath) output = self._tuple(freq, thisDuration) output += "\n" output += self._tuple(0, self.duration - thisDuration) else: output = self._tuple(freq, self.duration) return output def updateRhythm(self, cmd): self.currentBeatValue, self.duration = self.rhythm.value(cmd, self) def emitNote(self, token): if self.crescendoBeatsRemaining > 0: self.amplitude = self.amplitude*self.currentCrescendoSpeed self.crescendoBeatsRemaining -= self.currentBeatValue freq, root, suffix = self.note.freq(token, self.transpositionSemitones, self.octaveNumber) self.output += self.tuple(freq, root, suffix) + "\n" # summary data self.totalDuration += self.duration self.currentBeat += self.currentBeatValue if self.amplitude > self.maximumAmplitude: self.maximumAmplitude = self.amplitude def executeCommand(self, ops): cmd = ops[0] # if cmd is a rhythm symbol, change value of duration register if self.rhythm.isRhythmOp(cmd): self.updateRhythm(cmd) # if cmd is a tempo command, change value of the tempo register if self.rhythm.isTempoOp(cmd): self.tempo = self.rhythm.tempo[cmd] self.updateRhythm(cmd) if cmd == "tempo": self.tempo = float(ops[1]) self.updateRhythm(cmd) # if cmd is an articulation command, change value of the decay register if self.rhythm.isArticulationOp(cmd): self.decay = self.rhythm.decay[cmd] # if cmd is a dynamics command, change value of the amplitude register if self.dynamics.isDynamicsConstant(cmd): self.amplitude = self.dynamics.value[cmd] # crescendo and decrescendo if cmd == "crescendo" or cmd == "cresc": self.crescendoBeatsRemaining = float(ops[1]) self.currentCrescendoSpeed = self.crescendoSpeed if cmd == "decrescendo" or cmd == "decresc": self.crescendoBeatsRemaining = float(ops[1]) self.currentCrescendoSpeed = 1.0/self.crescendoSpeed # pitch transposition if cmd == "octave": self.octaveNumber = int(ops[1]) if cmd == "transpose": self.transpositionSemitones = int(ops[1]) # pass special commands through if cmd[0] == '@': CMD = catList2(ops) CMD = CMD[:len(CMD)]+"\n" self.output += CMD # tuples: returns a string of tuples from input = solfa text def tuples(self): # split intput into list of tokens self.input = self.input.replace("\n", " ") tokens = self.input.split(" ") # make sure there are not empty list elements tokens = filter( lambda x: len(x), tokens) # initialize output self.output = "" for token in tokens: if self.note.isNote(token): self.emitNote(token) else: ops = token.split(":") ops = filter(lambda x: len(x) > 0, ops) if DEBUG == ON: self.output += "cmd: "+ `ops`+"\n" self.executeCommand(ops) return self.output
class SFM(object): # pitch registers transpositionSemitones = 0 octaveNumber = 3 # tempo registers tempo = 60 currentBeatValue = 60.0 / tempo currentBeat = 0 totalDuration = 0.0 # dynamics registers crescendoSpeed = 1.1 currentCrescendoSpeed = crescendoSpeed crescendoBeatsRemaining = 0.0 maximumAmplitude = 0.0 # tuple registers duration = 60.0 / tempo amplitude = 1.0 decay = 1.0 # I/O input = "" ######################################################### # initialize Note, Rhythm, and Dynamics objects def __init__(self, SCALE): NOTES, FREQ_DICT = SCALE self.note = Note(NOTES, FREQ_DICT) self.rhythm = Rhythm() self.dynamics = Dynamics() self.equalizerFactor = {} self.equalizerFactor[-0.1] = 1.0 self.equalizerFactor[220] = 1.0 self.equalizerFactor[440] = 0.7 self.equalizerFactor[880] = 0.35 self.equalizerFactor[1760] = 0.15 self.equalizerFactor[3520] = 0.15 self.equalizerFactor[7040] = 0.15 self.equalizerFactor[14080] = 0.15 self.equalizerFactor[28160] = 0.15 self.equalizerFactor[56320] = 0.15 self.equalizerBreakPoints = [ -0.1, 220, 440, 880, 1760, 3520, 7040, 14080, 28160, 56320 ] # self.tempo = 60 # self.currentBeatValue = 60.0/self.tempo # self.octaveNumber = 3 def equalize(self, freq): a, b = interval(freq, self.equalizerBreakPoints) f = mapInterval(freq, a, b, self.equalizerFactor[a], self.equalizerFactor[b]) # print freq, a, b, f return f # return tuple as string given frequency, # duration, decay, and amplitude def _tuple(self, freq, duration): output = ` freq ` output += " " + ` duration ` a = self.amplitude a = a * self.equalize(freq) output += " " + ` a ` output += " " + ` self.decay ` return output # return tuple as string from frequency of token # and root and suffix of token def tuple(self, freq, root, suffix): if suffix.find(",") > -1: thisDuration = self.duration * (1 - self.rhythm.breath) output = self._tuple(freq, thisDuration) output += "\n" output += self._tuple(0, self.duration - thisDuration) else: output = self._tuple(freq, self.duration) return output def updateRhythm(self, cmd): self.currentBeatValue, self.duration = self.rhythm.value(cmd, self) def emitNote(self, token): if self.crescendoBeatsRemaining > 0: self.amplitude = self.amplitude * self.currentCrescendoSpeed self.crescendoBeatsRemaining -= self.currentBeatValue freq, root, suffix = self.note.freq(token, self.transpositionSemitones, self.octaveNumber) self.output += self.tuple(freq, root, suffix) + "\n" # summary data self.totalDuration += self.duration self.currentBeat += self.currentBeatValue if self.amplitude > self.maximumAmplitude: self.maximumAmplitude = self.amplitude def executeCommand(self, ops): cmd = ops[0] # if cmd is a rhythm symbol, change value of duration register if self.rhythm.isRhythmOp(cmd): self.updateRhythm(cmd) # if cmd is a tempo command, change value of the tempo register if self.rhythm.isTempoOp(cmd): self.tempo = self.rhythm.tempo[cmd] self.updateRhythm(cmd) if cmd == "tempo": self.tempo = float(ops[1]) self.updateRhythm(cmd) # if cmd is an articulation command, change value of the decay register if self.rhythm.isArticulationOp(cmd): self.decay = self.rhythm.decay[cmd] # if cmd is a dynamics command, change value of the amplitude register if self.dynamics.isDynamicsConstant(cmd): self.amplitude = self.dynamics.value[cmd] # crescendo and decrescendo if cmd == "crescendo" or cmd == "cresc": self.crescendoBeatsRemaining = float(ops[1]) self.currentCrescendoSpeed = self.crescendoSpeed if cmd == "decrescendo" or cmd == "decresc": self.crescendoBeatsRemaining = float(ops[1]) self.currentCrescendoSpeed = 1.0 / self.crescendoSpeed # pitch transposition if cmd == "octave": self.octaveNumber = int(ops[1]) if cmd == "transpose": self.transpositionSemitones = int(ops[1]) # pass special commands through if cmd[0] == '@': CMD = catList2(ops) CMD = CMD[:len(CMD)] + "\n" self.output += CMD # tuples: returns a string of tuples from input = solfa text def tuples(self): # split intput into list of tokens self.input = self.input.replace("\n", " ") tokens = self.input.split(" ") # make sure there are not empty list elements tokens = filter(lambda x: len(x), tokens) # initialize output self.output = "" for token in tokens: if self.note.isNote(token): self.emitNote(token) else: ops = token.split(":") ops = filter(lambda x: len(x) > 0, ops) if DEBUG == ON: self.output += "cmd: " + ` ops ` + "\n" self.executeCommand(ops) return self.output