WAS:
Re: [LAD] Devs needed for opensource virtual analog softsynth idea
..............
I wouldn't mind jumping in and work a little on a key assign/voice
stealing algorithm. Since I happen to need a better one myself for
another project, it would be nice if it is kept separate from the
private working set of the voice ( - the "state" or what a voice needs
to know about itself to render the next sample.) This would be the
preferred case anyway for efficient code generation for an arbitrary,
irregular polysynth architcture.
Suggesting the following outline for data structures:
// Voice state
// -----------
// We want to be able to autovectorize as well as CUDA'fy. Data
// elements must therefore be arranged as "structs of arrays"
// rather than "arrays of structs," so that operations on
// neighbouring data will be identical while also keeping memory
// access' in straightforward wide chunks ...
#define VOICES 16 // less than 16 will not (automatically) play well
// with SSE, because of instruction latency
typedefine struct
{
int phase[VOICES]; // current position
int freq [VOICES]; // value to be iteratively added to phase
} Oscillator;
typedefine struct
{
} Envelope;
...
...
typedefine struct
{
Oscillator osc[2]; // 2 oscillators on each voice
Oscillator lfo;
Envelope env[2]
...
} VoiceState;
// ... which all means that there is no pointer to a voice! There is
// an index though. All array elements sharing the same index also
// belongs to the same voice. Assuming we do not need more voices
// than a hundred and then some, a byte will be plenty for the index:
typedefine struct
{
unsigned char next, previous;
} VoiceList;
// Depending on where in its lifecycle a voice is, it can be more
// or less desireable to "steal" it. At first we will of course look
// for one that is idle and not in use at the moment, second best is
// one in its final fading release stage. For each stage, we will
// maintain a FIFO, changing whenever a key (or pedal) is struck
// or released. Worst case is stealing a voice the user is still
// holding his hands on. For a monotimbral synthesizer:
typedefine struct
{
// index to first VoiceList element for each que, or 0xFF if empty
unsigned char
idle,
release,
sustain,
sostenuto,
keyon;
VoiceList voice_list[VOICES];
} VoiceAssign;
/J
On Sat, 2011-01-08 at 05:07 -0500, Jeremy wrote:
On Sat, Jan 8, 2011 at 3:27 AM, Jens M Andreasen
<jens.andreasen(a)comhem.se> wrote:
On Fri, 2011-01-07 at 01:57 -0500, Jeremy wrote:
Also if you're looking for a channel stealing
algorithm, try
this:
the type of a synth engine is "synth"
typedef struct _synthblock {
_synthblock* next;
_synthblock* previous;
synth item;
} synthblock;
What is a "synthblock" here? Is that what is otherwise refered
to as a
"voice" (complete with 2 oscillators, envelopes and filter.)
Sorry, I'm not experienced with all the terminology. In this case a
"synth" would be a voice, and a synthblock is simply a voice with some
added book-keeping data. It is essentially just a node of a linked
list. It's just weird, because sometimes it behaves as a singly
linked list, and sometimes it behaves as a doubly linked list.
Jeremy