workable smnb compilation
This commit is contained in:
parent
04690d9df8
commit
0d33e1e022
8 changed files with 618 additions and 7 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -9,6 +9,8 @@ sonnum.prj
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.snm
|
||||||
|
*.snmb
|
||||||
err*.txt
|
err*.txt
|
||||||
log*.txt
|
log*.txt
|
||||||
err.txt
|
err.txt
|
||||||
|
|
|
||||||
59
pysonnum/activity.py
Normal file
59
pysonnum/activity.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import struct
|
||||||
|
|
||||||
|
class Activity:
|
||||||
|
|
||||||
|
OPCODES = {
|
||||||
|
|
||||||
|
'create': 0,
|
||||||
|
'wire': 1,
|
||||||
|
'air': 2,
|
||||||
|
'endtick': 3,
|
||||||
|
'relay': 4,
|
||||||
|
'reset': 5,
|
||||||
|
'setfreq': 6,
|
||||||
|
'setpos': 7,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
return f'{self.name.rjust(20)} | {self.OPCODES[self.name]} {self.tick_start} {self.tick_end} {self.src_node.order if self.src_node else 0} {self.trg_node.order if self.trg_node else 0} '+' '.join(str(op) for op in self.operands)
|
||||||
|
|
||||||
|
def __init__(self, sonnum, name, tick_start, tick_end, src_node, trg_node, operands):
|
||||||
|
|
||||||
|
self.sonnum = sonnum
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
self.tick_start = tick_start
|
||||||
|
self.tick_end = tick_end
|
||||||
|
self.src_node = src_node
|
||||||
|
self.trg_node = trg_node
|
||||||
|
self.operands = operands
|
||||||
|
|
||||||
|
def to_bytes(self):
|
||||||
|
|
||||||
|
if self.name in self.OPCODES:
|
||||||
|
|
||||||
|
b_opcode = self.OPCODES[self.name].to_bytes(2, byteorder="big")
|
||||||
|
b_tick_start = int(self.tick_start).to_bytes(4, byteorder="big")
|
||||||
|
b_tick_end = int(self.tick_end).to_bytes(4, byteorder="big")
|
||||||
|
|
||||||
|
if not self.src_node:
|
||||||
|
b_src_node = b'\x00' * 2
|
||||||
|
else:
|
||||||
|
b_src_node = self.src_node.order.to_bytes(2, byteorder="big")
|
||||||
|
|
||||||
|
if not self.trg_node:
|
||||||
|
b_trg_node = b'\x00' * 2
|
||||||
|
else:
|
||||||
|
b_trg_node = self.trg_node.order.to_bytes(2, byteorder="big")
|
||||||
|
|
||||||
|
b_operands = [struct.pack('>d', 0.0)] * 6
|
||||||
|
|
||||||
|
for i in range(0, 6):
|
||||||
|
if len(self.operands) > i: b_operands[i] = struct.pack('>d', self.operands[i])
|
||||||
|
|
||||||
|
return b_opcode + b_tick_start + b_tick_end + b_src_node + b_trg_node + b''.join(b_operands)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return b''
|
||||||
161
pysonnum/compiler.py
Normal file
161
pysonnum/compiler.py
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
from sonnum import Sonnum
|
||||||
|
from activity import Activity
|
||||||
|
from instruction import *
|
||||||
|
|
||||||
|
|
||||||
|
class SonnumCompiler:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.sonnum = Sonnum() # {order: name}
|
||||||
|
self.activities = []
|
||||||
|
|
||||||
|
def list_activities(self):
|
||||||
|
|
||||||
|
print('ACTIVITY LISTING')
|
||||||
|
for activity in self.activities:
|
||||||
|
print(activity)
|
||||||
|
|
||||||
|
def list_bytecode(self):
|
||||||
|
|
||||||
|
print('BYTECODE LISTING')
|
||||||
|
for activity in self.activities:
|
||||||
|
print(list(activity.to_bytes()))
|
||||||
|
|
||||||
|
def add_activity(self, name, tick_start, tick_end, src_node, trg_node, operands):
|
||||||
|
|
||||||
|
a = Activity(self.sonnum, name, tick_start, tick_end, src_node, trg_node, operands)
|
||||||
|
self.activities.append(a)
|
||||||
|
|
||||||
|
def sanitize_operand(self, operand):
|
||||||
|
|
||||||
|
try:
|
||||||
|
return str(float(operand))
|
||||||
|
except:
|
||||||
|
return str(operand)
|
||||||
|
|
||||||
|
def transpile_snm_to_py(self, snm_src):
|
||||||
|
|
||||||
|
py_src = []
|
||||||
|
|
||||||
|
for ln in snm_src.split('\n'):
|
||||||
|
|
||||||
|
tablevel = 0
|
||||||
|
|
||||||
|
while ln.startswith('\t'):
|
||||||
|
|
||||||
|
tablevel += 1
|
||||||
|
ln = ln[1:]
|
||||||
|
|
||||||
|
if ln.startswith(';'):
|
||||||
|
|
||||||
|
if ln.endswith('*'):
|
||||||
|
|
||||||
|
name = ln[1:-1]
|
||||||
|
ln = f"i_create_simple(self, self.sonnum, '{name}')"
|
||||||
|
|
||||||
|
elif ln.endswith('!'):
|
||||||
|
|
||||||
|
ticklen = int(ln[1:-1])
|
||||||
|
ln = f"i_end_tick(self, self.sonnum, {ticklen})"
|
||||||
|
|
||||||
|
elif ln.endswith('@'):
|
||||||
|
|
||||||
|
name = ln[1:-1]
|
||||||
|
ln = f"i_create_relay(self, self.sonnum, '{name}')"
|
||||||
|
|
||||||
|
elif '=>' in ln:
|
||||||
|
name_src, name_trg = ln[1:].split('=>')
|
||||||
|
ln = f"i_wire(self, self.sonnum, '{name_src}', '{name_trg}')"
|
||||||
|
|
||||||
|
elif '->' in ln:
|
||||||
|
name_src, name_trg = ln[1:].split('->')
|
||||||
|
ln = f"i_air(self, self.sonnum, '{name_src}', '{name_trg}')"
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(ln)
|
||||||
|
lst = ln[1:].split(' ')
|
||||||
|
src_node_name = lst.pop(0)
|
||||||
|
instr = lst.pop(0)
|
||||||
|
operands = [self.sanitize_operand(op) for op in lst]
|
||||||
|
ln = f"i_{instr}(self, self.sonnum, '{src_node_name}', "+', '.join(operands)+")"
|
||||||
|
|
||||||
|
ln = tablevel*'\t' + ln
|
||||||
|
py_src.append(ln)
|
||||||
|
|
||||||
|
else:
|
||||||
|
ln = tablevel*'\t' + ln
|
||||||
|
py_src.append(ln)
|
||||||
|
|
||||||
|
return '\n'.join(py_src)
|
||||||
|
|
||||||
|
def run_transpiled_code(self, py_src):
|
||||||
|
|
||||||
|
exec(py_src)
|
||||||
|
|
||||||
|
def sort_activities(self):
|
||||||
|
|
||||||
|
new = []
|
||||||
|
|
||||||
|
to_delete = []
|
||||||
|
for activity in self.activities:
|
||||||
|
|
||||||
|
if activity.name == 'endtick':
|
||||||
|
new.append(activity)
|
||||||
|
to_delete.append(activity)
|
||||||
|
|
||||||
|
for activity in to_delete:
|
||||||
|
self.activities.remove(activity)
|
||||||
|
|
||||||
|
to_delete = []
|
||||||
|
for activity in self.activities:
|
||||||
|
|
||||||
|
if activity.name == 'create':
|
||||||
|
new.append(activity)
|
||||||
|
to_delete.append(activity)
|
||||||
|
|
||||||
|
for activity in to_delete:
|
||||||
|
self.activities.remove(activity)
|
||||||
|
|
||||||
|
to_delete = []
|
||||||
|
for activity in self.activities:
|
||||||
|
|
||||||
|
if activity.name in ('wire','air'):
|
||||||
|
new.append(activity)
|
||||||
|
to_delete.append(activity)
|
||||||
|
|
||||||
|
for activity in to_delete:
|
||||||
|
self.activities.remove(activity)
|
||||||
|
|
||||||
|
self.activities.sort(key=lambda x: x.tick_start, reverse = False)
|
||||||
|
new.extend(self.activities)
|
||||||
|
self.activities = new
|
||||||
|
|
||||||
|
def compile_to_smnb(self, snm_src, fn):
|
||||||
|
|
||||||
|
py_src = self.transpile_snm_to_py(snm_src)
|
||||||
|
self.run_transpiled_code(py_src)
|
||||||
|
self.sort_activities()
|
||||||
|
self.list_activities()
|
||||||
|
|
||||||
|
bytecode = []
|
||||||
|
|
||||||
|
for activity in self.activities:
|
||||||
|
bytecode.append(activity.to_bytes())
|
||||||
|
|
||||||
|
with open(fn, 'wb') as fl:
|
||||||
|
fl.write(b''.join(bytecode))
|
||||||
|
|
||||||
|
|
||||||
|
TEST = """;44100!
|
||||||
|
;left_mic@
|
||||||
|
;right_mic@
|
||||||
|
;synth*
|
||||||
|
|
||||||
|
;synth setfreq 0 440 0.9
|
||||||
|
|
||||||
|
;synth=>left_mic
|
||||||
|
;synth=>right_mic"""
|
||||||
|
|
||||||
|
C = SonnumCompiler()
|
||||||
|
snm = C.compile_to_smnb(TEST, '../zigsonnum/test.snmb')
|
||||||
48
pysonnum/instruction.py
Normal file
48
pysonnum/instruction.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Here, s stands for the sonnum object,
|
||||||
|
# c stands for compiler object
|
||||||
|
|
||||||
|
def i_create_simple(c, s, name):
|
||||||
|
# ;name*
|
||||||
|
|
||||||
|
node = s.add_node(name)
|
||||||
|
c.add_activity('create', 0, 0, node, None, [])
|
||||||
|
|
||||||
|
def i_create_relay(c, s, name):
|
||||||
|
# ;name@
|
||||||
|
|
||||||
|
node = s.add_node(name)
|
||||||
|
c.add_activity('create', 0, 0, node, None, [])
|
||||||
|
c.add_activity('relay', 0, s.g('endtick'), node, None, [])
|
||||||
|
|
||||||
|
def i_end_tick(c, s, endtick):
|
||||||
|
# ;endtick!
|
||||||
|
c.add_activity('endtick', 0, endtick, None, None, [])
|
||||||
|
s.s('endtick', endtick)
|
||||||
|
|
||||||
|
def i_wire(c, s, src_name, trg_name):
|
||||||
|
# ;name=>name
|
||||||
|
|
||||||
|
src_node = s.node_by_name(src_name)
|
||||||
|
trg_node = s.node_by_name(trg_name)
|
||||||
|
|
||||||
|
if src_node and trg_node:
|
||||||
|
c.add_activity('wire', 0, 0, src_node, trg_node, [])
|
||||||
|
|
||||||
|
def i_air(c, s, src_name, trg_name):
|
||||||
|
# ;name->name
|
||||||
|
|
||||||
|
src_node = s.node_by_name(src_name)
|
||||||
|
trg_node = s.node_by_name(trg_name)
|
||||||
|
|
||||||
|
if src_node and trg_node:
|
||||||
|
c.add_activity('air', 0, 0, src_node, trg_node, [])
|
||||||
|
|
||||||
|
def i_pos(c, s, node_name, tick, x, y, z):
|
||||||
|
|
||||||
|
node = s.node_by_name(node_name)
|
||||||
|
c.add_activity('setpos', tick, tick, node, None, [x, y, z])
|
||||||
|
|
||||||
|
def i_setfreq(c, s, node_name, tick, freq, r_amp):
|
||||||
|
|
||||||
|
node = s.node_by_name(node_name)
|
||||||
|
c.add_activity('setfreq', tick, tick, node, None, [freq, r_amp])
|
||||||
47
pysonnum/sonnum.py
Normal file
47
pysonnum/sonnum.py
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
class SoundNode:
|
||||||
|
|
||||||
|
def __init__(self, order, name):
|
||||||
|
|
||||||
|
self.order = order
|
||||||
|
self.name = name
|
||||||
|
self.properties = dict() # {k: v}
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{self.order}:{self.name}'
|
||||||
|
|
||||||
|
def g(self, k):
|
||||||
|
return self.properties.get(k)
|
||||||
|
|
||||||
|
def s(self, k, v):
|
||||||
|
self.properties[k] = v
|
||||||
|
|
||||||
|
class Sonnum:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.nodes = dict() # {order: name}
|
||||||
|
self.properties = dict() # {k: v}
|
||||||
|
|
||||||
|
def add_node(self, name):
|
||||||
|
|
||||||
|
order = len(self.nodes)
|
||||||
|
self.nodes[name] = SoundNode(order, name)
|
||||||
|
|
||||||
|
return self.nodes[name]
|
||||||
|
|
||||||
|
def node_by_name(self, name):
|
||||||
|
|
||||||
|
for order, node in self.nodes.items():
|
||||||
|
|
||||||
|
if node.name == name:
|
||||||
|
return node
|
||||||
|
|
||||||
|
def node_by_order(self, order):
|
||||||
|
|
||||||
|
return self.nodes.get(order)
|
||||||
|
|
||||||
|
def g(self, k):
|
||||||
|
return self.properties.get(k)
|
||||||
|
|
||||||
|
def s(self, k, v):
|
||||||
|
self.properties[k] = v
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const print = std.debug.print;
|
const print = std.debug.print;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
const SoundNode = @import("soundnode.zig").SoundNode;
|
const SoundNode = @import("soundnode.zig").SoundNode;
|
||||||
const FreqAmpList = @import("freqamp.zig").FreqAmpList;
|
const FreqAmpList = @import("freqamp.zig").FreqAmpList;
|
||||||
|
|
||||||
|
|
@ -11,12 +12,27 @@ pub const Activity = struct {
|
||||||
soundnode: *SoundNode,
|
soundnode: *SoundNode,
|
||||||
operands: [6]f64 = std.mem.zeroes([6]f64),
|
operands: [6]f64 = std.mem.zeroes([6]f64),
|
||||||
|
|
||||||
|
pub fn create(allocator: Allocator, start_tick: u32, end_tick: u32, opcode: u16, soundnode: *SoundNode, operands: [6]f64) !*Activity {
|
||||||
|
|
||||||
|
const a = try allocator.create(Activity);
|
||||||
|
a.* = .{
|
||||||
|
.start_tick = start_tick,
|
||||||
|
.end_tick = end_tick,
|
||||||
|
.opcode = opcode,
|
||||||
|
.soundnode = soundnode,
|
||||||
|
.operands = operands,
|
||||||
|
};
|
||||||
|
|
||||||
|
return a;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pub fn do(self: *Activity) !void {
|
pub fn do(self: *Activity) !void {
|
||||||
switch (self.opcode) {
|
switch (self.opcode) {
|
||||||
0 => { try self.reset(); },
|
4 => { try self.relay(); },
|
||||||
1 => { try self.setfreq(); },
|
5 => { try self.reset(); },
|
||||||
2 => { try self.relay(); },
|
6 => { try self.setfreq(); },
|
||||||
3 => { try self.slide_freq(); },
|
7 => { try self.slide_freq(); },
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,265 @@ pub fn singleSineTick(st: *SoundSettings, freq: f64, t: u32, phase: f64) f64 {
|
||||||
return math.sin(st.sine_multiplier * freq * ft - phase * utility.tau);
|
return math.sin(st.sine_multiplier * freq * ft - phase * utility.tau);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
|
|
||||||
|
const allocator = std.heap.c_allocator;
|
||||||
|
|
||||||
|
// Initializing sound settings
|
||||||
|
var settings: SoundSettings = SoundSettings{};
|
||||||
|
|
||||||
|
// Creating a list of soundnodes
|
||||||
|
var soundnodes = ArrayList(*SoundNode).init(allocator);
|
||||||
|
defer soundnodes.deinit();
|
||||||
|
|
||||||
|
// Determining length of resulting audio in ticks
|
||||||
|
const start_tick: u32 = 0;
|
||||||
|
var end_tick: u32 = 44100 * 10;
|
||||||
|
|
||||||
|
// Loading the input binary code, preparing registers
|
||||||
|
const file = try std.fs.cwd().openFile("test.snmb", .{});
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const stat = try file.stat();
|
||||||
|
const buf: []u8 = try file.readToEndAlloc(allocator, stat.size);
|
||||||
|
|
||||||
|
var cursor: u32 = 0;
|
||||||
|
|
||||||
|
var opcode: u16 = 0;
|
||||||
|
var tick_start: u32 = 0;
|
||||||
|
var tick_end: u32 = 0;
|
||||||
|
var src_node: u16 = 0;
|
||||||
|
var trg_node: u16 = 0;
|
||||||
|
var op1: f64 = 0;
|
||||||
|
var op2: f64 = 0;
|
||||||
|
var op3: f64 = 0;
|
||||||
|
var op4: f64 = 0;
|
||||||
|
var op5: f64 = 0;
|
||||||
|
var op6: f64 = 0;
|
||||||
|
|
||||||
|
// Preparing to write wav data to stdout
|
||||||
|
const stdout_file = std.io.getStdOut().writer();
|
||||||
|
var bw = std.io.bufferedWriter(stdout_file);
|
||||||
|
const stdout = bw.writer();
|
||||||
|
|
||||||
|
// Writing WAV header
|
||||||
|
|
||||||
|
try stdout.writeAll("RIFF");
|
||||||
|
|
||||||
|
try stdout.writeInt(
|
||||||
|
u32,
|
||||||
|
36 + (end_tick * 2 * settings.sample_width),
|
||||||
|
Endian.little,
|
||||||
|
);
|
||||||
|
|
||||||
|
try stdout.writeAll("WAVE");
|
||||||
|
try stdout.writeAll("fmt ");
|
||||||
|
|
||||||
|
try stdout.writeInt(u32, 16, Endian.little);
|
||||||
|
try stdout.writeInt(u16, 1, Endian.little);
|
||||||
|
try stdout.writeInt(u16, 2, Endian.little);
|
||||||
|
try stdout.writeInt(u32, settings.sample_rate, Endian.little);
|
||||||
|
|
||||||
|
const block_align: u16 = @intCast(2 * settings.sample_width);
|
||||||
|
|
||||||
|
try stdout.writeInt(u32, @as(u32, block_align) * settings.sample_rate, Endian.little);
|
||||||
|
try stdout.writeInt(u16, block_align, Endian.little);
|
||||||
|
try stdout.writeInt(u16, settings.bit_depth, Endian.little);
|
||||||
|
|
||||||
|
try stdout.writeAll("data");
|
||||||
|
try stdout.writeInt(
|
||||||
|
u32,
|
||||||
|
end_tick * 2 * settings.sample_width,
|
||||||
|
Endian.little,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Setting up tick iteration
|
||||||
|
var tick: u32 = start_tick;
|
||||||
|
var amp: f64 = 0;
|
||||||
|
var sample: i24 = 0.0;
|
||||||
|
var left: *SoundNode = undefined;
|
||||||
|
var right: *SoundNode = undefined;
|
||||||
|
|
||||||
|
while (tick < end_tick) {
|
||||||
|
|
||||||
|
while (cursor < buf.len) {
|
||||||
|
|
||||||
|
opcode = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
|
||||||
|
//print("----\nOPCODE {d} :: {any}\n", .{opcode, buf[cursor..cursor+2]});
|
||||||
|
cursor += 2;
|
||||||
|
|
||||||
|
tick_start = std.mem.readVarInt(u32, buf[cursor..cursor+4], .big);
|
||||||
|
//print("TICKSTART {d} :: {any}\n", .{tick_start, buf[cursor..cursor+4]});
|
||||||
|
cursor += 4;
|
||||||
|
|
||||||
|
if (tick_start > tick) {
|
||||||
|
cursor -= 6;
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
tick_end = std.mem.readVarInt(u32, buf[cursor..cursor+4], .big);
|
||||||
|
//print("TICKEND {d} :: {any}\n", .{tick_end, buf[cursor..cursor+4]});
|
||||||
|
cursor += 4;
|
||||||
|
|
||||||
|
src_node = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
|
||||||
|
//print("SRCNODE {d} :: {any}\n", .{src_node, buf[cursor..cursor+2]});
|
||||||
|
cursor += 2;
|
||||||
|
|
||||||
|
trg_node = std.mem.readVarInt(u16, buf[cursor..cursor+2], .big);
|
||||||
|
//print("TRGNODE {d} :: {any}\n", .{trg_node, buf[cursor..cursor+2]});
|
||||||
|
cursor += 2;
|
||||||
|
|
||||||
|
op1 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP1 {d} :: {any}\n", .{op1, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
op2 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP2 {d} :: {any}\n", .{op2, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
op3 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP3 {d} :: {any}\n", .{op3, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
op4 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP4 {d} :: {any}\n", .{op4, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
op5 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP5 {d} :: {any}\n", .{op5, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
op6 = @bitCast(std.mem.readVarInt(u64, buf[cursor..cursor+8], .big));
|
||||||
|
//print("OP6 {d} :: {any}\n", .{op6, buf[cursor..cursor+8]});
|
||||||
|
cursor += 8;
|
||||||
|
|
||||||
|
// Executing opcodes
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
|
||||||
|
0 => {
|
||||||
|
const nodename = try std.fmt.allocPrint(allocator, "{d}", .{src_node});
|
||||||
|
|
||||||
|
const sn = try SoundNode.create(allocator, nodename);
|
||||||
|
//print("Added node {s} at tick {d}\n", .{nodename, tick});
|
||||||
|
try soundnodes.append(sn);
|
||||||
|
},
|
||||||
|
|
||||||
|
1 => {
|
||||||
|
const src = soundnodes.items[src_node];
|
||||||
|
const trg = soundnodes.items[trg_node];
|
||||||
|
//print("Wired nodes at tick {d}\n", .{tick});
|
||||||
|
|
||||||
|
try trg.wire_in.append(src);
|
||||||
|
},
|
||||||
|
|
||||||
|
2 => {
|
||||||
|
const src = soundnodes.items[src_node];
|
||||||
|
const trg = soundnodes.items[trg_node];
|
||||||
|
|
||||||
|
//print("Aired nodes at tick {d}\n", .{tick});
|
||||||
|
try trg.air_in.append(src);
|
||||||
|
},
|
||||||
|
|
||||||
|
3 => {
|
||||||
|
end_tick = tick_end;
|
||||||
|
//print("End tick set to {d}\n", .{end_tick});
|
||||||
|
},
|
||||||
|
|
||||||
|
else => {
|
||||||
|
|
||||||
|
const src = soundnodes.items[src_node];
|
||||||
|
const a = try Activity.create(allocator, tick_start, tick_end, opcode, src, [6]f64{op1, op2, op3, op4, op5, op6});
|
||||||
|
|
||||||
|
//print("Set activity {d} for node {d} s at tick {d}\n", .{opcode, src_node, tick});
|
||||||
|
try src.activities.append(a);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//All but left and right
|
||||||
|
|
||||||
|
for (soundnodes.items, 2..) |soundnode, i| {
|
||||||
|
|
||||||
|
for (soundnode.activities.items, 0..) |activity, j| {
|
||||||
|
|
||||||
|
if (tick <= activity.end_tick and tick >= activity.start_tick) {
|
||||||
|
try activity.do();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
soundnode.fab.increment_tick();
|
||||||
|
_ = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Left and right
|
||||||
|
|
||||||
|
for (soundnodes.items, 0..2) |soundnode, i| {
|
||||||
|
|
||||||
|
for (soundnode.activities.items, 0..) |activity, j| {
|
||||||
|
|
||||||
|
if (tick <= activity.end_tick and tick >= activity.start_tick) {
|
||||||
|
try activity.do();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
soundnode.fab.increment_tick();
|
||||||
|
_ = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculating and writing output amps
|
||||||
|
|
||||||
|
amp = 0;
|
||||||
|
|
||||||
|
left = soundnodes.items[0];
|
||||||
|
right = soundnodes.items[1];
|
||||||
|
|
||||||
|
const current_index = left.fab.current_index;
|
||||||
|
|
||||||
|
const current_fal_left = left.fab.fal_array[current_index];
|
||||||
|
|
||||||
|
for (current_fal_left.arraylist.items) |fa| {
|
||||||
|
amp += fa.r_amp * singleSineTick(&settings, fa.freq, tick, fa.phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
sample = @intFromFloat(amp * @as(f64, @floatFromInt(settings.max_amp)));
|
||||||
|
try stdout.writeInt(i24, sample, Endian.little);
|
||||||
|
|
||||||
|
amp = 0;
|
||||||
|
|
||||||
|
const current_fal_right = right.fab.fal_array[current_index];
|
||||||
|
|
||||||
|
for (current_fal_right.arraylist.items) |fa| {
|
||||||
|
amp += fa.r_amp * singleSineTick(&settings, fa.freq, tick, fa.phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
sample = @intFromFloat(amp * @as(f64, @floatFromInt(settings.max_amp)));
|
||||||
|
try stdout.writeInt(i24, sample, Endian.little);
|
||||||
|
|
||||||
|
tick += 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try bw.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nnnmain() !void {
|
||||||
|
|
||||||
//var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
//var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
//const allocator = gpa.allocator();
|
//const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,28 @@ pub const SoundNode = struct {
|
||||||
|
|
||||||
fab: FreqAmpBuffer,
|
fab: FreqAmpBuffer,
|
||||||
|
|
||||||
|
pub fn create(allocator: Allocator, name: []const u8) !*SoundNode {
|
||||||
|
|
||||||
|
const air_in = ArrayList(*SoundNode).init(allocator);
|
||||||
|
const wire_in = ArrayList(*SoundNode).init(allocator);
|
||||||
|
const activities = ArrayList(*Activity).init(allocator);
|
||||||
|
const fab = try FreqAmpBuffer.init(allocator);
|
||||||
|
|
||||||
|
const sn = try allocator.create(SoundNode);
|
||||||
|
|
||||||
|
sn.* = .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.name = name,
|
||||||
|
.air_in = air_in,
|
||||||
|
.wire_in = wire_in,
|
||||||
|
.activities = activities,
|
||||||
|
.fab = fab,
|
||||||
|
};
|
||||||
|
|
||||||
|
return sn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, name: []const u8) !SoundNode {
|
pub fn init(allocator: Allocator, name: []const u8) !SoundNode {
|
||||||
|
|
||||||
const air_in = ArrayList(*SoundNode).init(allocator);
|
const air_in = ArrayList(*SoundNode).init(allocator);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue