conserving for now
This commit is contained in:
parent
1981f243ed
commit
89952cf8f6
7 changed files with 205 additions and 86 deletions
|
|
@ -2,84 +2,148 @@ import random
|
|||
|
||||
class PianoString:
|
||||
|
||||
def __init__(self, s, note, i):
|
||||
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
|
||||
|
||||
self.basefreq = self.s.note(note)
|
||||
self.primary_gain = 0.4
|
||||
|
||||
self.mod = self.s.node()
|
||||
self.node = self.s.node()
|
||||
|
||||
self.node.setpos(0, -10.0+i, 0, 0)
|
||||
|
||||
self.node.setbasefreq(0, self.basefreq)
|
||||
self.node.setgain(0, self.primary_gain)
|
||||
|
||||
self.mod.setbasefreq(0, 10)
|
||||
self.mod.setgain(0, 0.8)
|
||||
self.node.fmsetup(0, self.basefreq, 0.009)
|
||||
self.node.setskew(0, 0.3)
|
||||
|
||||
self.node.setadsrgain(0, 1)
|
||||
self.node.setadsrsustain(0, 0.2)
|
||||
|
||||
self.s.wire(self.mod, self.node)
|
||||
self.s.air(self.node, [self.s.left, self.s.right])
|
||||
|
||||
def gain(self, starttick, gain):
|
||||
|
||||
self.node.setgain(starttick, gain)
|
||||
|
||||
def play(self, starttick, endtick):
|
||||
|
||||
keyhold_endtick = endtick
|
||||
endtick += self.s.sec(0.3)
|
||||
|
||||
self.node.adsr(starttick, endtick,
|
||||
self.s.sec(0.03),
|
||||
self.s.sec(0.03),
|
||||
self.s.sec(0.36),
|
||||
keyhold_endtick - starttick,
|
||||
keyhold_endtick - starttick + self.s.sec(0.3))
|
||||
|
||||
#self.mod.sine(starttick, endtick)
|
||||
#self.node.fm(starttick, endtick)
|
||||
self.node.sine(starttick, endtick, 0.2)
|
||||
self.node.skewsine(starttick, endtick, 0.3)
|
||||
self.node.square(starttick, endtick, 0.04)
|
||||
|
||||
self.node.adsr(starttick, endtick,
|
||||
self.s.sec(0.067),
|
||||
self.s.sec(0.07),
|
||||
self.s.sec(0.09),
|
||||
self.s.sec(0.1),
|
||||
self.s.sec(0.2))
|
||||
|
||||
self.node.whitenoise(starttick, endtick, 0.01)
|
||||
self.node.triangle(starttick, endtick, 0.2)
|
||||
|
||||
|
||||
def playsec(self, start, end):
|
||||
|
||||
self.play(self.s.sec(start), self.s.sec(end))
|
||||
|
||||
|
||||
notes = 'CDEFGAB'
|
||||
octaves = '345'
|
||||
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)
|
||||
s.setup(s.sec(60))
|
||||
|
||||
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]
|
||||
|
||||
S = PianoString(s, note, 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))
|
||||
|
||||
S.playsec(i, i+1.4)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -8,16 +8,17 @@ sn = s.node(1)
|
|||
;0 sn.@setfreq(0, 4)
|
||||
;0-10 sn.sine()
|
||||
|
||||
sn2 = s.node(2)
|
||||
sn2 = s.node(3)
|
||||
|
||||
;sn:0 >> sn2:10
|
||||
|
||||
;0 sn2.@wire_lr()
|
||||
;0 sn2.@setfreq(0,400)
|
||||
;0 sn2.@setfreq(0, note("C4"))
|
||||
;0 sn2.@setfreq(1,800)
|
||||
|
||||
;0-10 sn2:10:-1/1 ::> fp(0):396/404
|
||||
;0-10 sn2:10:-1/1 ::> fp(1):795/806
|
||||
;0-10 sn2:10:-1/1 ::> fp(0):note("A5")-10/note("A5")+10
|
||||
;0-10 sn2:10:-1/1 ::> fp(0):note("E4")-10/note("E4")+10
|
||||
;0-10 sn2:10:-1/1 ::> fp(1):note("C6")-10/note("C6")+10
|
||||
|
||||
;0 sn2.setpin(40, 0.9)
|
||||
;0 sn2.setpin(41, 0.4)
|
||||
|
|
@ -25,5 +26,7 @@ sn2 = s.node(2)
|
|||
;0-10 sn2:10:-1/1 ::> 35:0.1/0.9
|
||||
;0-10 sn2.adsr(sec(0.1), sec(0.2), sec(0.3), sec(0.4), sec(0.5))
|
||||
|
||||
;0-10 sn2.triangle(0.5)
|
||||
;0-10 sn2.triangle(0.4)
|
||||
;0-10 sn2.sine(0.5)
|
||||
;0-10 sn2.sawtooth(0.04)
|
||||
;0-10 sn2.whitenoise(0.004)
|
||||
|
|
@ -48,29 +48,29 @@ class SonnumCompiler:
|
|||
if '=>' in ln:
|
||||
|
||||
name_src, name_trg = ln[1:].split('=>')
|
||||
ln = f'self.add_activity("link", 0, 0, {name_src}, {name_trg}, [0, 1])'
|
||||
ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [0, 1])'
|
||||
|
||||
elif '->' in ln:
|
||||
|
||||
name_src, name_trg = ln[1:].split('->')
|
||||
ln = f'self.add_activity("link", 0, 0, {name_src}, {name_trg}, [0, 2])'
|
||||
ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [0, 2])'
|
||||
|
||||
elif '=/>' in ln:
|
||||
|
||||
name_src, name_trg = ln[1:].split('=/>')
|
||||
ln = f'self.add_activity("unlink", 0, 0, {name_src}, {name_trg}, [0, 1])'
|
||||
ln = f'{name_src}.act("unlink", 0, 0, {name_src}, {name_trg}, [0, 1])'
|
||||
|
||||
elif '-/>' in ln:
|
||||
|
||||
name_src, name_trg = ln[1:].split('-/>')
|
||||
ln = f'self.add_activity("unlink", 0, 0, {name_src}, {name_trg}, [0, 2])'
|
||||
ln = f'{name_src}.act("unlink", 0, 0, {name_src}, {name_trg}, [0, 2])'
|
||||
|
||||
elif '>>' in ln:
|
||||
|
||||
name_src, name_trg = ln[1:].split('>>')
|
||||
name_src, pin_src = name_src.split(':')
|
||||
name_trg, pin_trg = name_trg.split(':')
|
||||
ln = f'self.add_activity("link", 0, 0, {name_src}, {name_trg}, [{pin_src}, {pin_trg}])'
|
||||
ln = f'{name_src}.act("link", 0, 0, {name_src}, {name_trg}, [{pin_src}, {pin_trg}])'
|
||||
|
||||
elif '::>' in ln:
|
||||
tickdata, cmd = ln[1:].split(' ',1)
|
||||
|
|
@ -85,7 +85,7 @@ class SonnumCompiler:
|
|||
pin_trg, rangepair_trg = name_trg.split(':')
|
||||
from_src, from_trg = rangepair_src.split('/')
|
||||
to_src, to_trg = rangepair_trg.split('/')
|
||||
ln = f'self.add_activity("rerange", sec({starttick}), sec({endtick}), {name_src}, {name_src}, [{pin_src}, {pin_trg}, {from_src}, {from_trg}, {to_src}, {to_trg}])'
|
||||
ln = f'{name_src}.act("rerange", sec({starttick}), sec({endtick}), {name_src}, {name_src}, [{pin_src}, {pin_trg}, {from_src}, {from_trg}, {to_src}, {to_trg}])'
|
||||
|
||||
elif ':>' in ln:
|
||||
tickdata, cmd = ln[1:].split(' ',1)
|
||||
|
|
@ -97,7 +97,7 @@ class SonnumCompiler:
|
|||
endtick = starttick
|
||||
name_src, pin_trg = cmd.split(':>')
|
||||
name_src, pin_src = name_src.split(':')
|
||||
ln = f'self.add_activity("copy", sec({starttick}), sec({endtick}), {name_src}, None, [{pin_src}, {pin_trg}])'
|
||||
ln = f'{name_src}.act("copy", sec({starttick}), sec({endtick}), {name_src}, None, [{pin_src}, {pin_trg}])'
|
||||
|
||||
else:
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ class SonnumCompiler:
|
|||
cmdparts = cmdcore.split('.')
|
||||
operand = cmdparts.pop(-1)
|
||||
nodenames = '.'.join(cmdparts)
|
||||
|
||||
print(operand, nodenames)
|
||||
if '>' in nodenames:
|
||||
src_nodename, trg_nodename = nodenames.split('>')
|
||||
else:
|
||||
|
|
@ -128,7 +128,7 @@ class SonnumCompiler:
|
|||
ln = f'{src_nodename}.{operand}(sec({starttick}), sec({endtick}), [{cmdargs}])'
|
||||
|
||||
else:
|
||||
ln = f'self.add_activity("{operand}", sec({starttick}), sec({endtick}), {src_nodename}, {trg_nodename}, [{cmdargs}])'
|
||||
ln = f'{src_nodename}.act("{operand}", sec({starttick}), sec({endtick}), {src_nodename}, {trg_nodename}, [{cmdargs}])'
|
||||
|
||||
ln = tablevel*'\t' + ln
|
||||
py_src.append(ln)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class Sonnum:
|
|||
self.left = self.relay()
|
||||
self.right = self.relay()
|
||||
|
||||
self.left.act("setpos", 0, 0, self.left, None, [0.3, 0, 0])
|
||||
self.right.act("setpos", 0, 0, self.right, None, [-0.3, 0, 0])
|
||||
self.left.act("setpos", 0, 0, self.left, None, [-0.3, 0, 0])
|
||||
self.right.act("setpos", 0, 0, self.right, None, [0.3, 0, 0])
|
||||
|
||||
def add_node(self, name, freq_q):
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from .notes import *
|
||||
|
||||
R_AMP = 0
|
||||
WIRE_IN = 1
|
||||
AIR_IN = 2
|
||||
|
|
@ -28,6 +30,12 @@ def sp(freq_no):
|
|||
def sec(seconds):
|
||||
return seconds * 44100
|
||||
|
||||
def note(note):
|
||||
return note_to_freq(note)
|
||||
|
||||
def tick(ticks):
|
||||
return ticks / 44100.0
|
||||
|
||||
class SoundNode:
|
||||
|
||||
def __init__(self, sonnum, order, name):
|
||||
|
|
|
|||
|
|
@ -227,3 +227,46 @@ pub fn whitenoise(self: *Activity) void {
|
|||
self.soundnode.fab.add_r_amp(final_amp);
|
||||
|
||||
}
|
||||
|
||||
// Produces a sine wave to r_amp pin
|
||||
pub fn residualsines(self: *Activity) void {
|
||||
|
||||
const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick);
|
||||
const maingain = self.soundnode.corrGain(self.operands[1]);
|
||||
|
||||
const resolution: usize = @intFromFloat(self.operands[0]);
|
||||
|
||||
var final_amp: f64 = 0;
|
||||
|
||||
const max_freq_pin = 64 + self.soundnode.freq_q;
|
||||
for (64..max_freq_pin) |freq_pin| {
|
||||
|
||||
if (self.soundnode.pins[freq_pin] > 0) {
|
||||
|
||||
const gain = self.soundnode.pins[freq_pin + 48];
|
||||
const shift = self.soundnode.pins[freq_pin + 96];
|
||||
const phase = self.soundnode.pins[freq_pin + 144];
|
||||
|
||||
const totalphase = self.soundnode.pins[33] + shift + phase;
|
||||
|
||||
for (0..resolution) |residual| {
|
||||
|
||||
const fresidual = @as(f64,@floatFromInt(residual))+1;
|
||||
const res_gain = 1 / math.pow(f64, gain, fresidual);
|
||||
|
||||
var amp = math.sin(utility.corrected_tau * (self.soundnode.pins[freq_pin]-fresidual) * current_tick - totalphase * utility.tau);
|
||||
|
||||
final_amp += maingain * res_gain * amp;
|
||||
|
||||
|
||||
amp = math.sin(utility.corrected_tau * (self.soundnode.pins[freq_pin]+fresidual) * current_tick - totalphase * utility.tau);
|
||||
|
||||
final_amp += maingain * res_gain * amp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
self.soundnode.add_r_amp(final_amp);
|
||||
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ pub const Activity = struct {
|
|||
54 => { basicsynths.skewsine(self); },
|
||||
55 => { basicsynths.pulse(self); },
|
||||
56 => { basicsynths.whitenoise(self); },
|
||||
57 => { basicsynths.residualsines(self); },
|
||||
|
||||
//100 => { generators.singenN(self); },
|
||||
150 => { generators.adsr(self); },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue