"Graintable" synthesis

Though Vital does not present its ability to do this natively to the user I think it’s really interesting. As has been noted before in other places, the 2048 sample-length of default wavetable formats corresponds to “F-1, detuned -22 cents”. This can be thought of, in Vital, as “the F above middle C, in an oscillator with -48 semitone detune and -22 detune”

What this means is that, at this frequency (F -1 detuned 22 cents) the wavetable in Vital is playing back the “natural sampled frequency” of its wavetable, at 44100 samples/second.

Now, Vital (as is the case with most wavetable synths) defaults to this “fidelity” because a 20Hz wave (the lower limit of human hearing) sampled at this frequency will be able to encode information up to 20kHz (the upper limit of human hearing, and basically the Nyquist frequency of normal 44.1kHz audio). So it’s a nice, “safe” wave size. And indeed, if you use Vital’s resynthesize preset to wavetable, it generates a note at this pitch (well, with the synth’s master voice detuned so that it’s this pitch) for 4 seconds (the duration required to cover exactly 256 “frames” at this sample rate).

So far, this is all public information. However, things get interesting when you drag a sample ONTO Vital and attempt to use it a wavetable. Specifically, if you import it “as a Wavetable” (rather than using Pitch Splice or Vocode, which involve resizing the FFT bins for pitch detection algorithm purposes).

If you do this, and you have the oscillator set to -48 semitones -22 cents and you play F above middle C, and you set LFO 1 to control wavetable position with a linear ramp, and you set LFO 1 to have a duration that matches the sample’s initial duration, and you set the blend mode to “file” or “time”, you will have created, in essence, a sampler.

What you’ve done is you’ve treated all of the non-harmonic content of the sample as though it were part of the harmonic partials of some much lower-pitched waveform (this works thanks to the magic of the Nyquist theorem) and divided it into small “grains”. Those grains have a duration of about 46 milliseconds. As you drag the wavetable position, you “slide” those grains around with crossfading.

You can adjust the size of these “grains” too, though doing so will involve some math. If you edit your wavetable, you can change the FFT “Window Size” to control the duration of each grain. You have to recalculate the “root pitch” if you do this, but using octaves it isn’t so bad (using 4096 as a window size, drop an octave. Using 1024 as a sample size, go up an octave. These each double and halve the duration of the grain, respectively)

You can also set Vital to “Vocode” spectral mode… in this mode, reducing the pitch of the oscillator will reduce the window size dynamically, but keep the sample playback rate the same (effectively extending/reducing the size of each grain). You can then use the spectral shift knob to “tune” the grains (Formant shift mode works similar, except it also reduces oscillator pitch, so you have to spin the Formant shift knob opposite your pitch motion to extend the grains). You can set a Macro up that adjusts the Formant and Oscillator pitch knobs in opposite directions and that Macro can manipulate “grain size” (the Formant Shift knob covers 2 octaves in each direction so you need to set your bipolar macro to connect to oscillator semitones bipolar in a 48 range, and to Spectral Morph Amount in bipolar with a -1 range)

Now, all that’s left is to use Unison mapped to the Wavetable position to create a “grain cloud”.

Tong Cloud.vital (440.8 KB)

8 Likes

Beyond using this for granular, I’ve realized that you can actually use Vital as a resynthesis engine here, in the style of Image Line’s Harmor or Unfiltered Audio’s SpecOps. You don’t have quite the degree of control normally afforded by those (since Harmor allows you do do things like manipulate spectral information by curve and SpecOps allows you to postprocess spectral bands individually, whereas Vital only has its warp modes for real-time partial manipulation) but you also have more control over oscillator phase than Harmor gives, AND an arbitrary number of frequency bands (by default, Vital’s WT engine breaks the audio into 1024 partials instead of Harmor’s 512, but you can set that window size yourself)… and it all happens immediately, without latency (unlike in SpecOps) and can be automated easily via Vital’s internal parameters.

Resynthesizer.vital (587.6 KB)

The patch description includes the following instructions, so you can remember how it works:.

Drag a sample into Osc 1 as a Wavetable. Ensure the wavetable mode is set to File Blend, Window Size is set to 0, and all Normalize and Remove DCs are untoggled. C5 will play back the sample at its original pitch. Note that to approximate Harmor’s Resynthesis more accurately, the sample FFT size should be set to 1024 and the oscillator coarse pitch increased 1 octave. LFO 1 controls playback rate; by default this is keytracked (so the audio will resynthesize faster or slower at different pitches), and LFO 2’s phase slider adjusts the base duration by extreme detuning the LFO 1 coarse pitch. If LFO 1 is set to other modes, playback tempo/rate can be controlled independently of pitch

So to start, you have to use LFO 2’s phase to “tune” the sample length to be correct, and the keytracking LFO 1 will play the sample back like a real sampler. This isn’t really useful but it’s the default because I think it’s impressive that it actually works. But it’s more interesting once you take control over what LFO 1 does

For example if you set LFO 1 to be in seconds, you can specify the duration of the original wave file (NOTE: Due to the 256 frame limit, you are limited to 4 seconds of audio to resynthesize) and from there, your keyboard acts as a pitch shifter.

If you set LFO 1 to Sync mode, the sample will play back and you can repitch it in real-time.
If you set LFO 1 to Tempo mode, you can lock a loop to the tempo of your DAW and retime it as you please.
Freeze LFO 1 and you can drag the wavetable slider directly as a “spectral freeze” which is a great effect, though be aware pitch information is retained.
If you map anything to LFO1’s keytrack pitch and Oscillator 1’s coarse detune at the same depth (once you have LFO 2’s length set up) you can use that parameter as a sort of “tape stop” that slows down the audio. I haven’t figured out how to make a scratcher yet, I think it would require a second keytracked LFO with a reversed shape and some bipolar stuff.
Oh, speaking of, LFO 1’s shape controls playback speed, so if you invert the ramp, you get reversed audio. Sort of. Technically each grain is still played forward, rather than in reverse, but it works for most cases.

The spectral warp modes also do interesting things; Harmonic Stretch repitches the audio. Inharmonic stretch is a linear pitch shifter (additive, rather than multiplicative). Formant Scale does like a granulizer or ring mod sort of effect (as explained above). They all have interesting properties when applied to a “spectrum” that’s not periodic.

EDIT: Oh, and if you manipulate the LFO 1 trigger modes, you can use it to do things like set up loop points in a sample. Since, you know, you can’t do that in the noise sampler. They’re even automatable.

4 Likes

Your incredible :grinning:

I’ve been thinking a lot lately that it would be pretty cool for a synth to kind of bridge the gap between wavetable and sample playback/resynthesis. Harmor was the only thing that ever came close but it’s really a pain to use. Vital gets very close, I’m blown away by the quality I get back from it.

It’s the sort of thing that would be far more powerful if there was a native way of doing it, though. Like a way of dragging a sample to an oscillator and saying “import as spectral bins” and have Vital preconfigure the oscillator to be set up so that it was playing back at native sample rate, whatever that was (because this method only works with 44.1kHz wav files, I have some stuff at other sample rates and you have to do more adjustment. And you’re already down at the lower end of the native Oscillator detune range so then you have to use an LFO/Macro to force the knob below it’s min position and it’s just generally a mess)

I also wish there was a cleaner way of extracting the actual playback rate, though in order to do that with the keytracked oscillator one thing that would be necessary would be for a table to import ONLY at the wavetable size that it is initially at, rather than stretching itself to fill all 256 frames. At least that way, once you had the duration set correctly, it would STAY set correctly unless you changed it. Or maybe a way of taking the size/duration of the wavetable and using it as an LFO sync option. But I guess it’s what I get for pushing Vital well beyond the bounds that Matt intended it to be used for.

2 Likes

Oh wow! I need to digest this somehow, it looks very nice. I tried to use import-as-wavetable for something like this but lacked the knowledge and willingless to calculate. Now we’re going somewhere! :clap::sweat_smile:

1 Like

You da man , Think Matt could use your knowledge ! way ahead of me :grinning: