This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| vividshaper_reference_manual [2023/11/12 19:02] – [A simple example] lars | vividshaper_reference_manual [2026/09/09 17:11] (current) – lars | ||
|---|---|---|---|
| Line 2: | Line 2: | ||
| ====== VividShaper Reference Manual ====== | ====== VividShaper Reference Manual ====== | ||
| - | VividShaper is a wavetable AUv3 plugin synthesizer, | + | VividShaper is a wavetable AUv3 plugin synthesizer, |
| - | The Lua-code is called many times per second. Default is 93.75 times/ | + | The Lua-code is called many times per second. This allows the waves to be programmatically changed in realtime. Default is 93.75 times/ |
| There are up to eight generators for polyphony (the number of generators can be set from 1 to 8). Each generator has in turn up to eight oscillators. Each oscillator has the following states that can be manipulated in Lua-code: | There are up to eight generators for polyphony (the number of generators can be set from 1 to 8). Each generator has in turn up to eight oscillators. Each oscillator has the following states that can be manipulated in Lua-code: | ||
| Line 12: | Line 12: | ||
| * left-right panning | * left-right panning | ||
| * note (including cent note) | * note (including cent note) | ||
| + | * pitch bend information | ||
| * A wave table array containing 128 samples | * A wave table array containing 128 samples | ||
| Line 24: | Line 25: | ||
| <code Lua> | <code Lua> | ||
| - | -- Patch: A simple example | + | -- Patch: A simple example |
| wave[1] = VSTriangle(1, | wave[1] = VSTriangle(1, | ||
| vol[1] = VSADSRE(1, | vol[1] = VSADSRE(1, | ||
| + | active = vol[1] > 0.00001 | ||
| + | pitchbend = pitchbend*2 | ||
| </ | </ | ||
| - | This example | + | This example |
| This is not the playback frequency of the note (i.e. which note that is being played). The speed of the 128 samples is determined by note[1] for oscillator 1. We don't have to set note[1] explicitly, it is already set by the note you are playing on the keyboard. However, if we do wish to change it, for instance transposing one octave, we can do so by setting: **note[1] = notein+12**. Alternatively, | This is not the playback frequency of the note (i.e. which note that is being played). The speed of the 128 samples is determined by note[1] for oscillator 1. We don't have to set note[1] explicitly, it is already set by the note you are playing on the keyboard. However, if we do wish to change it, for instance transposing one octave, we can do so by setting: **note[1] = notein+12**. Alternatively, | ||
| + | |||
| + | The pitch bend value comes from your keyboard and will be added to the note value for each oscillator after the Lua code has finished. This value is stored in the variable pitchbend, which goes from -2 to +2 (i.e. 2 semi-notes). If note[1] == 40 for oscillator 1 and pitchbend == 0.53, the final note value used to play the note will be 43.53. If you want to turn off pitch bend, you can set pitchbend = 0 anywhere in your code. if you want to pitch bend from -4 to +4, you can just multiply it by 2 (pitchbend = pitchbend *2). This is done in the example above. You can also use the pitch bend value to modulate e.g. something else first, then set it to zero if you don't want it to also bend the notes. | ||
| The volume will then be set to an exponential volume ADSR envelope, with attack=1 sec, decay=1 sec, sustain=0.8, | The volume will then be set to an exponential volume ADSR envelope, with attack=1 sec, decay=1 sec, sustain=0.8, | ||
| + | |||
| + | The last row checks if the volume is above a certain threshold. If not, the boolean variable **active** will be false and the generator will turn off. It is not needed but you save some CPU power by turning off non-sounding generators. | ||
| + | |||
| + | The patch name **A simple example #simple** has a hashtag **# | ||
| This is all it takes to generate a simple wave. This will then be played back at different speeds, depending on the note being played. | This is all it takes to generate a simple wave. This will then be played back at different speeds, depending on the note being played. | ||
| Line 43: | Line 52: | ||
| -- Input information | -- Input information | ||
| notein | notein | ||
| + | pitchbend | ||
| tempo -- Current tempo (beats per second, e.g. 120). | tempo -- Current tempo (beats per second, e.g. 120). | ||
| timesignnum | timesignnum | ||
| Line 51: | Line 61: | ||
| gate -- Either 1 or 0 depending on if gate is on or off. | gate -- Either 1 or 0 depending on if gate is on or off. | ||
| gatetimeon | gatetimeon | ||
| + | gon -- Same as gatetimeon(short version name) | ||
| gatetimeoff | gatetimeoff | ||
| + | goff -- Same as gatetimeoff (short version name) | ||
| + | timeon | ||
| + | gtimeon | ||
| tick -- The number of times the Lua code has been called since initiation (when tick=0). | tick -- The number of times the Lua code has been called since initiation (when tick=0). | ||
| cc[x] -- Value of CC message x (between 0 to 127). | cc[x] -- Value of CC message x (between 0 to 127). | ||
| Line 61: | Line 75: | ||
| -- Output information | -- Output information | ||
| - | wave[x] | + | pitchbend |
| + | wave[x] | ||
| panning[x] | panning[x] | ||
| note[x] | note[x] | ||
| vol[x] | vol[x] | ||
| + | ring[x]=y | ||
| + | sync[x]=y | ||
| gvol -- Global volume, default = 1. Multiplied on the output to amplify or limit the audio. | gvol -- Global volume, default = 1. Multiplied on the output to amplify or limit the audio. | ||
| updatefreq | updatefreq | ||
| generators | generators | ||
| - | active | + | active |
| - | midigenerator | + | midigenerator |
| + | legato | ||
| + | portamento[x] | ||
| + | portamentotype -- 0 for linear, 1 for exponential | ||
| + | |||
| + | -- Coming soon in a future | ||
| + | sample[x] | ||
| + | loopstart[x] | ||
| + | loopend[x] | ||
| + | sxfade[x] | ||
| + | svol[x] | ||
| + | |||
| + | -- Delay output information | ||
| + | delay1[x] | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | delay2[x] | ||
| + | d1vol[x] | ||
| + | d2vol[x] | ||
| + | |||
| + | -- Reverb output information | ||
| + | reverb1[x] | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | reverb2[x] | ||
| + | rrvol -- Amplification of reberb2 output | ||
| + | |||
| + | -- Other routes of sound | ||
| + | mvol[x] | ||
| + | mrvol -- Amplification on main route | ||
| + | avol[x] | ||
| + | apanning[x] | ||
| + | arvol -- Amplification on alternative route | ||
| + | |||
| -- Views settings | -- Views settings | ||
| text -- A text string that is printed in the waves view. | text -- A text string that is printed in the waves view. | ||
| scaleview | scaleview | ||
| - | wavesview | + | wavesview |
| + | oscnote | ||
| </ | </ | ||
| Line 95: | Line 158: | ||
| wave[x] = VSWaveFold(wave[x], | wave[x] = VSWaveFold(wave[x], | ||
| wave[x] = VSNorm(wave[x], | wave[x] = VSNorm(wave[x], | ||
| + | wave[x] = VSAbs(wave[x]) | ||
| -- Wave math operators - arguments can be either arrays or scalar factors | -- Wave math operators - arguments can be either arrays or scalar factors | ||
| + | -- These are obsolete in v2.0, but will remain for compatibility reasons. | ||
| + | -- In v2.0, you can instead do: wave[x] = wave1*wave2 or wave[x]=1.5*wave1+wave2 | ||
| + | -- Version 2.0 supports: == <= >= < > + - * / % where comparators return 0 or 1 | ||
| wave[x] = VSMul(wave1, | wave[x] = VSMul(wave1, | ||
| wave[x] = VSMul(wave1, | wave[x] = VSMul(wave1, | ||
| Line 102: | Line 169: | ||
| wave[x] = VSAdd(wave1, | wave[x] = VSAdd(wave1, | ||
| wave[x] = VSSub(wave1, | wave[x] = VSSub(wave1, | ||
| + | |||
| + | -- LFOs (Low Frequency Operators): | ||
| + | -- These LFO functions take time as input. They are similar to the wave generators in how they | ||
| + | -- operate, but they only return a scalar value between [-1, 1]. (v1.2): | ||
| + | lfo = VSLFOSin(frequency, | ||
| + | lfo = VSLFOTriangle(frequency, | ||
| + | lfo = VSLFOSaw(frequency, | ||
| + | lfo = VSLFOSquare(frequency, | ||
| + | |||
| + | -- Helper functions to remove negative values (Rect = rectify) | ||
| + | output = VSRect(input) | ||
| + | wave[x] = VSRect(wave[x]) -- Input is a wave array | ||
| + | |||
| + | -- Helper functions for delays | ||
| + | VSPingPong(feedback, | ||
| + | VSStereoDelay(feedback, | ||
| + | VSMonoDelay(feedback, | ||
| + | |||
| -- Envelopes | -- Envelopes | ||
| + | -- ADSR: | ||
| -- The level is the initial volume. Normally, it would start at zero, but could also be initiated to | -- The level is the initial volume. Normally, it would start at zero, but could also be initiated to | ||
| - | -- start higher. | + | -- start higher. You can also call the function without level as argument (v1.4). It will then be zero. |
| - | vol[x] = VSADSR(attack, | + | vol[x] = VSADSR(attack, |
| - | vol[x] = VSADSRE(attack, | + | vol[x] = VSADSR(attack, |
| + | vol[x] = VSADSRE(attack, | ||
| + | vol[x] = VSADSR(attack, | ||
| + | |||
| + | -- Attack: | ||
| + | vol[x] = VSAttack(attack, | ||
| + | |||
| + | -- Release: | ||
| + | vol[x] = VSRelease(release, | ||
| -- Filters (x = oscillator) | -- Filters (x = oscillator) | ||
| + | -- There are two different filters in VividShaper. One that you apply on the actual waveform and | ||
| + | -- one that you apply as an insert after the output of the oscillator. Both are biquad filters. | ||
| + | -- Common for both filters is that you need to create a filter array containing the biquad values. | ||
| + | -- You don't need to set the values yourself. Instead, this array is created using three different | ||
| + | -- functions, depending on what kind of filter you want. The notein argument is optional from v2.0, | ||
| + | -- but can be used to let the cutoff frequency follow the note. | ||
| + | |||
| + | biquadcoeff = VSLowpass(cutoffFreq, | ||
| + | biquadcoeff = VSLowpass(cutoffFreq, | ||
| + | biquadcoeff = VSBandpass(cutoffFreq, | ||
| + | biquadcoeff = VSBandpass(cutoffFreq, | ||
| + | biquadcoeff = VSHighpass(cutoffFreq, | ||
| + | biquadcoeff = VSHighpass(cutoffFreq, | ||
| + | |||
| -- A quad filter consists of 5 coefficents: | -- A quad filter consists of 5 coefficents: | ||
| - | -- consisting of these 5 coefficients. The functions VSLowpass, VSBandpass, and VSHighpass will | + | -- consisting of these 5 coefficients |
| + | -- waveform filter. The next five coefficients are for the insert filter. The last value is | ||
| + | -- turning on or off the insert filter. You can manipulate these values, but it is complicated and | ||
| + | -- unnecessary since we have the helper functions above. | ||
| + | |||
| + | -- Waveform filtering (uses the first five biquad coefficents): | ||
| + | wave[x] = VSBiquad(wave[x], | ||
| + | |||
| + | -- Insert filter (uses the last five biquad coefficients: | ||
| + | afilter[x] = biquadcoeff | ||
| + | |||
| + | -- | ||
| + | -- Waveform filtering: | ||
| + | -- The functions | ||
| + | The functions VSLowpass, VSBandpass, and VSHighpass will | ||
| -- set the coefficients given the values. When setting these filter coefficients, | -- set the coefficients given the values. When setting these filter coefficients, | ||
| -- frequency and the note value are considered. This is because the cutoff frequency is typically | -- frequency and the note value are considered. This is because the cutoff frequency is typically | ||
| Line 119: | Line 241: | ||
| biquadcoeff = VSBandpass(cutoffFreq, | biquadcoeff = VSBandpass(cutoffFreq, | ||
| biquadcoeff = VSHighpass(cutoffFreq, | biquadcoeff = VSHighpass(cutoffFreq, | ||
| - | wave[x] = VSBiquad(wave[x], | + | wave[x] = VSBiquad(wave[x], |
| -- MIDI output | -- MIDI output | ||
| Line 127: | Line 249: | ||
| -- beatpos crosses over to a new bar. | -- beatpos crosses over to a new bar. | ||
| - | VSMIDI(command, | + | VSMIDI(command, |
| - | VSMIDIPlay(channel, | + | VSMIDINote(channel, |
| - | VSTick(prevbeatpos, | + | VSTick(prevbeatpos, |
| </ | </ | ||