User Tools

Site Tools


getting_started_vividshaper

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
getting_started_vividshaper [2024/06/08 21:12] larsgetting_started_vividshaper [2025/01/09 21:41] (current) – [Using more oscillators] lars
Line 140: Line 140:
  
 In this example, we continue to let the generator be active as long as the volume for the oscillator is above 0.000001. Once the volume goes below, then **active == false** and the generator will turn itself off (until you press a note again). In this example, we continue to let the generator be active as long as the volume for the oscillator is above 0.000001. Once the volume goes below, then **active == false** and the generator will turn itself off (until you press a note again).
 +
 +From version 1.3, you can instead call **VSDeactivate()**. It will run exactly the same code:
 +
 +<code Lua>
 +VSDeactivate()
 +-- This runs exactly the same thing as:
 +--   active = vol[1] > 0.000001
 +</code>
  
 When you play this simple patch, you will see the wave on the right side view: When you play this simple patch, you will see the wave on the right side view:
Line 165: Line 173:
  
 active = VSMax(vol) > 0.00001 active = VSMax(vol) > 0.00001
 +
 +pitchbend = pitchbend * 2
 </code> </code>
  
Line 171: Line 181:
 note[x] is an array corresponding to the notes being played for the eight oscillators (x is between 1-8). If we don't set note[x] explicitly, each oscillator will keep the default notein value. Hence, you don't have to set the note[] array if you don't want to change the note. note[x] is an array corresponding to the notes being played for the eight oscillators (x is between 1-8). If we don't set note[x] explicitly, each oscillator will keep the default notein value. Hence, you don't have to set the note[] array if you don't want to change the note.
  
-Given that notein=48, note[1] will be 47.99 and note[2] will be 48.01. Setting these two oscillators slightly detuned will create a beat effect, which you can read more about here:+The pitchbend variable is representing the current pitch bend data from your keyboard, and ranges by default between -2 to +2 (two semi-tones in each direction). This value is added to each note[x] value in the sound engine (after the Lua code has finished running). Say that note[1] == 48 and pitchbend == 0.3. The note that will be played by the oscillator will then be 48.3. In the code above, we manipulate the pitchbend variable so that it ranges from -4 to +4 instead. If you wish to turn it off (or use the pitchbend data to modulate something else), you can do so by setting pitchbend = 0 somewhere in the code. 
 + 
 +In the above code, we are adding and subtracting 0.01 for note[1] and note[2]. Given that notein == 48, note[1] will then be 47.99 and note[2] will be 48.01. Setting these two oscillators slightly detuned will create a beat effect, which you can read more about here:
  
 https://en.wikipedia.org/wiki/Beat_(acoustics) https://en.wikipedia.org/wiki/Beat_(acoustics)
Line 418: Line 430:
 However, setting it to 128 means the Lua code is called 48000/128=375 times per second. That will put some demands on your CPU so test this carefully.  However, setting it to 128 means the Lua code is called 48000/128=375 times per second. That will put some demands on your CPU so test this carefully. 
  
-===== MIDI CC, AUv3 parameters, and other messages =====+===== MIDI CC input, AUv3 input parameters, and other messages =====
  
 Sometimes, it is very useful to obtain CC-messages so that you can manipulate the sound in realtime using an external MIDI controller. The array cc[x] gives you at each update the current values of all CC messages except CC message 0 which is not used. Hence, **cc[1]** gives you the message for CC 1, **cc[20]** gives you the message for CC 20, etc. The values you get are between 0 and 127. If you prefer to get them normalised between 0 and 1, you can use the array **ncc[x]** instead. Sometimes, it is very useful to obtain CC-messages so that you can manipulate the sound in realtime using an external MIDI controller. The array cc[x] gives you at each update the current values of all CC messages except CC message 0 which is not used. Hence, **cc[1]** gives you the message for CC 1, **cc[20]** gives you the message for CC 20, etc. The values you get are between 0 and 127. If you prefer to get them normalised between 0 and 1, you can use the array **ncc[x]** instead.
Line 442: Line 454:
 </code> </code>
  
 +===== Delay effect =====
 +
 +Version 1.3 of VividShaper comes with a delay effect. There are two delays (delay1 and delay2), which can either be used separately or as a ping-pong delay. There are a number of ways to route the audio through these delays.
 +
 +There is not a separate delay for each generator. Instead, the generators share the same delays. This means the parameters for the actual delays (feedback, time, amplify) are set globally for all generators. However,
 +you can control how much audio from each oscillator in each generator that should be routed to each delay. For instance, it is possible to let only one oscillator be sent to the delay.
 +
 +{{ :delayeffect.png?800 |}}
 +
 +The above picture shows how the different parameters affect the delays. The arrays d1vol[x] and d2vol[x] tell for each oscillator how much of the output that should be sent to each delay. For instance, if you wish to send the output of oscillator 1 to delay1 and the output from oscillator 2 to delay 2, you would set it as:
 +
 +<code>
 +d1vol[1] = 1
 +d2vol[2] = 1
 +</code>
 +
 +The output to the delay lines are also affected by vol[x], so if you have set vol[1] = 0, then you won't send any sound to the delay lines. It is thus the output after applying any volume envelopes that are sent to the delays.
 +
 +Separately, you can now also turn off the main output of an oscillator and just let it go through the delays. This is done by setting ovol[x] = 0, for oscillator x.
 +
 +d1vol, d2vol, and ovol are local variables for each generator. You can for instance let oscillator 1 be routed through the delay lines in generator 1, but not generator 2, depending e.g. on the note value (allowing you to only let higher notes be sent to the delays).
 +
 +There is a new global variable called mvol, which default value is always 1. It tells how much of the main output that should be sent to the output lines (before being amplify modulated by gvol). This allows you to decrease or increase the main volume without changing the delay effect volume.
 +
 +Delay1 and delay2 are controlled using two global arrays delay1[x] and delay2[x], with the following parameters:
 +
 +<code>
 +delay1[1] -- Feedback from itself
 +delay1[2] -- Feedback from delay2
 +delay1[3] -- How much of the input that should be sent through the delay (0 = dry, 1 = wet)
 +delay1[4] -- How much the volume should be amplified (1 = normal)
 +delay1[5] -- Panning (0 = left, 1 = right)
 +delay1[6] -- Time in seconds, e.g. 0.5
 +
 +delay2[1] -- Feedback from itself
 +delay2[2] -- Feedback from delay1
 +delay2[3] -- How much of the input that should be sent through the delay (0 = dry, 1 = wet)
 +delay2[4] -- How much the volume should be amplified (1 = normal)
 +delay2[5] -- Panning (0 = left, 1 = right)
 +delay2[6] -- Time in seconds, e.g. 0.5
 +</code>
 +
 +There are three functions that you can use to set these parameters more easily:
 +
 +<code>
 +VSPingPong(feedback,time)    -- Gives you a ping pong delay
 +VSStereoDelay(feedback,time) -- Gives you a stereo delay, using panning[] info for each oscillator
 +VSMonoDelay(feedback,time)   -- Gives you a mono delay
 +</code>
 +
 +Simply adding VSPingPoing(0.9,0.2) as the last line in your code will give you a nice ping pong effect. You can then change parts of the delay parameters if you like after calling this function.
 +
 +===== MIDI output (experimental) =====
 +
 +MIDI output is a new experimental feature in v1.2. If you add an instance of VividShaper as MIDI effect plugin, only one generator will run (for now at least - this may change) and you will not be able to play any sound but you can instead send MIDI.
 +
 +<code Lua>
 +VSMIDI(command,data1,data2) -- Send MIDI data. (Next version)
 +VSMIDINote(channel,note,velocity,length) -- Play a given note on the given channel. length=1/4 means a quarter note, (Next version)
 +VSTick(prevbeatpos,beatpos,length) -- Returns true for every new time interval with the given length. (Next version)
 +</code>
 +
 +The first function **VSMIDI()** is allowing you to send any kind of MIDI data, notes or CC messages. If you use it to play notes, you need to take of also turning them off. How MIDI messages are constructed is not covered here, but there are plenty of MIDI documentation that describe this.
 +
 +If you prefer to let VividShaper handle this, you can use **VSMIDINote()** instead. Here, you will only need to tell that you want to play a certain note on a specific channel with a given velocity and length.
 +
 +For instance, **VSMIDINote(0,36,127,1/4)** will play C-3 (note=36 corresponds to C-3) at maximum velocity (127) as a quarter note. Note that 1/4 is the gate time. Sometimes, you may want the gate time to be somewhat shorter, in which case you could write: **VSMIDINote(0,36,127,1/4-1/4*0.1)**. This would give you 90% gate time of a quarter note (we subtracted 10%).
 +
 +The final function is a pretty useful function not only for MIDI but for other things as well. It will return a true/false value for every time interval. You can think of it as a metronome returning "ticks". For instance:
 +
 +<code Lua>
 +tick = VSTick(prevbeatpos,beatpos,1/4)
 +</code>
 +
 +would give **tick==true** four times per bar (one time per quarter note).
 +
 +These functions together makes it possible to make simple sequencers, where one VividShaper instance can control any AUv3 plugin or even real hardware.
 +
 +Here is a longer example that you can try in Logic. Load a drum kit as instrument and VividShaper as MIDI effect.
 +
 +<code Lua>
 +-- Patch: MIDItest #midi
 +tick = VSTick(prevbeatpos,beatpos,1/16)
 +step = math.floor(beatpos*4)
 +
 +bd = {1,0,0,0,0,0,1,0}
 +sn = {0,0,0,0,1,0,0,0}
 +hh = {1}
 +
 +bdindex = step % #bd
 +snindex = step % #sn
 +hhindex = step % #hh
 +
 +if tick == true then
 +  if bd[bdindex+1] == 1 then
 +    VSMIDINote(0,36,127,1/16)
 +  end
 +  if sn[bdindex+1] == 1 then
 +    VSMIDINote(0,36+4,127,1/16)
 +  end
 +  if hh[hhindex+1] == 1 then
 +    VSMIDINote(0,36+6,127,1/16)
 +  end
 +end
 +</code>
  
 +Here is a short explanation:
  
 +   * **tick** gives us a metronome with 1/16 notes
 +   * We have three arrays telling when different percussions should be played. These arrays are our step sequencer data:
 +     * **bd** is the bass drum.
 +     * **sn** is the snare drum.
 +     * **hh** is the hihat.
 +   * The index variables **bdindex**, ***snindex**, **hhindex**, each tell the position of each step sequencer. Yes, they are in fact independent, allowing for polymeter sequences if you decide to shorten one of them.
 +   * If **tick == true**, we have jumped to another step in the step sequencer and we need to check if we should play something.
  
  
getting_started_vividshaper.1717873943.txt.gz · Last modified: 2024/06/08 21:12 by lars