Login / Register 0 items | $0.00 New @ KVR
jtxx000
KVRAF
 
1617 posts since 2 Dec, 2003

Postby jtxx000; Tue Jun 14, 2005 6:32 am Voice Stealing

What is the best way to implement voice stealing? Right now my idea is to have two linked lists - one for currently playing notes and one for notes that are free. When a note is played you an entry note from the free linked list and insert it at the beginnig of the playing linked list. If all the free notes are taken, then use the last entry in the playing list. To prevent clicking, add 1 ms latency to the synth and when a voice needs to be stolen start fading out the note. Is this a good approach, or is there an easier/better way of doing it?
Image
blümchen
Banned

Postby blümchen; Tue Jun 14, 2005 7:10 am

You should begin with thinking about "first note priority" or "last note priority" or "pitch related priority".

That entirely can be done with one list.

The problem is not the stealing algorithm itselfes. The problem is mostly to dynamically allocate and remap and remember the voices and exchange them without any clicks in the audio signal ...

I don't understand the 1 ms latency thingy you suggested. A synth should not have any latency.

No, it is not easy. It is rather hard to achieve (regarding the entire count and complexity of different play modi your synth finally has).
Borogove
KVRAF
 
2457 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Tue Jun 14, 2005 7:55 am

jtxx000 wrote:What is the best way to implement voice stealing?


Here's my shameful confession: I don't do anything to mask a click when a voice is stolen. I figure with 32 voices sounding, I can get away with it.

My synths maintain 32 or 64 voices, so I use pitch-based priority, and don't care about the order they were played in at all. For synths with very low polyphony, say 6 and under, order-based is generally more useful.

My steal algorithm prefers:
1. Any note that isn't the lowest note sounding, which is being doubled an octave higher. (e.g., if notes 60, 62, and 74 are sounding, then steal note 62)
2. The next-to-lowest note sounding.
Image
Don't do it my way.
jtxx000
KVRAF
 
1617 posts since 2 Dec, 2003

Postby jtxx000; Tue Jun 14, 2005 8:08 am

this is what I was talking about for the latency: http://aulos.calarts.edu/pipermail/musi ... 16954.html

but it seems if this is the easiest way to prevent clicking.
Image
jtxx000
KVRAF
 
1617 posts since 2 Dec, 2003

Postby jtxx000; Tue Jun 14, 2005 8:32 am

Borogove wrote:
jtxx000 wrote:What is the best way to implement voice stealing?


Here's my shameful confession: I don't do anything to mask a click when a voice is stolen. I figure with 32 voices sounding, I can get away with it.

My synths maintain 32 or 64 voices, so I use pitch-based priority, and don't care about the order they were played in at all. For synths with very low polyphony, say 6 and under, order-based is generally more useful.

My steal algorithm prefers:
1. Any note that isn't the lowest note sounding, which is being doubled an octave higher. (e.g., if notes 60, 62, and 74 are sounding, then steal note 62)
2. The next-to-lowest note sounding.


so do you have all your voices in a list/array and then cycle through them every sample? is there some kind of a flag for voices that aren't currently playing? wouldn't that be ineffecient?
Image
Hernan
KVRist
 
211 posts since 27 Feb, 2005

Postby Hernan; Tue Jun 14, 2005 8:42 am

Hello, interesting discussion.

I am currently at the "pen and pencil" stage of designing my soft synth. This is a first prototype, so I am just using arrays for the whole thing.

Probably for the final version I'll grab the Gonnet book and use B-trees or whatever :wink:

I am using a derivative of the "steal the last note" algorithm as seen on the example at the VST source code archive.

My idea is:

1) keep a list of the notes currently played

2) keep a list of the notes that are depressed but were stolen

3) when I need to steal a note, put the stolen note in "being stolen" mode. This means change its decay time to a 1/100sec or so

4) Put the new note in "waiting to be born" mode. This means wait 1/100 sec or so before the renderer starts to process its attack

Does this seem reasonable?

L
jtxx000
KVRAF
 
1617 posts since 2 Dec, 2003

Postby jtxx000; Tue Jun 14, 2005 8:45 am

Lorenzo333 wrote:Hello, interesting discussion.

I am currently at the "pen and pencil" stage of designing my soft synth. This is a first prototype, so I am just using arrays for the whole thing.

Probably for the final version I'll grab the Gonnet book and use B-trees or whatever :wink:

I am using a derivative of the "steal the last note" algorithm as seen on the example at the VST source code archive.

My idea is:

1) keep a list of the notes currently played

2) keep a list of the notes that are depressed but were stolen

3) when I need to steal a note, put the stolen note in "being stolen" mode. This means change its decay time to a 1/100sec or so

4) Put the new note in "waiting to be born" mode. This means wait 1/100 sec or so before the renderer starts to process its attack

Does this seem reasonable?

L

Music-Dsp wrote:Save output value at retriggering, and activate linear or exp fade out to
zerro in reasonable time.( it may be allways activated with zerro delta
value, jast set it to e.g. - (out value)/(time*48000)).


That would probably be easier...
Image
Fuzzpilz
KVRist
 
250 posts since 17 Jun, 2004, from Magdeburg

Postby Fuzzpilz; Tue Jun 14, 2005 8:52 am

Instead of killing a voice that's being stolen, you could also restart the envelopes without resetting them to zero first, not reset oscillator phases, and so on. That's what I do - might cause problems in some situations, though, I suppose. As for voice choice - my method currently doesn't regard pitch at all, but simply chooses the oldest voice that is already releasing; and if no voices are releasing, just the oldest. Seems to work fine.

The exact way I do it is this: I have a linked list of voices; when a new note is triggered, the number of voices in the list is counted. If there are fewer than maximally allowed, create a new instance of the voice class and insert it at the head of the list. Otherwise, go through the list from head to tail, setting a pointer to each voice you pass if that voice is releasing; if that pointer is still null after this, set it to the last voice in the list. Move the voice chosen this way back to the head of the list and retrigger it with the new note.
Borogove
KVRAF
 
2457 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Tue Jun 14, 2005 9:34 am

jtxx000 wrote:so do you have all your voices in a list/array and then cycle through them every sample? is there some kind of a flag for voices that aren't currently playing? wouldn't that be ineffecient?


I maintain a live list, so processing is efficient. I can't remember if I scan the whole array for free voices when allocating a new one, or if I maintain a separate free list - efficiency of note-on isn't as important because it happens relatively rarely.
Image
Don't do it my way.
Borogove
KVRAF
 
2457 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Tue Jun 14, 2005 9:39 am

Fuzzpilz wrote:As for voice choice - my method currently doesn't regard pitch at all, but simply chooses the oldest voice that is already releasing; and if no voices are releasing, just the oldest. Seems to work fine.


Yeah, that works well. Looking for notes which are releasing neatly avoids the usual problems with straight oldest-note stealing.
Image
Don't do it my way.
Borogove
KVRAF
 
2457 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Tue Jun 14, 2005 9:41 am

Lorenzo333 wrote:3) when I need to steal a note, put the stolen note in "being stolen" mode. This means change its decay time to a 1/100sec or so

4) Put the new note in "waiting to be born" mode. This means wait 1/100 sec or so before the renderer starts to process its attack


That means that new notes are delayed by 10ms. I don't agree with whatsisname that 1ms additional latency is a serious problem, but 10ms additional latency surely is.
Image
Don't do it my way.
Hernan
KVRist
 
211 posts since 27 Feb, 2005

Postby Hernan; Tue Jun 14, 2005 9:52 am

Borogove wrote:That means that new notes are delayed by 10ms. I don't agree with whatsisname that 1ms additional latency is a serious problem, but 10ms additional latency surely is.


Good point. I'll change the times to 1/2 ms and see what happens. Hopefully a zeroing of the volume in 1/2ms will not cause a click?

The other option would be to not have a "waiting to be born" stage for notes, and just have a short period of time where the stolen note and the new note play at the same time.

What do you think?

Thanks,

L

PS: Good idea about saving the current state of the envelopes of the stolen notes; I'll keep that in mind for version 0.2 of the synth.
blümchen
Banned

Postby blümchen; Tue Jun 14, 2005 9:59 am

Borogove wrote:That means that new notes are delayed by 10ms. I don't agree with whatsisname that 1ms additional latency is a serious problem, but 10ms additional latency surely is.


You don't need to agree.
But it shows, how "lapidar" your synthesizer engineering experiences probably are. (Now you can actually extend your signature this way :hihi: ).
blümchen
Banned

Postby blümchen; Tue Jun 14, 2005 10:02 am

:hug: Borogove and me.
Borogove
KVRAF
 
2457 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Tue Jun 14, 2005 11:21 am

upsidedown wrote:But it shows, how "lapidar" your synthesizer engineering experiences probably are.


Lapidar?
Image
Don't do it my way.
Next

Moderator: KVR Moderators (Main)

Return to DSP and Plug-in Development