def trackBar(self, pattern, ctable): """ Do the bass bar. Called from self.bar() """ sc = self.seq unify = self.unify[sc] for p in pattern: ct = self.getChordInPos(p.offset, ctable) if ct.bassZ: continue note = ct.chord.scaleList[ p.noteoffset] + p.addoctave + p.accidental if not self.harmonyOnly[sc]: self.sendNote(p.offset, self.getDur(p.duration), self.adjustNote(note), self.adjustVolume(p.vol, p.offset)) if self.harmony[sc]: h = harmonize(self.harmony[sc], note, ct.chord.noteList) for n in h: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(n), self.adjustVolume(p.vol * self.harmonyVolume[sc], -1))
def addHarmony(self, notes, ctable): """ Add harmony to solo notes. """ sc = self.seq harmony = self.harmony[sc] harmOnly = self.harmonyOnly[sc] for offset in notes: nn = notes[offset] if len(nn.nl) == 1 and nn.nl[0] != None: tb = self.getChordInPos(offset, ctable) if tb.chordZ: continue h = harmonize(harmony, nn.nl[0], tb.chord.bnoteList) """ If harmonyonly set then drop note, substitute harmony, else append harmony notes to chord. """ if harmOnly: nn.nl = h nn.velocity = [] off = 0 else: nn.nl.extend(h) off = 1 # Create velocites for harmony note(s) for i in range(off, len(nn.nl)): nn.velocity.append( self.adjustVolume( nn.defaultVel * self.harmonyVolume[sc], offset)) return notes
def trackBar(self, pattern, ctable): """ Do a arpeggio bar. Called from self.bar() """ sc = self.seq direct = self.direction[sc] for p in pattern: tb = self.getChordInPos(p.offset, ctable) if tb.arpeggioZ: continue if direct == 'DOWN': self.arpDirection = -1 if self.chordLimit: tb.chord.limit(self.chordLimit) if self.compress[sc]: tb.chord.compress() if self.invert[sc]: tb.chord.invert(self.invert[sc]) # This should be optimized, it recreates the chord for every pattern. # Problem is that one would need to check all the LIMIT, COMPRESS, etc # settings each for each bar as well, so it's probably just as easy to # leave it as is. Besides, this works. ln = self.chordRange[sc] o = 0 ourChord = [] while ln >= 1: for a in tb.chord.noteList: ourChord.append(a + o) ln -= 1 o += 12 if ln > 0 and ln < 1: # for fractional lengths ln = int(tb.chord.noteListLen * ln) if ln < 2: # important, min of 2 notes in arp. ln = 2 for a in tb.chord.noteList[:ln]: ourChord.append(a + o) if direct == 'BOTH': if self.arpOffset < 0: self.arpOffset = 1 self.arpDirection = 1 elif self.arpOffset >= len(ourChord): self.arpOffset = len(ourChord) - 2 self.arpDirection = -1 elif direct == 'UP': if self.arpOffset >= len(ourChord) or self.arpOffset < 0: self.arpOffset = 0 self.arpDirection = 1 elif direct == 'DOWN': if self.arpOffset < 0 or self.arpOffset >= len(ourChord): self.arpOffset = len(ourChord) - 1 self.arpDirection = -1 if direct == 'RANDOM': note = random.choice(ourChord) else: note = ourChord[self.arpOffset] self.arpOffset += self.arpDirection if not self.harmonyOnly[sc]: self.sendNote(p.offset, self.getDur(p.duration), self.adjustNote(note), self.adjustVolume(p.vol, p.offset)) if self.harmony[sc]: h = harmonize(self.harmony[sc], note, ourChord) for n in h: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(n), self.adjustVolume(p.vol * self.harmonyVolume[sc], -1)) tb.chord.reset() # important, other tracks chord object
def trackBar(self, pattern, ctable): """ Do the aria bar. Called from self.bar() """ sc = self.seq unify = self.unify[sc] for p in pattern: ct = self.getChordInPos(p.offset, ctable) if ct.ariaZ: continue thisChord = ct.chord.tonic + ct.chord.chordType stype = self.scaleType[sc] range = self.chordRange[sc] ### Generate notelist if nesc. if self.lastChord != thisChord or self.lastStype != stype or \ self.lastRange != range: self.lastChord = thisChord self.lastStype = stype self.lastRange = range if stype == 'CHORD': notelist = ct.chord.noteList elif stype == 'CHROMATIC': notelist = [ct.chord.rootNote + x for x in range(0, 12)] else: notelist = list(ct.chord.scaleList) o = 0 self.notes = [] while range >= 1: for a in notelist: self.notes.append(a + o) o += 12 range -= 1 if range > 0 and range < 1: # for fractional scale lengths range = int(len(notelist) * range) if range < 2: # important, must be at least 2 notes in a scale range = 2 for a in notelist[:range]: self.notes.append(a + o) # grab a note from the list if self.dirptr >= len(self.selectDir): self.dirptr = 0 a = self.selectDir[self.dirptr] if a == 'R': a = random.choice((-1, 0, 1)) self.noteptr += a if self.noteptr >= len(self.notes): if a > 0: self.noteptr = 0 else: self.noteptr = len(self.notes) - 1 elif self.noteptr < 0: if a < 0: self.noteptr = len(self.notes) - 1 else: self.noteptr = 0 note = self.notes[self.noteptr] self.dirptr += 1 # output if not self.harmonyOnly[sc]: self.sendNote(p.offset, self.getDur(p.duration), self.adjustNote(note), self.adjustVolume(p.vol, p.offset)) if self.harmony[sc]: h = harmonize(self.harmony[sc], note, ct.chord.noteList) for n in h: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(n), self.adjustVolume(p.vol * self.harmonyVolume[sc], -1))
def trackBar(self, pattern, ctable): """ Do a waling bass bar. Called from self.bar() """ sc=self.seq dir = self.direction[sc] unify = self.unify[sc] for p in pattern: tb = self.getChordInPos(p.offset, ctable) if tb.walkZ: continue root = tb.chord.rootNote # root note of chord """ Create a note list from the current scale. We do this for each beat, but it's pretty fast. The note list is simply notes 0..6 of the scale PLUS notes 1..5 reversed. So, a Cmajor chord would result in the note list (0,2,4,5,7,9,7,5,4,2). Note that we deliberately skip the 7th. Too often the chord is a Major but the melody note will be the dom. 7th and the M7 will sound off. So, just err on the side of caution. If DIR is UP or DOWN we don't append the 2nd half of the scale. If DIR is DOWN we reverse the order as well. """ wNotes = list(tb.chord.scaleList[0:6]) if dir not in ('UP', 'DOWN'): b = list(tb.chord.scaleList[1:5]) b.reverse() wNotes += b if dir == 'DOWN': wNotes.reverse() # Ensure that the offset is in range. if self.walkChoice >= len(wNotes) or self.walkChoice < 0: self.walkChoice = 0 """ Even with a walking bass it's nice to have the chord root on beat 1 ... not all the time, but most. This bit of code ensures that more that 50% of beat ones will have the root. """ if p.offset == 0 and random.choice((0,1)): self.walkChoice=0 note = wNotes[self.walkChoice] """ Adjust offset for NEXT TIME. If the direction is up/down we just increment the pointer. If we have direction set to RANDOM then we select either -1, 0 or 1 with equal change for moving up, down or not-at-all. With BOTH we have a preference to move up. """ if dir in ('UP', 'DOWN'): self.walkChoice += 1 elif dir == 'RANDOM': self.walkChoice += random.choice((0,1,-1)) else: # BOTH self.walkChoice += random.choice( (-1,0,0,2,2,1,1,1,1,1,1,1)) if not self.harmonyOnly[sc]: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(note), self.adjustVolume(p.vol, p.offset) ) if self.harmony[sc]: ch = self.getChordInPos(p.offset, ctable).chord.noteList h = harmonize(self.harmony[sc], note, ch) for n in h: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(n), self.adjustVolume(p.vol * self.harmonyVolume[sc], -1) )
def trackBar(self, pattern, ctable): """ Do a scale bar. Called from self.bar() """ sc = self.seq direct = self.direction[sc] unify = self.unify[sc] # If the range or direction has changed, we just start # with a new scale. t = self.chordRange[sc] if t != self.lastRange: self.lastRange = t self.lastChord = None if self.lastDirect != direct: self.lastDirect = direct self.lastChord = None for p in pattern: tb = self.getChordInPos(p.offset, ctable) if tb.scaleZ: continue thisChord = tb.chord.tonic + tb.chord.chordType stype = self.scaleType[sc] if thisChord != self.lastChord or stype != self.lastStype: self.lastChord = thisChord self.lastStype = stype if stype == 'CHROMATIC': notelist = [tb.chord.rootNote + x for x in range(0, 12)] else: notelist = list(tb.chord.scaleList) """ Get the current scale and append enuf copies together for RANGE setting. If Range happens to be 0 or 1 we end up with a single copy. """ ln = self.chordRange[sc] # RANGE 1...x (def. == 1) o = 0 self.notes = [] while ln >= 1: for a in notelist: self.notes.append(a + o) o += 12 ln -= 1 if ln > 0 and ln < 1: # for fractional scale lengths ln = int(len(notelist) * ln) if ln < 2: # important, must be at least 2 notes in a scale ln = 2 for a in notelist[:ln]: self.notes.append(a + o) if direct == 'DOWN': self.dirfact = -1 if self.lastNote == -1: self.sOffset = len(self.notes) - 1 else: self.sOffset = 0 if self.lastNote > -1: if self.lastNote in self.notes: self.sOffset = self.notes.index(self.lastNote) else: self.sOffset = len(self.notes) - 1 for i, a in enumerate(self.notes): if a > self.lastNote: self.sOffset = i break # Keep offset into note list in range # only > end of list if BOTH or UP if self.sOffset >= len(self.notes): if direct == 'BOTH': self.dirfact = -1 self.sOffset = len(self.notes) - 2 else: ## UP self.sOffset = 0 # only < start of list if DOWN or BOTH elif self.sOffset < 0: if direct == 'BOTH': self.dirfact = 1 self.sOffset = 1 else: ## DOWN self.sOffset = len(self.notes) - 1 if direct == 'RANDOM': note = random.choice(self.notes) else: note = self.notes[self.sOffset] self.sOffset += self.dirfact self.lastNote = note if not self.harmonyOnly[sc]: self.sendNote(p.offset, self.getDur(p.duration), self.adjustNote(note), self.adjustVolume(p.vol, p.offset)) if self.harmony[sc]: ch = self.getChordInPos(p.offset, ctable).chord.noteList h = harmonize(self.harmony[sc], note, ch) for n in h: self.sendNote( p.offset, self.getDur(p.duration), self.adjustNote(n), self.adjustVolume(self.harmonyVolume[sc] * p.vol, -1))