diff --git a/.gitignore b/.gitignore index fd6700b..d79d172 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ # https://www.atlassian.com/git/tutorials/saving-changes/gitignore sonnum.prj +sonnum # Node artifact files node_modules/ diff --git a/pysonnum/activity.py b/pysonnum/activity.py index d348d93..4a79f62 100644 --- a/pysonnum/activity.py +++ b/pysonnum/activity.py @@ -22,6 +22,7 @@ OPCODES = { 'slidephase': 17, 'slideskew': 18, 'slidepos': 19, + 'pulse': 20, } class Activity: diff --git a/pysonnum/soundnode.py b/pysonnum/soundnode.py index 94b8cdc..d35f528 100644 --- a/pysonnum/soundnode.py +++ b/pysonnum/soundnode.py @@ -64,4 +64,7 @@ class SoundNode: self.act('slideskew', start_tick, end_tick, self, None, [startskew, endskew]) def slidepos(self, start_tick, end_tick, sx, sy, sz, ex, ey, ez): - self.act('slidepos', start_tick, end_tick, self, None, [sx, sy, sz, ex, ey, ez]) \ No newline at end of file + self.act('slidepos', start_tick, end_tick, self, None, [sx, sy, sz, ex, ey, ez]) + + def pulse(self, start_tick, end_tick): + self.act('pulse', start_tick, end_tick, self, None, []) \ No newline at end of file diff --git a/sineex.py b/sineex.py index b554ce3..e51ae21 100644 --- a/sineex.py +++ b/sineex.py @@ -1,4 +1,4 @@ -ln = s.sec(6) +ln = s.sec(2) s.endtick(ln) @@ -9,12 +9,18 @@ left.setpos(0, -0.3, 0, 0) right.setpos(0, 0.3, 0, 0) tr1 = s.node() -tr1.setbasefreq(0, s.note("E4")) -tr1.slidebasefreq(s.sec(2), s.sec(4), s.note("E4"), s.note("C4")) -tr1.setbasefreq(s.sec(4), s.note("C4")) -tr1.sine(0, ln) -tr1.setgain(0, 0.3) +tr2 = s.node() -tr1.setpos(0, 100, 0, 0) -s.wire(tr1, [left]) -s.wire(tr1, [right]) \ No newline at end of file +tr1.setbasefreq(0, s.note("E4")) +tr1.setgain(0, 0.45) +tr1.setskew(0, 0.3) +tr1.square(0, ln) + +tr2.setbasefreq(0, s.note("E4")) +tr2.setgain(0, 0.4) +tr2.setphase(0, 0.4) +tr1.setskew(0, 0.3) +tr2.square(0, ln) + +s.wire(tr1, left) +s.wire(tr2, right) \ No newline at end of file diff --git a/snm.py b/snm.py index 65b2336..0c62f57 100644 --- a/snm.py +++ b/snm.py @@ -10,8 +10,9 @@ parser = argparse.ArgumentParser(description="Sonnum - the additive synthesizer. parser.add_argument('input_snm_fn', metavar="INPUT", nargs='?', type=str, help="Input *.snm source file", default='') -parser.add_argument('-t', '--transpile', help="View the transpiled python code", action='store_true') parser.add_argument('-b', '--bytecode', help="View the resulting bytecode", action='store_true') +parser.add_argument('-r', '--rebuild', help="Rebuild the executable", action='store_true') +parser.add_argument('-z', '--zigrun', help="Zig run instead of executable", action='store_true') parser.add_argument('-o', '--output', metavar='FN', help="Synthesize to given wav filenames", type=str) @@ -21,30 +22,34 @@ def run(): args = parser.parse_args() C = SonnumCompiler() - fn = args.input_snm_fn - with open(fn, 'r', encoding = 'utf-8') as fl: - snm = fl.read() + if args.rebuild: + os.system(f'zig build-exe zigsonnum/sonnum.zig -lc -OReleaseFast') - if args.transpile: - py_snm = C.transpile_snm_to_py(snm) - print('TRANSPILED CODE') - print(py_snm) + else: + fn = args.input_snm_fn - elif args.bytecode: - py_snm = C.transpile_snm_to_py(snm) - C.run_transpiled_code(py_snm) - C.sort_activities() - C.list_activities() - - elif args.output: - C.compile_to_smnb(snm, 'source.snmb') - os.system(f'./zigsonnum/sonnum > {args.output}') - - else: - C.compile_to_smnb(snm, 'source.snmb') - os.system(f'zig run zigsonnum/sonnum.zig -lc -OReleaseFast > {fn}.wav') - #os.system(f'zig run zigsonnum/sonnum.zig -lc > {fn}.wav') + with open(fn, 'r', encoding = 'utf-8') as fl: + snm = fl.read() + + if args.bytecode: + py_snm = C.transpile_snm_to_py(snm) + C.run_transpiled_code(py_snm) + C.sort_activities() + C.list_activities() + + elif args.output: + C.compile_to_smnb(snm, 'source.snmb') + os.system(f'./sonnum > {args.output}') + + elif args.zigrun: + C.compile_to_smnb(snm, 'source.snmb') + os.system(f'zig run zigsonnum/sonnum.zig -lc > {fn}.wav') + + else: + C.compile_to_smnb(snm, 'source.snmb') + os.system(f'./sonnum > {fn}.wav') + #os.system(f'zig run zigsonnum/sonnum.zig -lc > {fn}.wav') if __name__ == '__main__': run() \ No newline at end of file diff --git a/zigsonnum/activity.zig b/zigsonnum/activity.zig index bc9d990..7425fe8 100644 --- a/zigsonnum/activity.zig +++ b/zigsonnum/activity.zig @@ -49,6 +49,7 @@ pub const Activity = struct { 17 => { try self.slidephase(); }, 18 => { try self.slideskew(); }, 19 => { self.slidepos(); }, + 20 => { self.pulse(); }, else => {}, } } @@ -175,9 +176,9 @@ pub const Activity = struct { const phase = self.soundnode.g("phase"); const period = 44100 / freq; - const tp = current_tick / period; + const tp = (current_tick - (period * phase)) / period; - const amp = r_amp * (@abs(2 * (2 * ( tp - @floor(tp + 0.5) ) )) - 1 - (phase * utility.tau)); + const amp = r_amp * (@abs(2 * (2 * ( tp - @floor(tp + 0.5) ) )) - 1); self.soundnode.fab.add_r_amp(amp); } @@ -209,9 +210,9 @@ pub const Activity = struct { const phase = self.soundnode.g("phase"); const period = 44100 / freq; - const tp = current_tick / period; + const tp = (current_tick - (period * phase)) / period; - const amp = r_amp * (2 * (tp - @floor(0.5+tp) - (phase * utility.tau))); + const amp = r_amp * (2 * (tp - @floor(0.5+tp))); self.soundnode.fab.add_r_amp(amp); } @@ -328,4 +329,24 @@ pub const Activity = struct { } + pub fn pulse(self: *Activity) void { + + const current_tick: f64 = @floatFromInt(self.soundnode.fab.current_tick); + + const freq = self.soundnode.g("basefreq"); + const r_amp = self.soundnode.g("gain"); + const phase = self.soundnode.g("phase"); + + const period = 44100 / freq; + const tp = current_tick / period; + const tp_detract = (current_tick - (period * phase)) / period; + + const amp =2 * (tp - @floor(0.5+tp)); + const amp_detract = 2 * (tp_detract - @floor(0.5+tp_detract)); + + const final_amp = r_amp * (amp - amp_detract); + + self.soundnode.fab.add_r_amp(final_amp); + + } }; \ No newline at end of file