conserving for now

This commit is contained in:
aprilnightk 2025-09-21 14:01:29 +03:00
parent 1981f243ed
commit 89952cf8f6
7 changed files with 205 additions and 86 deletions

View file

@ -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.basefreq = self.s.note(note)
self.primary_gain = 0.4
self.piano = piano
self.note = notename
self.note_no = note_no
self.string_no = string_no
self.mod = self.s.node()
self.node = self.s.node()
self.node.setpos(0, -10.0+i, 0, 0)
self.xshift = [-0.002, 0, 0.002][string_no]
self.x = (1/24.0)*note_no - 1.5 + self.xshift
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])
if string_no == 1:
overtones = 10
else:
overtones = 8
def gain(self, starttick, gain):
self.node = self.s.node(overtones)
self.node.setgain(starttick, gain)
def play(self, starttick, endtick):
for reflector in self.piano.reflectors:
pass
#;self.node -> reflector
;0 self.node.@air_lr()
keyhold_endtick = endtick
endtick += self.s.sec(0.3)
;0 self.node.setpos(self.x, 0, 0)
;0 self.node.@setgain(0.5)
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)
fm_mod = self.piano.fm_mods[self.string_no]
;fm_mod:0 >> self.node:10
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):
;0 self.node.setpin(40, 0.9)
;0 self.node.setpin(41, 0.4)
;0 self.node.setpin(35, 0.3)
self.play(self.s.sec(start), self.s.sec(end))
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))
notes = 'CDEFGAB'
octaves = '345'
gamma = []
for o in octaves:
for n in notes:
gamma.append(n+o)
s.setup(s.sec(60))
for i in range(0, len(gamma)):
note = gamma[i]
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:
S = PianoString(s, note, i)
S.playsec(i, i+1.4)
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)

View file

@ -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.sine(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)

View file

@ -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)

View file

@ -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):

View file

@ -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):

View file

@ -226,4 +226,47 @@ 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);
}

View file

@ -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); },