This oscillator has 5,504 individual wave cycles, organized as 128 smoothly morphing waves, in 43 sets. The design is very simple, reading in a single audio file at initialization (included) that contains all the waves in continuous and contiguous segments. A gen~ object supports morphing between any wave in each set, and between any set, to eliminate clicks from wave discontinuities.

The 43 morphing sets include harmonic shapings, filter sweeps, vowel formants, and randomized loops (please note that the loops are for individual wave cycles, not for looper apps).

youtube

 

History

First it must be said, Palm Wolfgang is notorious for designing the first waveset oscillator, included in the PPG music synthesizer (1979). Since then his company Waldorf Music Gmbh has manufactured many hardware and software implementations, as well as licensing the Waldorf oscillator to third parties such as Creamware Scope. However Waldorf's high-end hardware is very expensive for modern musicians, and only a few (such as myself of course) have purchased more than one of them, so Waldorf has been in and out of business since then. Wolfgang currently sells his custom versions on his own website too, at http://wolfgangpalm.com.

That being said, the wavesets from the PPG and its successors are copyrighted, so the waveset collection provided in this download are instead a mix of individual public-domain waveset files (also available in Reaktor from Native Instruments), and some improved-quality versions which I made myself, catenated into a single file. This waveset collection was previously available, at lower quality, in some of my custom metamusic designs here, including Heidegger and Marx. About once a year someone writes asking for this, so now it is available in open source, and is becoming part of future metamusic instruments for native Macintosh and Windows operating systems, as well as Ableton Live!

Technology

Waveset oscillators are often confused with wavetable synthesis. Each soundfile in such wavetable sets contain a long sample stream covering many wavecycles. Properly the soundfile should contain an attack phase, loop phase (active during envelope sustain), and occasionally a release phase (although the looped segment is usually faded out during envelope release). Then the synthesizer plays a different wavetable file for each instrument. Better versions also layer overlapping files across the frequency range to provide more accurate emulation of a musical instrument's tonality at different frequencies, which in proprietary systems may be distributed as a compressed aggregate,such as a Soundfont file. Because of the layering, pitch shifting of an individual output note rarely obtains the desired accuracy of emulation, so it's not possible to change the pitch easily.

But pitch-shifting of sound files they has been very popular, perhaps because it is much simpler and cheaper than full analog emulation. For this reason a number of analog synthesizer features, such as glide and glissando, are not commonly available and have fallen out of style (which, on the other hand, also means they again sound very new).

Waveset oscillators may be confused with wavetable oscillators because they also loop a soundfile. However, in waveset oscillators, the loop covers exactly one wavecycle, which is then stretched (or shrunk) by interpolation to produce any desired output frequency.The waves are grouped into continuously varying tones across multiple sets.

For smoothly changing tonalities, the current wave is swapped for another predesigned wave in the waveset. Each waveset contains a serious of waves which differ very slightly from its neighbors, so smooth sweeps though each set is possible by stepping forwards or backwards though each wave in the set. Thus the instrument can select a different wave by a triangle LFO, or by any other modulation source; and as the waves can be pitch shifted across the entire frequency spectrum, the oscillators also support glide, glissando, any amount of tremolo, or even complete pitch movement across the entire audible spectrum, such as in Shepard tones.

The following diagram shows some samples for one waveset in the Waldorf PPG. Note, as this was designed in 1979, memory was at a premium. Hence, in the the Waldorf wavesets, identical cycles in multiple wavesets were shared, and a particular waveset jumps virtually, between non-consecutive waves in physical memory. For example, wavecycle 101 is a fundamential sinewave, and it occurs in many separate wavesets (sometimes more than once in a single waveset). Additionally, if a smooth sweep could be obtained by less cycles, the number of wavecycles in each set could change.

The Waldorlf Waveset 'Resonant 1'
The Waldorlf Waveset 'Resonant 1'

In modern implementations, memory is no longer a constraint. Instead, in fact, fast access to sequential data is preferred, to make optimal use of DRAM page caching. Thus in this waveset implementation, the wavecycles in each set are continuous and contiguous; there are exactly the same number of samples in each cycle, and exactly the same number of waves in each set. This makes lookup of a new wave in linear sequence into a direct equally-spaced step, rather than vectoring through indirect table lookup to shared data for memory optimization. The benefits of wavesets are therefore amenable to modern computer technology.

Thus, sudden different tones can easily be achieved by instant transitioning to a non-contiguous wave in the set. Also, this implementation preloads multiple wavesets, so the sound tonality can also shift dramatically by selecting another waveset, either by a sequencer, or velocity, or keyboard pitch, or pulse LFO, or other ways. This implementation additionally can support FM and sync for the additional thicker timbres currently returning into vogue.

After all these advantages, what disadvantages do wavesets have? Well, in the past, it is difficult to anti-alias them, because with traditional antialiasing techniques, the aliasing compensation added to the naive digitized forms of waves is frequency depemndent. For this reason, Yofiel has developed EPTR antialised oscillators which are not frequency dependent; thus, in the future, they may be combined in new ways to create waveform sweeps which may also work well across a complete audio spectrum. At this point however, there is still not a waveset oscillator available elsewhere with the spectral and frequency sweeps in this set, which includes 43 sine-derived waves, that do not have sudden transitions, and so only exhibit substantial aliasing as the fundamental approaches Nyquist.

For more information on why aliasing is not so much a concern with sine-based derivatives, please see the popular and comprehensive article Antialiased Oscillators on this site.

Waveset Sampling Resolution

The other limitation of a waveset oscillator is that the output can only be as good as the sampled waves. The included waveset only includes sine and filter derivatives, so aliasing is not a problem. However the wave cycles are only 256 cycles long, and the waveset sweeps contain 128 gradually changing wavecycles, which has been found empirically to be sufficient in virtually all cases.

This selection results, with 32-bit float samples, in a 4MB waveset collection (uncompressed). Ideally the iondividual waves should be 50msec long (20Hz) to capture all audible harmonics without any distortion. With 256 sammples, the waves are 5.8msec at 44.1kHz (sampled at ~172Hz), so notes below MIDI F2 necessarily contain interpolated values between the available samples, and harmonics below 172Hz cannot be represented when played at higger frequencies than unity sample rate (when played at lower frequencies, the harmonics are scaled down appropriately).

To extend the harmonic range to include harmonics down to 20Hz, and improve lower-frequency note accuracy, the waveset file would need to be 32MB. Hence this version restricts to 256 samples per wave, in order to reduce the free download size. Note that creating a full 32MB waveset would take 30 minutes on a standard cycle-based indexed capture, so it is not expedient to create higher resolution waves at initialization. On the other hand, the existing waveset still produces unique sounds anyway, expecially suitable for rapid creation of new presets with comparatively low CPU usage.

And now without further ado, here is the demo.

Using the Demo Patch

The patch is set to turn on automatically at load. Click to select the desired pitch with the onscreen keyboard. Click on the right-hand description list to select any of the 43 sets.

Waveset Oscillator
Waveset Oscillator

The demo patch also contains a metro counter, which acts as a simple ramp LFO, to sweep smoothly through the waves in each waveset. This LFO is turned on automatically at load. To audition an individual wave, turn off this LFO and select the wave base in its number box (between 0 and 127).

Parameters

The oscillator is built in gen~ and has three parameters:

Name Range Description
pitch 0.0~127.0 The MIDI pitch of the oscillator. Float values may be set for detuning.
wave 0~127

The specific wave cycle of the 128 in each wave set that currently plays. All wave cycles are stored in the waveset file as continuous and contiguous representations, with 256 samples for each wave cycle. The design time-stretches the wave for the set frequency, using 4-point cubic interpolation to determine intermediate point values between the 256 precalculated samples. Changes between the separate waves within each set occur on the next zero crossing of the wave cycle to prevent clicks, so there is a slight latency after changing a setting depending on the frequency and time at which the values changes.

The input parameter should be an integer. The integer is internally wrapped between 0 and 127, so out-of-range vales may be set for this parameter.

set 0 ~ 42 Selects the wave set. All wave sets are stored in the waveset file as continuous and contiguous representations, with 32K (256*128) audio samples for each wave set. Changes between sets occur on the next zero crossing of the wave cycle to prevent clicks from wave discontinuities. The input parameter should be an integer and should not exceed the available range.

Available Sets

Waveset Type Index and Description
Harmonic Sweeps:
  1. Octave doubler: A sine fades from the base frequency, to a mix of the base frequency plus a sine one active higher, to the higher octave sine alone
  2. Doubler + fifth thinner: LOctaves and fifths are added successively until the midpoint, then the lower harmonics are removed
  3. Doubler + Fifth thicker: Octaves are faded in the first half, then fifths are faded in to the end/li>
  4. High harmonics: Starts with higher harmonics, which are thinned out starting from the lower frequencies
  5. High cluster harmonics: Harmonics 8-12 are faded in successively, then 16-19
  6. Steps 4th harmonics: Different pairs of harmonics with a constant distance, new harmonics with increasing frequencies are added and lower harmonics are removed
  7. Steps 4th tripled: As the previous, but three simultaneous harmonics
  8. Harmonics 8-16: Harmonics 8, 16, and an increasing number of harmonics betweeen these frequencies
  9. High odd harmonics: High odd harmonics added successively
  10. Bells: Asine adds bell sounds with an increasing number of higher harmonics
Filter Sweeps:
  1. High resonant sweep: Two resonant filters with rising and falling frequencies
  2. Medium resonant sweep: As the previous, with a medium frequency range
  3. Low resonant sweep: As the previous, with a low frequency range
  4. Multiple high diverging filters Diverging filters with higher frequencies and resonance
  5. Multiple low soft filters: As the previous, with less resonance and lower frequencies
  6. Several converging + diverging filters
  7. Multiple parallel filter sweeps
  8. Four resonant peaks: Four independent resonance peaks moving in wave movements towards higher frequencies
  9. Two bundles of three sweeps: Two bundles of three sweeps each, each bundle going from broad to narrow frequency distribution
  10. Two bundles of two sweeps: As the previous, with two sweeps instead of three
  11. Two bundles of three sweeps + notch: As above, adding a notch filter
  12. Wood emulation: A sequence of slightly irregular sweeps from low to higher frequencies
  13. High tree morph: Morph from single frequencies to a broad distribution with higher frequencies, random components
  14. Low tree morph: As the previous, with a lower frequency range
  15. Rain filter sweep: Linear sweep with single filter and random variations
  16. Base and ascending filter ramp:
  17. Soft filter ramp: As the previous with ascending sweep of single filter with lower resonance and no base frequency
Vowel Formant Sweeps:
  1. Soft vowel formants: Sucession of vowels (heed, hid, head, had, hod, hawed, hood, and who'd), broad formant peaks
  2. Hard vowel formats: As the previous, with narrower formant peaks
  3. Synthetic vowel formants: As above,with more synthetic version
  4. Doubled vowel formants: As above, with doubled frequencies
  5. Noisy vowel formants
  6. Formants of 'how are you"
  7. Lower Formants of 'how are you'
Randomized Loops:
  1. 32 random harmonics
  2. 8 random harmonics
  3. 8 random harmonics + ascending notch
  4. Random Few but strong random harmonics
  5. Low random harmonics with ascending cutoff
  6. High random harmonics with ascending cutoff
  7. Random and sweep components
  8. Random waveforms with smooth transitions
  9. Sample Loop with bass, drum, snare, and synth

 

 

Modifying the Basic Design

Switch from presentation mode to patching mode.

Waveset Oscillator Demo Patch
Waveset Oscillator Demo Patch

The design is single-level and very straightforward. Please contact us if you need assistance on the Yofiel forums.

Waveset Oscillator gen~ Core
Waveset Oscillator gen~ Core

The waveform switching is performed in gen~ for cycle accuracy on zero crossings, to prevent clicks when sweeping between waves in the same set.

Adding FM and Sync

To reduce distortion when moving from one non-contiguous wave to another, the above implementation uses two-point cubic interpolation. Four-point spline interpolation noticeably improves SNR for the waves, but adds distortion when moving between two non-contiguous waves and can cause noticeable clicks if the waves are significantly different. Also, when modulating at FM rate, one or two of the interpolation samples cross the wave cycle boundary into the next wave at FM wavelength rate, significantly reducing quality.

The FM version therefore performs four non-interpolated peeks at sample points that wrap within each wave cycle, then performs spline interpolation across the wrapped values. For sync, the current sample point can simply be set to the first sample in the current wave, as splines always pass through all their interpolation points.

Waveset Oscillator with FM, Sync, and Spline Interpolation
Waveset Oscillator with FM, Sync, and Spline Interpolation

Additional CPU optimization could be attained by replacing the peek operations of neighboring samples with a series chain of z-1 history operators. However the output would then have to be delayed by up to three audio clock cycles, and this latency would not make cycle-accurate FM and sync possible. So instead of using an IIR-style delay chain, this implementation adds two forward lookups to support FM+sync inputs. In addition, when changing the waveset, the z-1 sample point for the spline interpolation is also looked up again with the current waveset, to improve the quality of these transitions also.

Because the codebox contains a counter that is evaluated for every sample, Param modifications inside the codebox would be evaluated at vector boundaries. Therefore, in case the Params are being modified low rates or not changing, the Param scaling values are outside the codebox. Please note that changes to samplerate do not take affect in gen~ until the patcher is reopened.

Binaries for this enhancement are planned for later download, together with a BEAP module.

Crossfading Waves

Peter McCullogh suggested this elaboration, as for low-frequency sweeps, discontinuities can otherwise be heard. Following is the complete gen~ code prototype for a MAx7 BEAP module, with switchable wrapping modes.
Hide LIne Numbers
  1. Buffer rep("rep"); 
  2. Param mute(1); Param wmod(0); Param fade(1); Param wave(0); 
  3. Param xp(0); Param wm(0); Param wset(0); Param sync;
  4. idx1 =0; idx2 =0; idx3 =0; idx4 =0; s1 =0; s2 =0; s3 =0; s4 =0;
  5. wav = 266; trg = 1; bas = 0; wsel=0; sr = 256 / samplerate; 
  6. if (mute){
  7.     out1 = 0;
  8.     out2 = 0;
  9.     out3 = -1;
  10. } else {
  11.    snc= (sync)? change(in4 >0) : 0;
  12.    mid = in1 + xp; 
  13.    fc = mtof(mid + mid * in2);
  14.    wav, trg = counter(fc * sr, snc, 256);
  15.    acc = fract(wav); 
  16.    if (wmod==0)    //fold
  17.        wsel = sah(fold(wave +wm *(in3 *.1 +.5), 0,128), trg);
  18.    else if (wmod==1) //clip
  19.        wsel = sah(clip(wave +wm *(in3 *.1 +.5), 0,127), trg);
  20.    else //wrap
  21.        wsel = sah(wrap(wave +wm *(in3 *.1 +.5), 0,128), trg);
  22.    bas = floor(wsel) *256 + sah(wset, trg); 
  23.    out3 = bas;
  24.    faded = sah(fade,trg);
  25.    if (faded==0){
  26.        s1  = peek(rep, wrap(wav -1, 0, 256) + bas, 0);
  27.        s2  = peek(rep, wrap(wav   , 0, 256) + bas, 0);
  28.        s3  = peek(rep, wrap(wav +1, 0, 256) + bas, 0); 
  29.        s4  = peek(rep, wrap(wav +2, 0, 256) + bas, 0); 
  30.    } else {
  31.        //by Peter Mccullogh
  32.        blend_b = fract(wsel); 
  33.        blend_a = 1 -blend_b;
  34.        base_next = bas +256;
  35.        idx1 = wrap( wav-1, 0, 256);
  36.        idx2 = (idx1 +1) -256 *(idx1 >=255);
  37.        idx3 = (idx2 +1) -256 *(idx2 >=255);
  38.        idx4 = (idx3 +1) -256 *(idx3 >=255);
  39.        s1 = peek(rep, idx1 +bas, 0) *blend_a + peek(rep, idx1 +base_next, 0) *blend_b;
  40.        s2 = peek(rep, idx2 +bas, 0) *blend_a + peek(rep, idx2 +base_next, 0) *blend_b;
  41.        s3 = peek(rep, idx3 +bas, 0) *blend_a + peek(rep, idx3 +base_next, 0) *blend_b;
  42.        s4 = peek(rep, idx4 +bas, 0) *blend_a + peek(rep, idx4 +base_next, 0) *blend_b;
  43.    }
  44.    out1 = interp(acc, s1, s2, s3, s4, mode="spline") * 5;
  45.    out2 = neg(out1);
  46. }

But Why does it Sound so Good?

Part of the reason that the BEAP oscillator sounds so good is that its code performs all Param changes on the output waveform's zero crossings, reducing clicks wherever feasible between any oscillator settings in any preset.

The other part of the reason this oscillator sounds so good is that the above code is all calculated in 64-bit maths internally, and moreover, the coefficients are hand-coded for sharp frequency bounds and fades, with 4-point Catmull-Rom spline interpolation for intermediate values.

Prior versions built in Reaktor, on this site, also provided custom click-free operation, but they used a less-precise wavetable with less exact coefficients. Reaktor also provides inferior interpolation methods, and without 64-bit accuracy, for its built-in waveset oscillator modules. This is the first open-source implementation of this superior quality.

Download

Waveset oscillator as BEAP Module

This is the oscillator inisde a BEAP module. For more information, see this link:

BEAP Waveset Oscillator Module

Demo

This is the first demo, as a Max 7 file, but does not use any features specific to Max 7, so it should open in Max 6 also. Please register to receive notification on download updates.

Download: 5.5K Waveset Oscillator
Title
5.5K Waveset Oscillator (Details)
File Type
zip
File Version
1.0
File Size
2,890.80 Kb
Brief Description:
An oscillator with 5,504 indivudual cycles, organized as 128 smoothly morphing waves in 43 sets.