Node arrays
Polyphony in one line — eight instances, one compiled function, three connection shapes.
Anyone building an instrument rather than an effect.
node voices = Voice[8];Eight independent instances of one processor, each with its own state. The compiler emits one function and the graph runs it eight times a frame against eight different state pointers — so eight voices cost eight times the arithmetic and nothing times the code.
A voice is a complete little instrument#
One voice may contain an oscillator, an envelope and a filter. Playing a second note should not reset the first note's phase or envelope. A node array gives each instance separate state while letting you describe the voice once.
Creating eight instances does not itself decide which MIDI note reaches which
voice. The host or event routing still supplies the per-voice pitch and gate.
When the outputs are summed, allow headroom: eight voices can be much louder
than one. Multiplying the sum by 1.0f / 8.0f is a conservative starting point,
although perceived loudness depends on the material.
Why this matters more than it looks#
A voice written this way is just a processor. It has float phase; because it
has one phase.
The alternative is what a language without node arrays forces: the same job
inside a single processor as a for (wrap<8> v) loop over eight parallel
arrays — phase[v], env[v], lp[v] — where every mistake in the indexing
is a bug you hear rather than one the compiler catches.
Three connection shapes#
They are exactly the three a polyphonic patch needs:
voicePitch -> voices.pitch | N to N, element by element |
modWheel -> voices.bright | 1 to N, broadcast to every instance |
voices.out -> mix.in | N to 1, summed — which is what a mixer is |
Anything else is a size the author did not mean, and is rejected. One instance
can be addressed on its own as voices[3].out.
Nothing downstream knows#
Instances are expanded when the graph is lowered, so voices[3] is a node like
any other to the runtime, the block renderer and the exporter.
A polyphonic synth therefore exports to an object file with no extra
machinery: examples/poly_graph.pole is an eight-voice instrument whose object
holds two functions.