If you have a problem or need to report a bug please email : support@dsprobotics.com
There are 3 sections to this support area:
DOWNLOADS: access to product manuals, support files and drivers
HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects
USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here
NEW REGISTRATIONS - please contact us if you wish to register on the forum
Users are reminded of the forum rules they sign up to which prohibits any activity that violates any laws including posting material covered by copyright
Splines and DSP
39 posts
• Page 1 of 4 • 1, 2, 3, 4
Splines and DSP
Those of you who had a look at my spline class, will have noticed that it comes with some comfortable features. For this topic, I will concentrate on three of them:
1) I can set each section (the line between two control nodes) to be constructed from a specific amount of segments (basically short lines that create the curvature of the spline).
2) I can get normalized output and even output mapped to a certain range, both from x and y axes seperately or combined. (The result is an array)
3) The grid on which the splines are created also can be used normalized (it is then a grid ranging from -1 to +1 on both axes no matter the ratio of the drawing, meaning you can draw a spline on a rectangular grid, but its values are always perfectly square)
Now the downside for my current thinking: segments of course can't be fractions. They have to be integers (1 to +inf).
That said:
If I create a spline with 4 control points, it would mimic a standard adsr, except that they all would be in the same distance from each other. However, since it calculates the sections between the control points, I have to deal with 3 sections. To define the number of segments that each section is using, I would need to know, what the dsp section expects to get. For example, it might want to have sample-based timing, so that each value of the array corresponds to an envelope value per sample. This would rule out a lot of lengths if the sections can only be composed of integer segments and all sections have to share the same number of segments (There is no way to have the first section use 10 segments, and the second 30, both have to use either 10 or 30).
Also, the arrays would be enormous for longer envelopes, like 176,000 values for 4 seconds at 44.1kHz sample rate.
What would be needed to get an envelope that follows close to exactly the curvature of the visually created envelope, on the DSP side?
Also, how would you work with such green or RubyValue arrays on the DSP side, especially as envelopes need to affect the polystream?
Is there anyone among you that could create an envelope creator on the DSP side, that expects an array of values, but is not bound to ADSR (aka freeform envelopes, for example an envelope composed from a spline with 12 control nodes, where the basis is time, not envelope stages, yet with switchable sustain at any of the nodes if wanted)?
Since interpolation within the DSP module would counter the idea of having a freely designed spline envelope, is it even possible to work with such huge arrays? Maybe in the form of on-the-fly generated waves that are read from memory?
I would love to work on something like this, but I can only do the user interaction part, up until the array of values are ready to be delivered. So I hope to get some serious help here, even if it means that I have to make severe changes to this initial design.
Thank you!
1) I can set each section (the line between two control nodes) to be constructed from a specific amount of segments (basically short lines that create the curvature of the spline).
2) I can get normalized output and even output mapped to a certain range, both from x and y axes seperately or combined. (The result is an array)
3) The grid on which the splines are created also can be used normalized (it is then a grid ranging from -1 to +1 on both axes no matter the ratio of the drawing, meaning you can draw a spline on a rectangular grid, but its values are always perfectly square)
Now the downside for my current thinking: segments of course can't be fractions. They have to be integers (1 to +inf).
That said:
If I create a spline with 4 control points, it would mimic a standard adsr, except that they all would be in the same distance from each other. However, since it calculates the sections between the control points, I have to deal with 3 sections. To define the number of segments that each section is using, I would need to know, what the dsp section expects to get. For example, it might want to have sample-based timing, so that each value of the array corresponds to an envelope value per sample. This would rule out a lot of lengths if the sections can only be composed of integer segments and all sections have to share the same number of segments (There is no way to have the first section use 10 segments, and the second 30, both have to use either 10 or 30).
Also, the arrays would be enormous for longer envelopes, like 176,000 values for 4 seconds at 44.1kHz sample rate.
What would be needed to get an envelope that follows close to exactly the curvature of the visually created envelope, on the DSP side?
Also, how would you work with such green or RubyValue arrays on the DSP side, especially as envelopes need to affect the polystream?
Is there anyone among you that could create an envelope creator on the DSP side, that expects an array of values, but is not bound to ADSR (aka freeform envelopes, for example an envelope composed from a spline with 12 control nodes, where the basis is time, not envelope stages, yet with switchable sustain at any of the nodes if wanted)?
Since interpolation within the DSP module would counter the idea of having a freely designed spline envelope, is it even possible to work with such huge arrays? Maybe in the form of on-the-fly generated waves that are read from memory?
I would love to work on something like this, but I can only do the user interaction part, up until the array of values are ready to be delivered. So I hope to get some serious help here, even if it means that I have to make severe changes to this initial design.
Thank you!
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Splines and DSP
Interesting. The Multi Stage Envelope module is kinda doing what you want to achieve no? Have you looked at that?
- adamszabo
- Posts: 667
- Joined: Sun Jul 11, 2010 7:21 am
Re: Splines and DSP
It’s a funny thing but I’ve been thinking about using Martin’s curve drawing code for an envelope generator. I adapted his code in my recent Quilcom Phadex project, but this was for creating single cycle waveforms.
Envelopes can normally be relatively slow compared to audio stream rates. Apart from granular synthesis they typically hop 16 samples.
My starting approach (which I haven’t even tried) would be to assign segments of the curve to envelope phases. So you have the attack phase, the decay phase, the sustain or hold phase and the release phase. Each segment could be any shape so you could have 4 points on the attack “area”, 3 in the decay area and 3 in the release area. The time for each phase would be independently adjustable, so you could have a fast and detailed attack and a slower decay etc.
The curve would be translated into a float array with maybe 2000 elements. This array would be read out by an array to poly prim, with linear interpolation. The important thing is that the readout rate of the array would be variable, on a per-phase basis. So the first (attack) phase would be read out fast, then the indexing oscillator could slow down for the decay phase and so on. The break points in this scheme would be fixed, so the first quarter of the graph would be for attack, the second for decay, the third for sustain and the final one for release.
You would have a graph and four time knobs to get pretty much any useful envelope shape and duration you wanted. The graph display would not reflect the time element for each phase.
The index counter rate would switch over based on the index value, so with a total of 2000 elements the index rate would switch over at 500, 1000, and 1500, assuming an equal proportion of the array was assigned to each envelope phase.
One big issue I can see is re-triggering. An envelope usually has “soft” retriggering, so if re-triggered it will carry on from the current value and restart the attack phase from that value, rather than from zero every time (to avoid sudden changes in level which cause horrible clicks).
I don’t know if that helps or not, but I like the idea for sure, and would be happy to contribute. It would be great to have a really cool graphical envelope generator…
Cheers
Spogg
Envelopes can normally be relatively slow compared to audio stream rates. Apart from granular synthesis they typically hop 16 samples.
My starting approach (which I haven’t even tried) would be to assign segments of the curve to envelope phases. So you have the attack phase, the decay phase, the sustain or hold phase and the release phase. Each segment could be any shape so you could have 4 points on the attack “area”, 3 in the decay area and 3 in the release area. The time for each phase would be independently adjustable, so you could have a fast and detailed attack and a slower decay etc.
The curve would be translated into a float array with maybe 2000 elements. This array would be read out by an array to poly prim, with linear interpolation. The important thing is that the readout rate of the array would be variable, on a per-phase basis. So the first (attack) phase would be read out fast, then the indexing oscillator could slow down for the decay phase and so on. The break points in this scheme would be fixed, so the first quarter of the graph would be for attack, the second for decay, the third for sustain and the final one for release.
You would have a graph and four time knobs to get pretty much any useful envelope shape and duration you wanted. The graph display would not reflect the time element for each phase.
The index counter rate would switch over based on the index value, so with a total of 2000 elements the index rate would switch over at 500, 1000, and 1500, assuming an equal proportion of the array was assigned to each envelope phase.
One big issue I can see is re-triggering. An envelope usually has “soft” retriggering, so if re-triggered it will carry on from the current value and restart the attack phase from that value, rather than from zero every time (to avoid sudden changes in level which cause horrible clicks).
I don’t know if that helps or not, but I like the idea for sure, and would be happy to contribute. It would be great to have a really cool graphical envelope generator…
Cheers
Spogg
-
Spogg - Posts: 3358
- Joined: Thu Nov 20, 2014 4:24 pm
- Location: Birmingham, England
Re: Splines and DSP
adamszabo wrote:Interesting. The Multi Stage Envelope module is kinda doing what you want to achieve no? Have you looked at that?
I don't understand anything of what is going on there regarding DSP. So unfortunately, yes I had a look at it several times over the last years, but no, it doesn't really help me.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Splines and DSP
Spogg wrote:It’s a funny thing but I’ve been thinking about using Martin’s curve drawing code for an envelope generator. I adapted his code in my recent Quilcom Phadex project, but this was for creating single cycle waveforms.
Envelopes can normally be relatively slow compared to audio stream rates. Apart from granular synthesis they typically hop 16 samples.
My starting approach (which I haven’t even tried) would be to assign segments of the curve to envelope phases. So you have the attack phase, the decay phase, the sustain or hold phase and the release phase. Each segment could be any shape so you could have 4 points on the attack “area”, 3 in the decay area and 3 in the release area. The time for each phase would be independently adjustable, so you could have a fast and detailed attack and a slower decay etc.
The curve would be translated into a float array with maybe 2000 elements. This array would be read out by an array to poly prim, with linear interpolation. The important thing is that the readout rate of the array would be variable, on a per-phase basis. So the first (attack) phase would be read out fast, then the indexing oscillator could slow down for the decay phase and so on. The break points in this scheme would be fixed, so the first quarter of the graph would be for attack, the second for decay, the third for sustain and the final one for release.
You would have a graph and four time knobs to get pretty much any useful envelope shape and duration you wanted. The graph display would not reflect the time element for each phase.
The index counter rate would switch over based on the index value, so with a total of 2000 elements the index rate would switch over at 500, 1000, and 1500, assuming an equal proportion of the array was assigned to each envelope phase.
One big issue I can see is re-triggering. An envelope usually has “soft” retriggering, so if re-triggered it will carry on from the current value and restart the attack phase from that value, rather than from zero every time (to avoid sudden changes in level which cause horrible clicks).
I don’t know if that helps or not, but I like the idea for sure, and would be happy to contribute. It would be great to have a really cool graphical envelope generator…
Cheers
Spogg
There's a lot of info in there that helps me. I don't like the idea of sticking to ADSR stages, as I explicitly am looking into freeform envelopes. To my understanding, such envelopes used on amplitudes would just alter the the original static amplitude shape to follow a given curvature. ADSR is just one possible way. But imagine a sound that wiggles quickly 8 times, then abruptly stops. Do it with a noise oscillator and you're close to a clap sound (just to put the envelope in a musical context). You can't realize such free forms with the adsr corset.
But the technical information helps a lot. Not to a point, where I could program the DSP myself, but at least in understanding what the output array could look like.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Splines and DSP
I’m glad I helped a bit tulamide.
My idea was simplified to relate it to an ADSR in behaviour. You could just as easily refer to it as a four-stage envelope. With a suitable number of nodes available in each stage you could create what you describe. Stage 1 would be the “bouncy” envelope and the other 3 stages all set to zero. So you just got the machine gun or clap sound or whatever you wanted.
You could maybe nominate a stage for sustain. In that case any curves drawn would be played to the end and then held there until release of the note. In this way you could draw a declining sustain stage, or one with a wobble, or one that got louder during sustain, while the note was held. The constraint of this sustain stage would be that it would have to complete before the next stage happened. So it would in effect be like the Hold stage on an AHDSR env. Or you could make a 5 stage env with a conventional sustain level. You could even nominate any part of a curve as being the sustain point.
The biggest problem would be what happens if you have a slow attack set, and release the note before it reached the defined attack level. On a conventional env there is a single value that changes over time, and if release happens “too soon” the current momentary value is passed over to the release slope calculation. This avoids an abrupt change in level.
It might be better to use your system to make a one-shot “modulator” with an option to repeat, so it then becomes a sophisticated LFO. Once started, it would always complete its single cycle. That would be a better and more workable application I think. The env prim could be used to keep the channel open while the “LFO” is active. This would be a nice thing to have to create transients and weird modulation shapes, which could be great for percussive sounds etc.
In this case the float array could be read out at a defined and adjustable speed. Since the index counter would be poly, it could be modulated. This means, for example, you could key-scale the speed of readout so higher notes read out the “envelope” faster. I think that’s a good way forward, and gets over the stage/sustain/re-trigger problem in one go. Plus, it would be quite easy to implement (I think!).
If I were to do this I would just need a float array that described the shape of the curve in a linear temporal form (say 2048 elements intended to be read out by an index number ramp). The amount of float elements could be variable too (but a bit easier if fixed at the design stage).
Also, please keep in mind that the curve drawing system would have to work with presets, although for test purposes that could come later. But it might influence your development process.
Sorry if this comes over as the ramblings of an old man. It was a sort of (poly) stream of consciousness.
Cheers
Spogg
My idea was simplified to relate it to an ADSR in behaviour. You could just as easily refer to it as a four-stage envelope. With a suitable number of nodes available in each stage you could create what you describe. Stage 1 would be the “bouncy” envelope and the other 3 stages all set to zero. So you just got the machine gun or clap sound or whatever you wanted.
You could maybe nominate a stage for sustain. In that case any curves drawn would be played to the end and then held there until release of the note. In this way you could draw a declining sustain stage, or one with a wobble, or one that got louder during sustain, while the note was held. The constraint of this sustain stage would be that it would have to complete before the next stage happened. So it would in effect be like the Hold stage on an AHDSR env. Or you could make a 5 stage env with a conventional sustain level. You could even nominate any part of a curve as being the sustain point.
The biggest problem would be what happens if you have a slow attack set, and release the note before it reached the defined attack level. On a conventional env there is a single value that changes over time, and if release happens “too soon” the current momentary value is passed over to the release slope calculation. This avoids an abrupt change in level.
It might be better to use your system to make a one-shot “modulator” with an option to repeat, so it then becomes a sophisticated LFO. Once started, it would always complete its single cycle. That would be a better and more workable application I think. The env prim could be used to keep the channel open while the “LFO” is active. This would be a nice thing to have to create transients and weird modulation shapes, which could be great for percussive sounds etc.
In this case the float array could be read out at a defined and adjustable speed. Since the index counter would be poly, it could be modulated. This means, for example, you could key-scale the speed of readout so higher notes read out the “envelope” faster. I think that’s a good way forward, and gets over the stage/sustain/re-trigger problem in one go. Plus, it would be quite easy to implement (I think!).
If I were to do this I would just need a float array that described the shape of the curve in a linear temporal form (say 2048 elements intended to be read out by an index number ramp). The amount of float elements could be variable too (but a bit easier if fixed at the design stage).
Also, please keep in mind that the curve drawing system would have to work with presets, although for test purposes that could come later. But it might influence your development process.
Sorry if this comes over as the ramblings of an old man. It was a sort of (poly) stream of consciousness.
Cheers
Spogg
-
Spogg - Posts: 3358
- Joined: Thu Nov 20, 2014 4:24 pm
- Location: Birmingham, England
Re: Splines and DSP
Coincidentally, I'm working on a similar problem in one of my current projects - i.e. how to have envelope sections each of which can contain any number of 'segments' and where the 'segments' can have any arbitrary spacing in time and so have to be interpolated from one to the next, including the 'wrapping' of sustain/release loops.
Essentially, my solution is to send the ASM an Array (converted to mem) in a special format. At the start of this array, there's a little "header' chunk of values which contains 'global' parameters, such as the total number of segments and the indexes of loop start/end segments for the sustain phase. The rest of the array contains a series of 'segment' chunks, each containing the playback parameters for the segment and a value for the time when the segment should be hit. Between segments, the other parameters are linearly interpolated. Because only a single array is used, it's easy to store the whole sequence in a VST Preset Array, including all of the 'metadata' in the header chunk.
The times are measured relative to a one-time-unit clock ramp, so that any time unit can be used. This allows the time unit to be changed in real-time without having to edit the sequence data, by simply changing the clock speed, even while notes are playing (so times can be modulated as Spogg suggested above). I haven't implemented it yet, but the idea is that a one-beat ramp is easily derived from the VST PPQ position so that perfect tempo-sync is possible even for very long notes.
The application in this case is slightly different - wavetable sequencing - but the code could be adapted to work for any kind of data that has to hit discrete values at arbitrary times and with a sustain and/or release loop. There's no limit to the number of 'segments' other than having to fix a maximum size for VST Preset Arrays.
Here's what I've got so far...
The relevant DSP code is inside 'Wave Sequence Oscillator' -> 'Wave Sequence Player'. Note that this is only a prototype with randomly generated wave tables. If you see '- empty - ' in the wave selector at the top, click the 'Generate' button to recreate the wavetables. You'll probably also want to click 'Clear' before saving it, otherwise the schematic file will be swelled in size by all the wave-table data!
If I get a bit of free time in the next few days, I'll have a go at adapting the code for simple envelope data points rather than overlapping wave segments. That should simplify the code quite a bit, and make it easier to adapt to any kind of editor for the array of 'segment' points. In combination with the versatility and easy editing of the spline curves, this could maybe make the most powerful FS envelope generator yet!
Essentially, my solution is to send the ASM an Array (converted to mem) in a special format. At the start of this array, there's a little "header' chunk of values which contains 'global' parameters, such as the total number of segments and the indexes of loop start/end segments for the sustain phase. The rest of the array contains a series of 'segment' chunks, each containing the playback parameters for the segment and a value for the time when the segment should be hit. Between segments, the other parameters are linearly interpolated. Because only a single array is used, it's easy to store the whole sequence in a VST Preset Array, including all of the 'metadata' in the header chunk.
The times are measured relative to a one-time-unit clock ramp, so that any time unit can be used. This allows the time unit to be changed in real-time without having to edit the sequence data, by simply changing the clock speed, even while notes are playing (so times can be modulated as Spogg suggested above). I haven't implemented it yet, but the idea is that a one-beat ramp is easily derived from the VST PPQ position so that perfect tempo-sync is possible even for very long notes.
The application in this case is slightly different - wavetable sequencing - but the code could be adapted to work for any kind of data that has to hit discrete values at arbitrary times and with a sustain and/or release loop. There's no limit to the number of 'segments' other than having to fix a maximum size for VST Preset Arrays.
Here's what I've got so far...
The relevant DSP code is inside 'Wave Sequence Oscillator' -> 'Wave Sequence Player'. Note that this is only a prototype with randomly generated wave tables. If you see '- empty - ' in the wave selector at the top, click the 'Generate' button to recreate the wavetables. You'll probably also want to click 'Clear' before saving it, otherwise the schematic file will be swelled in size by all the wave-table data!
If I get a bit of free time in the next few days, I'll have a go at adapting the code for simple envelope data points rather than overlapping wave segments. That should simplify the code quite a bit, and make it easier to adapt to any kind of editor for the array of 'segment' points. In combination with the versatility and easy editing of the spline curves, this could maybe make the most powerful FS envelope generator yet!
All schematics/modules I post are free for all to use - but a credit is always polite!
Don't stagnate, mutate to create!
Don't stagnate, mutate to create!
-
trogluddite - Posts: 1730
- Joined: Fri Oct 22, 2010 12:46 am
- Location: Yorkshire, UK
Re: Splines and DSP
Fascinating trog!
I’ve given some thought to wavetable sequencing myself. It seems to be a popular technique these days, and understandably so.
But I couldn’t think of a way of doing it smoothly using the prims we have available, so I concluded it would have to be a custom DSP/ASM system, which is way beyond me.
So I wish you well with this.
Cheers
Spogg
Edit: I’ve now had a look and a play with this. What you’ve done there so far is simply astonishing to me. This is going to be great (already is actually) and I wouldn’t be surprised if Kevin’s keeping a close watch on this! Brilliant trog!
I’ve given some thought to wavetable sequencing myself. It seems to be a popular technique these days, and understandably so.
But I couldn’t think of a way of doing it smoothly using the prims we have available, so I concluded it would have to be a custom DSP/ASM system, which is way beyond me.
So I wish you well with this.
Cheers
Spogg
Edit: I’ve now had a look and a play with this. What you’ve done there so far is simply astonishing to me. This is going to be great (already is actually) and I wouldn’t be surprised if Kevin’s keeping a close watch on this! Brilliant trog!
-
Spogg - Posts: 3358
- Joined: Thu Nov 20, 2014 4:24 pm
- Location: Birmingham, England
Re: Splines and DSP
Spogg wrote:...it then becomes a sophisticated LFO. Once started, it would always complete its single cycle. That would be a better and more workable application I think. The env prim could be used to keep the channel open while the “LFO” is active. This would be a nice thing to have to create transients and weird modulation shapes, which could be great for percussive sounds etc.
In this case the float array could be read out at a defined and adjustable speed. Since the index counter would be poly, it could be modulated. This means, for example, you could key-scale the speed of readout so higher notes read out the “envelope” faster. I think that’s a good way forward, and gets over the stage/sustain/re-trigger problem in one go. Plus, it would be quite easy to implement (I think!).
If I were to do this I would just need a float array that described the shape of the curve in a linear temporal form (say 2048 elements intended to be read out by an index number ramp). The amount of float elements could be variable too (but a bit easier if fixed at the design stage).
A free shape lfo! Awesome idea! If I have it down to a meaningful array output, I will let you know, so you could play with it and see if it does indeed become a useful lfo!
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: Splines and DSP
trogluddite wrote:If I get a bit of free time in the next few days, I'll have a go at adapting the code for simple envelope data points rather than overlapping wave segments. That should simplify the code quite a bit, and make it easier to adapt to any kind of editor for the array of 'segment' points. In combination with the versatility and easy editing of the spline curves, this could maybe make the most powerful FS envelope generator yet!
That's what I was hoping for. Someone who understands the impact of it and is willing to take over the DSP coding! Thank you so much. That motivates me to actually start working on it already, instead of gathering as much info as possible, which I normally do.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
39 posts
• Page 1 of 4 • 1, 2, 3, 4
Who is online
Users browsing this forum: No registered users and 7 guests