def miditable(self): miditable = NoteTable(100, **self.def_cols) for pattern in self.seq: if isinstance(pattern, Pattern): table = pattern.miditable if pattern.channel: table['channel'] = pattern.channel miditable.insert_table(table, timecatenate=True, exclude_cols=['channel']) else: miditable.insert_table(pattern.miditable, timecatenate=True) else: writetime = miditable.maxtime for pat in pattern: table = pat.miditable if pat.channel: table['channel'] = pat.channel miditable.insert_table(table, offset=writetime, exclude_cols=['channel']) else: miditable.insert_table(table, offset=writetime) self.table.insert_table_loop(miditable, self.loopno, exclude_cols=['channel']) self.table.insert_note_offs() return self.table
def pause(stmt): """Pause statement for tplay. Can take a number of rest units.""" parse = stmt.split(' ') val = 1 if len(parse) == 1 else int(parse[1]) table = NoteTable(1) table.rest(attacktick=0, score_d=TheoryPlayer.Notedur * val) return table
def voicechord(pcgroup): table = NoteTable(len(pcgroup)) for idx in range(len(pcgroup)): table.note_on(time=0, noteval=pcgroup[idx].midi, score_d=TheoryPlayer.Longdur, notevel=TheoryPlayer.Vol) return table
def ascend(pcgroup): table = NoteTable(len(pcgroup) + 1) for idx in range(0, len(pcgroup) + 1): table.note_on(time=idx * TheoryPlayer.Notedur, noteval=pcgroup[idx].midi, score_d=TheoryPlayer.Notedur, notevel=TheoryPlayer.Vol) return table
def descend(pcgroup): table = NoteTable(len(pcgroup) + 1) for idx, tidx in zip(range(len(pcgroup), -1, -1), range(0, len(pcgroup) + 1)): table.note_on(time=tidx * TheoryPlayer.Notedur, noteval=pcgroup[idx].midi, score_d=TheoryPlayer.Notedur, notevel=TheoryPlayer.Vol) return table
def compose(pcgroup, loop=1): """Compose the MidiTable depending on type of argument.""" table = NoteTable(1, channel=TheoryPlayer.Channel) if isinstance(pcgroup, PC): return compose(PCGroup([pcgroup]), loop=loop) elif isinstance(pcgroup, Durations): return rhythm(pcgroup, loop=loop) else: for funcname in getattr(TheoryPlayer.Compiler, pcgroup.__class__.__name__): func = Compilers.funcs[funcname] subtable = func(pcgroup) table.insert_table_loop(subtable, loop, timecatenate=True) return table
def rhythm(durations, loop=1): table = NoteTable(1 + len(durations), channel=9) for attak, dur in zip( durations.midi_attacks, durations): # Todo: Durations has evolved in branch `counter-dev` if dur.rest: table.rest(attak, dur.score_d) else: table.note_on( time=attak, noteval=GMDRUMS['stick'], notevel=TheoryPlayer.Vol, # table.note_on(time=attak, noteval=gmdrums['stick'], notevel=dur.velocity, score_d=dur.score_d, midi_d=dur.score_d) mtable = NoteTable(1, channel=9) # mtable.TempoSet(TheoryPlayer.Tempo) mtable.insert_table_loop(table, noloops=loop) return mtable
def __init__(self, rhythm=None, accent=None, rest=None, midi_scale=None, header=None, loop=1, rest_quenches_note=True, **def_cols): self.seq = [] self.header = header if header else None self.loopno = loop self.__rest_quenches_note = rest_quenches_note self.rhythm = rhythm self.accent = accent self.rest = rest self.midi_scale = midi_scale self.def_cols = def_cols self.target = self.seq self.table = NoteTable(100, **self.def_cols) if self.header: self.table.insert_table(self.header)
def tplay(*pcgroups, loop=1): """A function to listen to theory objects like chords, scales, and rhythm.""" comptables = NoteTable(1) comptables.program(program=TheoryPlayer._instrument, channel=TheoryPlayer.Channel) for pcgroup in pcgroups: if type(pcgroup) == str: if 'pause' in pcgroup: table = pause(pcgroup) else: raise NotImplementedError( f"tplay doesn't support '{pcgroup}' command.") else: table = compose(pcgroup, loop=loop) comptables.insert_table(table, timecatenate=True) comptables.insert_note_offs() comptables.remove_rests() comptables.remove_empty_rows() comptables.encode_table() TheoryPlayer.port.queue_table(comptables)
ch1 = Chord.from_library('D', 'sus2') ch2 = Chord.from_names('Bb D A D E') ch3 = Chord.from_library('C', 'add9') ch4 = Chord.from_library('E', 'add9') ch5 = Chord.from_library('Ab', 'major') ch6 = Chord.from_library('G', 'major') ch7 = Chord.from_library('F', 'major') ch8 = Chord.from_library('C', 'add9') arp = ChordProgArp([ch1, ch2, ch1, ch3, ch1, ch5, ch6, ch7], 5) combs = list(Combinations.generate_comb(['q', 'e'], [3, 2])) Counter = CounterBasis().tick print(len(combs)) idx = 4 comb = combs[idx] print(comb) # __debug_rhythm__(self, num) # [print(count) for count in comb.getcounts(self.Counter)] table = NoteTable(rhythm=comb.midi_delts * 8, notes=arp.randgen(), velocity=it.cycle([120, 80, 80, 80, 80]), rests=it.cycle([0, 1, 0, 0, 1]), channel=1, offset=0, repeat=16, ) table.TempoSet(tempo=140, time=0) # Printer.Theory. tprint(table) with portopen('FLUID'): play(table) # export_midifile(table, 'genrated2.mid') # Todo: invalid midi ??
def miditable(self): if not self.notes: warnings.warn("Trying to sequence partial pattern.") table = NoteTable(len(self)) if self.volume: table.__extend_table__(1) table.control('Channel Volume', self.volume) times = rationals_2_ticks(rel_to_abstime(self.rhythm)) for time, dur, note in zip(times, self.rhythm, self.notes): if dur.rest or not note: table.rest(time, dur.score_d) elif isinstance(note, PC): table.note_on(time=time, noteval=note.midi, score_d=dur.score_d, midi_f=dur.midi_scale, notevel=NoteVelocity.accent_to_velocity( dur.accent)) elif type(note) == int: table.note_on(time=time, noteval=note, score_d=dur.score_d, midi_f=dur.midi_scale, notevel=dur.velocity) elif isinstance(note, PCGroup): table.multinote(attacktick=time, notevals=note.midis, score_d=dur.score_d, midi_d=dur.midi_d, notevel=dur.velocity) # table.remove_empty_rows() return table
class Sequencer: """ This sequencer accepts rhythm as `Durations` objects. It does not take iterators. However, we can optionally send iterators for accents and rests, and these will be used to sound the notes. Otherwise these data will be taken from the `Durations` object. Notes can be iterator of `PC`. Thus, any `Scale` or `Chord` or iterators from the note generator module are allowed. """ def __init__(self, rhythm=None, accent=None, rest=None, midi_scale=None, header=None, loop=1, rest_quenches_note=True, **def_cols): self.seq = [] self.header = header if header else None self.loopno = loop self.__rest_quenches_note = rest_quenches_note self.rhythm = rhythm self.accent = accent self.rest = rest self.midi_scale = midi_scale self.def_cols = def_cols self.target = self.seq self.table = NoteTable(100, **self.def_cols) if self.header: self.table.insert_table(self.header) def sequence(self, pattern=None, rhythm=None, notes=None, accent=None, rest=None, midi_scale=None, loop=1, channel=None): if pattern: pattern = Pattern(pattern) else: pattern = Pattern(rhythm=rhythm if rhythm else self.rhythm, notes=notes) if accent: pattern.rhythm.set_accents(accent) if rest: pattern.rhythm.set_rests(rest) if midi_scale: pattern.rhythm.set_midi_scales(midi_scale) if channel: pattern.channel = channel pattern *= loop self.target.append(pattern) @contextmanager def concurrent(self): self.seq.append([]) self.target = self.seq[-1] yield self.target = self.seq @property def miditable(self): miditable = NoteTable(100, **self.def_cols) for pattern in self.seq: if isinstance(pattern, Pattern): table = pattern.miditable if pattern.channel: table['channel'] = pattern.channel miditable.insert_table(table, timecatenate=True, exclude_cols=['channel']) else: miditable.insert_table(pattern.miditable, timecatenate=True) else: writetime = miditable.maxtime for pat in pattern: table = pat.miditable if pat.channel: table['channel'] = pat.channel miditable.insert_table(table, offset=writetime, exclude_cols=['channel']) else: miditable.insert_table(table, offset=writetime) self.table.insert_table_loop(miditable, self.loopno, exclude_cols=['channel']) self.table.insert_note_offs() return self.table
rests2 = InfiniteGens.atindices([2, 4, 6]) chords = [ Chord.from_library('C', 'maj7'), Chord.from_library('A', 'sus2'), Chord.from_library('F', 'major'), Chord.from_library('F', 'minor') ] scales = [ Scale.from_library('A', 'aolean'), Scale.from_library('F', 'lydian'), Scale.from_library('G', 'mixolydian'), Scale.from_library('F', 'minor pentatonic') ] header = NoteTable(1) header.TempoSet(70) sequencer = Sequencer(header=header, rhythm=rhythm, accent=accents, rest=None, loop=16) for chord, scale in zip(chords, scales): with sequencer.concurrent(): sequencer.sequence(notes=chord, rest=rests1) sequencer.sequence(notes=meloseq(scale), channel=2) result = sequencer.miditable tprint(result) rhythm = Durations('e^ e e e e e e e')