import random class PianoString: def __init__(self, s, piano, notename, note_no, string_no): self.s = s self.piano = piano self.note = notename self.note_no = note_no self.string_no = string_no self.xshift = [-0.002, 0, 0.002][string_no] self.x = (1/24.0)*note_no - 1.5 + self.xshift if string_no == 1: overtones = 10 else: overtones = 8 self.node = self.s.node(overtones) for reflector in self.piano.reflectors: pass #;self.node -> reflector ;0 self.node.@air_lr() ;0 self.node.setpos(self.x, 0, 0) ;0 self.node.@setgain(0.5) fm_mod = self.piano.fm_mods[self.string_no] ;fm_mod:0 >> self.node:10 ;0 self.node.setpin(40, 0.9) ;0 self.node.setpin(41, 0.4) ;0 self.node.setpin(35, 0.3) for overtone in range(overtones): ;0 self.node.@setfreq(overtone, note(self.note)*(overtone+1)) ;0 self.node.@setfreqgain(overtone, 0.1/(overtone**1.5+1)) def play_string(self, startsec, endsec, gainmult): for overtone in range(0, 8): ovfreq = note(self.note)*(overtone+1) dispersion = (8-overtone) * 0.1 ;startsec-endsec self.node:10:-1/1 ::> fp(overtone):ovfreq-dispersion/ovfreq+dispersion attack = sec(0.05) hold = sec(0.1) decay = sec(0.5) sustain = sec(endsec - startsec) release = sec(endsec - startsec + 0.2) ;startsec-endsec+0.2 self.node.adsr(attack, hold, decay, sustain, release, gainmult) #;startsec-endsec+0.2 self.node.sine(0.3) #;startsec-endsec+0.2 self.node.skewsine(35, 0.1) #;startsec-endsec+0.2 self.node.square(0.04) #;startsec-endsec+0.2 self.node.triangle(0.4) ;startsec-endsec+0.2 self.node.residualsines(3, 0.00002) class Piano: def __init__(self, s): self.s = s notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#','G','G#','A','A#','B'] octaves = '3456' gamma = [] for o in octaves: for n in notes: gamma.append(n+o) self.fm_mods = [] self.reflectors = [] for i in range(0, 7): self.reflectors.append(self.s.relay()) ;0 self.reflectors[-1].@air_lr() ;0 self.reflectors[-1].@setgain(0.4) ;0 self.reflectors[-1].setpos(0,-1.1*i,-1.1*i) for i in range(0,3): fm_mod = self.s.node(1) ;0 fm_mod.@setfreq(0, 4*i) ;0-tick(self.s.end) fm_mod.sine() self.fm_mods.append(fm_mod) self.strings = dict() # {note: []} for i in range(0, len(gamma)): note = gamma[i] self.strings[note] = [] self.strings[note].append(self.s.PianoString(s, self, note, i, 0)) self.strings[note].append(self.s.PianoString(s, self, note, i, 1)) self.strings[note].append(self.s.PianoString(s, self, note, i, 2)) def get_nodes(self, note): if note in self.strings: return self.strings[note] def play(self, note, startsec, endsec, gainmult): for node in self.get_nodes(note): node.play_string(startsec, endsec, gainmult) ### s.setup(8) s.PianoString = PianoString P = Piano(s) if False: P.play("C4", 0, 7, 0.6) else: P.play("C4", 0, 2, 0.6) P.play("E4", 0.3, 2, 0.6) P.play("G4", 0.6, 2, 0.6) P.play("C4", 2, 3, 0.6) P.play("A4", 2, 3, 0.6) P.play("F4", 2, 3, 0.6) P.play("B3", 3, 4, 0.6) P.play("G4", 3, 4, 0.6) P.play("D4", 3, 4, 0.6) P.play("C4", 4, 5, 0.6) P.play("E4", 4, 5, 0.6) P.play("A3", 4, 5, 0.6) P.play("C5", 4, 5, 0.6)