A simple monophonic patch demonstrating the Yofiel synthesizer core. The single gen~ object's CPU utilization is extremely low, even though no sacrifices were made for quality. It is typically 0.6% on a 4GHz Windows machine, and built-in dynamic CPU throttling drops usage to near zero when not outputting audio.

The following video demonstrates some of the synthcore sounds.

youtube

Features

SynthCore in Presentation Mode
SynthCore in Presentation Mode
  • Single gen~ object with codebox optimizations for best performance. This provides 64-bit floating-point accuracy and coded CPU throttling when parts are not in use, so the object can be used as is if only wanting to use one part.
  • Two complete waveset+anti-aliased oscillators. Both oscillators have sync, FM, FM feedback. There's 37 oscillator wavesets plus noise, anti-aliased PWM, saw. triangle waveforms. All have variable shape. The 3x oversampled anti-aliasing uses the EPTR and LTR algorithms. Variable mix and ring modulation.
  • 0/12/24-dB/octave 3x-oversampled LP+BP+HP+Comb filter with table-based gain compensation: Variable mixing mixing of freq, resonance, poles, saturation, and comb filter;. Unfiltered oscillator mix with optional oscillator saturation;
  • Two LFOs with sine/twosine, square/pulse, saw/triangle, and S&H waveforms; adjustable waveform shape, frequency, and optional gate sync.
  • Two ADSR envelopes.with interactive controls (changing ADSR values directly affects currently playing sound).
  • Modulation matrix with individual level control on six matrix crossbars for each of 21 sources, including envelopes, LFOs, gate levels, oscillator pitch, and other parameters, routed to any of 37 destinations.
  • MIDI I/O: Receives note on/off, volume, all notes off, program change, mod wheel, and pitch bend. Six other freely assignable controller sources are available in the modulation matrix, electable here. MIDI output is still preliminary.

Usage

it should be rather self explanatory. All the synth parameters are set with messages (there is no audio input). The panel itself shows the messages, and the panel control show the values and ranges.When you unlock it, you can see the messages are sent to the gen~ object by a SEND/RECEIVE pair (this does add one audio-frame latency, typically 64 samples).

Top Level Patch
Top Level Patch

There is one subpatch to set up the audio buffers. The buffers contain the oscillator wavesets, two very large files containing filter gain compensation data, and some ancillary data. The audio files yq2.wav, yq4.wav, wavgodel.wav, are included in the zipfile and must be in the same directory as the synth.maxpat file for it work as delivered.

Initialization Subpatch
Initialization Subpatch
The subpatch must have a loadbang passed into it from the top level so that it initializes in the correct order. If you want multiple synth objects in your design, include the initialization subpatch only once, The subpatch also can turn on the ~ezdac and reset the ~synth if you want.

There is a separate subpatch to format MIDI input for the gen~ object. It allows any MIDI CCs to be assigned to size controller inputs in the modulation matrix. It also supplies pitch bend and mod wheel values to the gen~ object.

MIDI input Subpatch Design
MIDI input Subpatch Design

There is one audio output. Please contact me if you have any questions.

Parameter Reference

In the below tables, the "name" column specifies the scripting name, and for audio parameters, the same name is used for the gen~ Parameter name.

Oscillators

The controls for the two oscillators are identical, except for mix and ring modulation.

o1trck, o2trck
Name Param Range Default Description
Wave Select
o1s, 02s 1~48 1

Selects between different waveform sets, each of which may continuously vary depending on the shape control.

Group Index and Description
Fundamental:
  1. Off: oscillator is disabled.
  2. Square/Pulse: 3x-oversampled, anti-aliased pulse with duty cycle of 2.5% to 97.5%.
  3. Saw/Triangle: 3x-oversampled, anti-aliased ramp, varying between downward-falling sawtooth, through triangle, to upward-rising sawtooth.
  4. Sine/tri: Sinewave with decreasing parabolic shape until it becomes a triangle wave.
Harmonic Sweeps:
  1. Sine/2sine: A sine fades from the base frequency, to an equal mix of the base frequency plus a sinewave one active higher.
  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.
  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.
Sync
o1snc, o2snc 0~1 0

When enabled (1), the oscillator phase resets to zero upon the other oscillator output making a rising crossing over zero.

Both oscillators may sync to each to each other, although generally sync would only be enabled for one. Both oscillators also reset to a phase of zero upon gate-on events.

Pitch
o1p, o2p -50 ~ 50 0 Sets an offset for the oscillator from the input pitch (after pitch mapping, keyboard pitch transposition). This pitch is also the offset for the pitch track control.
Detune
o1d, o2d -50 ~ 50 0.0

For oscillator 1, sets a detune for both oscillators, to play with other instruments. For oscillator 2, sets a detune for the oscillator, added after pitch tracking.

Pitch Track
0 ~ 2.0 1.0

(In version 1.3) Sets the amount of linear pitch tracking around middle C. At 0.0, there is no pitch tracking. Between 0.0 and 1.0, pitch increases slower than note pitch across rising notes. At 1.0, the oscillator tracks the pitch of the keyboard perfectly. Between 1.0 and 2.0, pitch increases faster than note pitch across rising notes.

Shape
o1w, o2w 0 ~ 100 50

Adjusts the waveform shape, depending on the selected waveform output.

This is an unusual feature, so the oscilloscope display assists with knowing the current output waveform after waveform selection and shape adjustment, before any modulation by the modulation matrix.

Mix
o2mix 0 ~ 100 50

The mix of the oscillators into the filter input. At 0, only oscillator 1 is output. At 100 only oscillator 2 is output.

Ring
o2am 0 ~ 100 0

Mixes ring modulation with the oscillators into the filter input. At 0 there is no ring modulation. At higher values the amount of ring modulation in the output signal rises linearly, until at 100 the output is ring modulation only.

Fb Lvl
o1ft1, o2ft1 0~ 100 0

Sets the amount that the oscillator modulates itself. At higher levels, the feedback creates white noise.

FM
o1f2, o2f1 0 ~ 100 0

Sets the base amount of FM modulation by the other oscillator. Both oscillators may modulate each other.

FM Track
o1ft2, o2ft1 0.0 ~ 2.0 0

The pitch from keyboard tracking is added to the base FM level. Between 0.0 and 1.0, the amount of FM increases slower than note pitch across rising notes. At 1.0, the oscillator FM tracks the eyboard perfectly. Between 1.0 and 2.0, FM increases faster than note pitch across rising notes.

Filter

The filter receives input from the oscillators and outputs to the effects. The panel shows an approximation of the current filter shape in a graphical display.

Name Param Range Default Description
Cutoff
fcut -63 ~ 63 0

Offset the cutoff pitch from the keyboard pitch, set in MIDI note values before modulation and tracking.

Filter Track
ftrck 0.0 ~ 2.0 1.0

Offset the cutoff pitch from the keyboard pitch, set in MIDI note values before modulation and tracking.

L/B/H
T 0 ~ 100 0

At 0, the output is low-pass filtered. At 50, it is band-pass filtered. At 100, it is high-pass filtered. Intermediate values linearly mix the filter types.

Q
q 0 ~ 100 0

At 0, there is no resonance. At 100 resonance is actually 1.1. This control is logarithmically adjusted to provide finer control at higher resonance settings.

Poles
u 0 ~ 100 0

At 0% the output is the oscillators without filtering (with oversaturation set by the SATcontrol). At 40%, it is a two-pole filter. At 100% the output is a four-pole filter. Intermediate values provide a mix of the oscillator and filter types.

Comb
fo -50 ~ 50 0

Adds a non-gain-compensated comb filter to the output. The filter delay is controlled by the filter cutoff. In later versions, the filter feedback is controlled by the filter resonance. At 0 there is no comb filter added. At positve values a feedforward filter is added. At negative values the comb is inverted.

Saturation
s 0 ~ 100 0

Linearly sets the amount of saturation for the filters and oscillators.

Env1, Env2
fe1, fe2 -50 ~ 50 0

Sets the envelope modulation level for the filter cutoff pitch, set in MIID note values. The envelope is applied after scaling by the envelope’s pitch and gate sensitivity controls. Higher positive modulation increases the filter cutoff point. Negative values invert the envelope modulation and decrease the cutoff point.

Lfo1, Lfo2
fl1, fl2 -50 ~ 50 0

Sets the LFO modulation level for the filter cutoff pitch, set in MIDI note values. The LFO inputs are bipolar, between -1. ~ +1, unless scaled by polyphonic spread in the LFO panel. Negative modulation levels invert the LFO modulation

LFOs

The two LFOs have identical controls.

Name Param Range Default Description
Wave Select
0 ~ 4 l1s, l2s 0

Selects between different waveform sets, each of which may continuously vary depending on the shape control. The available shapes are:

  1. Off: Disables the wave, reducing CPU usage.
  2. Sine/2sine: A sine fades from the base frequency, to an equal mix of the base frequency plus a sinewave one active higher.
  3. Ramp/Triangle: Varies between downward-falling sawtooth, through triangle, to upward-rising sawtooth.
  4. Pulse/Square: Varies between an up-rising pulse, through square, to a down-falling pulse.
  5. S&H: A random sample-and-hold signal, varying to noise.
Sync
l1t, l2t 0, 1 0

When enabled, this resets the LFO phase to zero when the voice receives a gate-on event. That is, this is a gate sync, not a oscillator sync as for the oscillators.

Shape
l1w, l2w 0 ~ 100 50

Adjusts the waveform shape, depending on the selected waveform output.

  • Sine - The output at 100% is a direct inversion of the sine wave at 0%. At intermediate values, a sine at double the frequency is mixed.\
  • Ramp – At 0 the output is a falling sawtooth. It slowly transforms to a triangle waveform at 50, then at values above that transforms to a rising sawtooth.
  • Pulse - At 0, the output is a pulse with a 5% duty cycle. At 50, the output is a square waved. At 100, the pulse is inverted. Intermediate values vary the duty cycle.
  • $&H - At 0, the output is a random step. At 100, the output is pure noise. At intermediate values, noise is injected between each random step.
Spread
l1sprd, l2sprd 0 ~ 100 0

(in version 1.3) Sets the amount of pitch spread added to the LFO. With frequency spread, the addition to the LFO frequency is 0 at the bottom of the keyboard range, and slowly increased jup the keyboard. At maximum setting, the frequency is doubled at the top of the pitch range. With amplitude spread, amplitude is slowly decreased up th ekeyboard. At maximum setting, the LFO ampluitude is halved.

Spread type
l1p, l2p 0, 1 0

(in version 1.3) Selects how spread affects the LFO. At 0, the spread is applied to amplitude. At 1, the spread is applied to frequency.

Freq
l1f, l2f 0.01 ~ 30Hz 5.0 Hz

Sets the base frequency before any frequency spread. This control provides higher resolution control at lower frequencies.

Envelopes

The first envelope sets the output amplitude and is available as a control source too. The second envelope is a control source only. The two envelopes have identical controls except for mode, which is only available for envelope 2.

Name Param Range Default Description
Attack
e1a, e2a 0 ~ 127 0

The attack phase, with logarithmic scaling of attack duration, as follows:

  • 0: 3 ms
  • 16: 3.162 ms
  • 32: 9.385 ms
  • 48: 27.863 ms
  • 64: 82.666 ms
  • 80: 245.337 ms
  • 96: 728.123 ms
  • 112: 2.160 seconds
  • 127: 296 minutes

The attack rises to the level set by the note velocity.

Decay
e1d, e2d 0 ~ 127 64

The decay phase, with timing as for attack. The decay level falls to the level set by the envelope sustain.

Sustain
e1s, e2s 0 ~ 127 64

The sustain level, which is multipled by the current note's velocity.

Release
e1r, e2r 0 ~ 127 64

The release phase, with timing as for attack. If there is another note still playing when a gate-on event occurs, the envelope ramps quickly (at 5ms) to 0 and then starts the attack phase, to preserve the entire attack cycle at all times.

Mode
e1m, e2m 0, 1, 2 0

Sets the envelope behavior.

  1. Multi - The envelope triggers on every gate-on event. When all notes are turned off, the release phase starts.
  2. Single - The envelope is only triggered when no other notes are playing. When all notes are turned off, the release phase starts.
  3. Loop – The envelope triggers and releases as for Single mode. While the envelope is running the attack and decay cyoles repeat. The attack rises to velocity level, then the decay falls to sustain level. When the sustain level is reached, the attack cycle restarts again. This continues until the note is turned off, at which time the release phase starts.

Modulation Matrix

When the modulation amount is zero, or either the source or destination is off, the CPu load is reduced.

Name Param Range Default Description

Amount
m1x, m2x, m3x, m4x, m5x, m6x 100 ~ -100 0

The amount of modulation. At -100, the modulation is fully inverted. When 0, the modulation is disabled. When 100, the modulation is fully applied. Intermediate values scale the modulation linearly. When the added result of the parameter and modulation exceeds the parameter range, the value is clipped to permissable values.

Source
m1s, m2s, m3s, m4s, m5s, m6s 100 ~ -100 0
  1. Off - Disables matrix node.
  2. Env1 - Envelope 1 prior to velocity scaling. This is different from the amp and filter envelopes, which are scaled by velocity. The current velocity can be controlled seprately in the modulation matrix from the vel1 and vel2 sources.
  3. Env2 - The source is envelope 2, otherwise same as env1.
  4. Vel1 - The velocity of envelope 1.
  5. Vel2 - Reserved for future use.
  6. Lfo1 - LFO 1 modulation
  7. Lfo2 - LFO2 modulation.
  8. Osc1 Pitch - Oscillator 1 pitch after semitone offset and pitch tracking, but prior to synth detuning.
  9. Osc2 Pitch - Oscillator 2 pitch after semitone offset and pitch tracking, and with detuning from oscillator 1 too.
  10. Mono Pitch - The instrument pitch prior to oscillator pitch shift.
  11. Mono Vel - The velocity in envelople single mode, available in multi mode.
  12. Voice # - Reserved for future use.
  13. Mod Wheel - From either panel or MIDI input.
  14. Lfo1 * Mod Wheel - The LFO1 is multiplied by mod wheel.
  15. Lfo2 * Mod Wheel - The LFO2 is multipleid by mod wheel. n
  16. Pitch Bend - From either panel or MIDI input.
  17. MIDI cc1 - Input from MIDI controlller in MIDI variable mode. The MIDI cc value is also transmitted from MIDI out on dedicated controller values, so it can be recorded and played back in fixed mode.
  18. MIDI cc2 - As for cc1.
  19. MIDI cc3 - As for cc1.
  20. MIDI cc4 - As for cc1.
  21. MIDI cc5 - As for cc1.
  22. MIDI cc6 - As for cc1.

Dest
m1d, m2d, m3d, m4d, m5d, m6d 100 ~ -100 0
  1. Off - Disables matrix node.
  2. vibrato - Modulates pitch, in semitones, of both oscillators.
  3. tremolo - Modulates output amplitude. At maximum value it doubles or silences the output gain.
  4. osc1 pitch - Modulates pitch of osc1, in semitones.
  5. detune - Modulates pitch of both oscillators, in cents.
  6. osc2 pitch - Modulates pitch of osc2, in semitones.
  7. osc2 detune - Modulates pitch of osc2, in cents.
  8. osc1 shape - Modulates osc1 duty cycle, shape, or waveset depending on oscillator waveform.
  9. osc2 shape - As for osc1.
  10. osc mix - Modulates mix of osc1 and osc2.
  11. ring mod - Modulates amount of ring modulation mixed with the oscillators.
  12. osc1 feedback - Modulates amount of osc1 feedback over feedback range.
  13. osc2 feedback - Modulates amount of osc2 feedback over feeack range.
  14. osc1 fm lvl - Modulates amount of osc1 FM, clipping to 8Hz-16KHz range.
  15. osc2 fm lvl - Modulates amount of osc2 FM, clipping to 8Hz-16KHz range.
  16. filter cutoff - Modulates filter cutoff in semitpones.
  17. filter Q - Modulates resonance between 0 and 1.1 logarithmically.
  18. filter type - At minimum value, the filter is Low pass. At center value, the filter mis band pass. At maximum value, the filter is high pass. Intermediate values mix the filter types.
  19. filter poles - When the modulation is at minumum value, the oscillators bypass the filter. At center values, the filter is two pole. At maximum value, the filter is 4 pole. Intermediate values mix the filter type.
  20. filter sat - Modulates the filter saturation logarithmically.
  21. filter comb - Modulates the amount of comb filter added to the SVF filter output.
  22. filter env1 mod - Modulates the amount of env1 filter modulation linearly.
  23. filter env2 mod - Modulates the amount of env2 filter modulation linearly.
  24. filter lfo1 mod - Modulates the amount of lfo1 filter modulation linearly.
  25. filter lfo2 mod - Modulates the amount of lfo2 filter modulation linearly.
  26. lfo1 freq - Modulates the LFO1 frequency linearly.
  27. lfo1 shape - Modulates the LFO1 shape linearly.
  28. lfo1 spread - Modulates the LFO1 spread linearly.
  29. lfo2 freq - Modulates the LFO2 frequency linearly.
  30. lfo2 shape - Modulates the LFO2 shape linearly.
  31. lfo2 spread - Modulates the LFO2 spread linearly.
  32. env1 attack - Modulates the env1 attack as a linear percentage of the phase duration.
  33. env2 attack - Modulates the env2 attack as a linear percentage of the phase duration.
  34. env1 decay - Modulates the env1 decay as a linear percentage of the phase duration.
  35. env2 decay - Modulates the env2 decay as a linear percentage of the phase duration.
  36. env1 sustain - Modulates the env1 sustain as a linear percentage of the level.
  37. env2 sustain - Modulates the env2 sustain as a linear percentage of the level.
  38. env1 release - Modulates the env1 release as a linear percentage of the phase duration.
  39. env2 release - Modulates the env2 release as a linear percentage of the phase duration.

Design Details

At the top level, all the parameters are passed into a gen~ subpatch, after any scaling which makes sense for better usability. This is so all the parameters can be passed into a codebox in the SYNTH subpatch. Because all the params must be linked at the top level, this design sheet is quite crowded. I hope to improve the layout

Top-Level gen~ Design
Top-Level gen~ Design

The parameter scaling is first performed outside the codebox so that the calculations are only performed when the params change. Then all the other audio processing is performed in a single codebox, with conditional tests to stop unnecessary processing when possible. The code follows.

Hide LIne Numbers
  1. /************************************************************
  2.  FUNCTIONS                                               
  3. /***********************************************************/
  4. smoother(val){
  5.     History h1;
  6.     val+= h1 *.99;
  7.     h1 = val;
  8.     return val;
  9. }
  10. smoother2(val){
  11.     History h1;
  12.     val= val *.01 + h1 *.99;
  13.     h1 = val;
  14.     return val;
  15. }
  16. eptr(ramp,inc,w1,d1){
  17.     Buffer buf("eptr"); w2 = 1-w1;    e0= 0; 
  18.     if (ramp <=  w1 -inc) return -1;                
  19.     else if (ramp < w1 +d1) {
  20.         e0 = peek(buf, d1*(ramp -w1 +inc), 0); return e0;
  21.     } else if (ramp <= w2 -d1) return 1; 
  22.     else if (ramp < w2+d1){    
  23.         e0 = peek(buf,d1*(ramp -w2 +inc), 0); return neg(e0);
  24.     } else return -1; 
  25. }
  26. sinewave(r1, w1){
  27.     wave1 = triangle(r1, w1); 
  28.     dx1 = delta(wave1);
  29.     wave1 = cycle(wrap(wave1 +.25, 0, 1), index="phase");
  30.     if (w1>0 && w1<1){
  31.         if (dx1>0 && w1<.5) wave1 *= (w1 *2);
  32.         else if (dx1<0 && w1>.5) wave1 *= (2 - w1 *2);
  33.     } return wave1;
  34. }
  35. triwave(tri, r1, zr1, w1){
  36.     dx1 = r1 - zr1;
  37.     if (dx1<0) return -1;
  38.     else if (r1>w1 && zr1<w1) return 1; 
  39.     else return tri;
  40. }
  41. oscillator(sel,w1,fc,snc,rsr,srx3,sr3d3){
  42.      Buffer wbuf("wavgodel"); 
  43.     History zr1(0); History zt(0); 
  44.     out_1, out_2, dx1, w2, d1, t0, t1, t2, D=0;
  45.     m13 = -1/3; p13 = 1/3; p23 = 2/3;
  46.     if (sel!=0){
  47.         inc = rsr * fc;
  48.         r1 = accum(inc,snc,max=1,resetmode="post"); 
  49.         if (sel==1) {  // PULSE 
  50.             w1 = scale(w1,0,1,.0025,.4975); 
  51.             w2 = scale(w1,0,1,.1,.9);
  52.             if (r1>w2) out_2 = 1; else out_2 = -1;
  53.             inc = (inc<0)? 1 - inc: inc;
  54.             if (inc<.125){    
  55.                 out_1 = eptr(r1, inc *4, w1);
  56.             } else { 
  57.                 t0 = delta(r1);
  58.                 if (t0>0){ t2 = r1 -t0 * p23;
  59.                               t1 = r1 -t0 * p13;
  60.                  } else {   t2 =wrap(zt * p13 +zr1, 0, 1);
  61.                            t1 =wrap(zt * p23 +zr1, 0, 1);
  62.                 }
  63.                 zt = t0;
  64.                 d1 = 8192  / inc;
  65.                 t2 =eptr(t2, inc, w1, d1); 
  66.                 t1 =eptr(t1, inc, w1, d1); 
  67.                 t0 =eptr(r1, inc, w1, d1);
  68.                 if      (t2==t1 && t1==t0)           out_1 = t0;
  69.                 else if (t2!=-1 && t1==-1 && t0!=-1) out_1 = -1;
  70.                 else if (t2!=1  && t1==1  && t0!=1)  out_1 =  1;
  71.                 else out_1 = (t2 + t1 + t0) * p13;
  72.                 out_2 = out_1;
  73.  
  74.             }
  75.         } else if (sel==2) { // SAW OR TRIANGLE 
  76.             dx1 = delta(r1);
  77.             out_2 = triangle(r1, w1) *2 -1;
  78.             if (w1 < .01) {  // falling saw
  79.                 if (r1<inc)out_1 = neg(pow(r1/fc,3) *sr3d3 +r1 *fc *rsr + 1);
  80.                 else if(r1 <inc *2){
  81.                     D = r1 * samplerate /fc;    
  82.                     out_1 = neg(D *D *D *p23 -D *D *3 +r1 *srx3/fc +r1 *2);        
  83.                 } else if(r1 <inc *3) {
  84.                     D = r1 *samplerate /fc;    
  85.                     out_1 = neg(D *D *D *m13 + D *D *3 + D * inc *2 - D *9 +8);    
  86.                 } else out_1 = out_2;
  87.                 //    if (dx1<0) out1 = 0; else out1 = out2;
  88.             } else if (w1>.99)  {  // rising saw
  89.                 //    if (dx1<0) out1 = 0; else out1 = out2;
  90.                 if (r1<inc)out_1 = pow(r1/fc,3) *sr3d3 +r1 *fc *rsr + 1;
  91.                 else if(r1 <inc *2){
  92.                     D = r1 *samplerate /fc;    
  93.                     out_1 = D *D *D *p23 -D *D *3 +r1 *srx3/fc +r1 *2;        
  94.                 } else if(r1 <inc *3) {
  95.                     D = r1 *samplerate /fc;    
  96.                     out_1 = D *D *D *m13 + D *D *3 + D *inc *2 - D *9 +8;    
  97.                 } else out_1 = out_2;
  98.             } else {  // variable slope
  99.                 //out_1 = triwave(out_2, r1, zr1, w1);
  100.                 out_1 = out_2;
  101.             }
  102.         }
  103.         else { //WAVESET
  104.             wsel = sel * 32768; // 256 * 128
  105.             wwav= w1 * 32512; // 256 * 127
  106.             idx1 =0; idx2 =0; idx3 =0; idx4 =0; s1 =0; s2 =0; s3 =0; s4 =0;
  107.             wav = r1 * 256;
  108.             trg = change(wav);
  109.             acc = fract(wav); 
  110.             wsel = sah(w1 *127, trg);
  111.             bas = floor(wsel) *256 +  sel *32768; 
  112.             bas2 = bas +256;
  113.             s1  = peek(wbuf, wrap(wav -1, 0, 256) + bas, 0);
  114.             s2  = peek(wbuf, wrap(wav   , 0, 256) + bas, 0);
  115.             s3  = peek(wbuf, wrap(wav +1, 0, 256) + bas, 0); 
  116.             s4  = peek(wbuf, wrap(wav +2, 0, 256) + bas, 0); 
  117.             s5  = peek(wbuf, wrap(wav -1, 0, 256) + bas2, 0);
  118.             s6  = peek(wbuf, wrap(wav   , 0, 256) + bas2, 0);
  119.             s7  = peek(wbuf, wrap(wav +1, 0, 256) + bas2, 0); 
  120.             s8  = peek(wbuf, wrap(wav +2, 0, 256) + bas2, 0); 
  121.             out_1 = mix(
  122.                 interp(acc, s1, s2, s3, s4, mode="spline"),
  123.                 interp(acc, s5, s6, s7, s8, mode="spline"),
  124.                 fract(wsel)
  125.             );
  126.             out_2 = out_1;
  127.         }
  128.         zr1 = r1; 
  129.     }
  130.     return out_1, out_2;
  131. }
  132. svf(val, wa, d1, ft1, ft1n, ft2, lpz, bpz){
  133.     hp = val - (lpz + d1 * bpz); val = bpz + hp * wa;
  134.      lp = lpz + wa * val; bp = clip(val, ft1n, ft1);
  135.     bp *= 1 - (abs(bp) * ft2); return lp, bp, hp; 
  136. }
  137. filt(OSCS,ft1,ft1n,ft2,wa,d1,d2,lx,bx,hx,f2x,l4x,b4x,h4x){
  138.     History ta1,ta2,ta3, 
  139.         lpz2,bpz2,lpz4,bpz4, tb1,tb21,tb22,tb23, tb31,tb32,tb33; 
  140.     t00 = (((1/3 * 1/3) - (.5 * 1/3 * 1/3 * 1/3)) - (.5 * 1/3));
  141.     t01 = (1 + (3/2 * 1/3 * 1/3 * 1/3 - 5/2 * 1/3 * 1/3));
  142.     t02 = (.5 * 1/3 + (2 * 1/3 * 1/3 - 3/2 * 1/3 * 1/3 * 1/3));
  143.     t03 = (.5 * 1/3 * 1/3 * 1/3  - .5 * 1/3 * 1/3);
  144.     t10 = (((2/3 * 2/3) - (.5 * 2/3 * 2/3 * 2/3)) - (.5 * 2/3));
  145.     t11 = (1 + (3/2 * 2/3 * 2/3 * 2/3 - 5/2 * 2/3 * 2/3));
  146.     t12 = (.5 * 2/3 + (2 * 2/3 * 2/3 - 3/2 * 2/3 * 2/3 * 2/3));
  147.     t13 = (.5 * 2/3 * 2/3 * 2/3  - .5 * 2/3 * 2/3);
  148.     val1 = ta1; 
  149.     val2 = OSCS * t00 + ta1 * t01 + ta2 * t02 + ta3 * t03;
  150.     val3 = OSCS * t10 + ta1 * t11 + ta2 * t12 + ta3 * t13;
  151.     ta3 = ta2; 
  152.     ta2 = ta1; 
  153.     ta1 = OSCS;
  154.     lp21, bp21, hp21 = svf(val1, wa, d1, ft1, ft1n, ft2, lpz2, bpz2);
  155.     lp22, bp22, hp22 = svf(val2, wa, d1, ft1, ft1n, ft2, lp21, bp21);
  156.     lp23, bp23, hp23 = svf(val3, wa, d1, ft1, ft1n, ft2, lp22, bp22);
  157.     lpz2 = lp23; bpz2 = bp23;
  158.     val1 = lx * lp21 + bx * bp21  + hx *  hp21;
  159.     val2 = lx * lp22 + bx * bp22  + hx *  hp22;
  160.     val3 = lx * lp23 + bx * bp23  + hx *  hp23;
  161.     lp41, bp41, hp41 = svf(val1, wa, d2, ft1, ft1n, ft2, lpz4, bpz4);
  162.     lp42, bp42, hp42 = svf(val2, wa, d2, ft1, ft1n, ft2, lp41, bp41);
  163.     lp43, bp43, hp43 = svf(val3, wa, d2, ft1, ft1n, ft2, lp42, bp42);
  164.     lpz4 = lp43; bpz4 = bp43;
  165.     val1 = val1 * f2x + l4x * lp41 + b4x * bp41  + h4x *  hp41;
  166.     val2 = val2 * f2x + l4x * lp42 + b4x * bp42  + h4x *  hp42;
  167.     val3 = val3 * f2x + l4x * lp43 + b4x * bp43  + h4x *  hp43;
  168.     FILT = tb1  + val2 * t00 + tb21 * t01 + tb22 * t02 + tb23 * t03
  169.                 + val3 * t10 + tb31 * t11 + tb32 * t12 + tb33 * t13; 
  170.     tb33=tb32; 
  171.     tb32=tb31; 
  172.     tb31=val3; 
  173.     tb23=tb22; 
  174.     tb22=tb21; 
  175.     tb21=val2; 
  176.     tb1 = val1;
  177.     return dcblock(FILT);
  178. }
  179. lfo(sel,frq,sprdAmount,wid,sprdType,snc_en,trg,sprd,noise1,rsr){
  180.     fourpi = twopi * 2;
  181.     sprd   = sprd * sprdAmount + 1;
  182.     frq    = frq * rsr;
  183.     amod   = 1;
  184.     if(sprdType==0){ frq = frq * sprd;
  185.     }else{ amod = sprd; }
  186.     x = accum(max (0, frq), (snc_en)? trg: 0, max=1);
  187.     x = selector(sel, 
  188.         mix(sin(x * twopi), sin(x * fourpi), wid) * amod, 
  189.         triangle(wrap(x +.25, 0, 1), wid) *amod *2 -amod, 
  190.         (wrap(x + wid, 0, 1) >(wid*.98 +.01))* amod * 2 -amod, 
  191.         sah(noise1, mix(x>wid,noise1,wid))*amod * 2 - amod);
  192.     return x;    
  193. }
  194. /************************************************************
  195.  PARAMS and VARIABLES                                               
  196. /***********************************************************/
  197. Delay fdelay(96000, 1, feedback=1); 
  198. Buffer pow25_buf("pow25_buf"), y2("y2"),y4("y4"),synthdata("synthdata"),wbuf("wavgodel"); 
  199.  
  200. Param pitch, gate, vel0, vel1, vel2, trk0, trk1, trk2,
  201.     mgate, monop, monov, wheel, bend, e2mode,
  202.     o1s, p01, fma, fba, ow1, o2s, p02, fmb, fbb, ow2, om2, or2, o1snc, o2snc, 
  203.     m1s, m2s, m3s, m4s, m5s, m6s, m1x, m2x, m3x, m4x, m5x, m6x,
  204.     m1d, m2d, m3d, m4d, m5d, m6d, cc1, cc2, cc3, cc4, cc5, cc6,
  205.     ea1, ed1, es1, esx1, er1, ea2, ed2, es2, esx2, er2,
  206.     lv1, lw1, l1f, l1t, l1p, l1sel, l1poke,
  207.     lv2, lw2, l2f, l2t, l2p, l2sel, l2poke,
  208.     fe1, fe2, fl1, fl2, fcut,fT,  q,   s,   fU,  fo0, ftrck, fbrk1, fcrv,
  209.     sprd, rsr, sr_25, sr_flt, srx3, sr3d3;
  210.  
  211. History hq0(-1), hs0(-1), s1, ft1, q1, q2, q3;
  212. History hinc1(6), hinc2(6), henv1(0), henv2(0); 
  213. History elvl(0), elvl2(0), hlfo1, hlfo2, hosc1(0), hosc2(0), hmgate; 
  214.  
  215. noise1    = in1;
  216. out1     = 0;
  217. wa, d1, d2,  ft1, ft1n,ft2, fout, ox, f2x,f4x, l4x, b4x, h4x, f1  =0;
  218. lx, bx, hx,  lvl, l2l, b2l, h2l, l4l, b4l, h4l, OUT, fdel =0;
  219. zerocross, lvl2, trem, x,  y, src, d, a, OSCS =0;
  220. p1, p2 = 60;
  221.  
  222. fm1        = fma;  fm2    = fmb;
  223. fb1        = fba;  fb2       = fbb;
  224. w1        = ow1;  w2     = ow2; 
  225. mix2    = om2;  ring   = or2;
  226. att1    = ea1;  dec1   = ed1; sus1 = es1; sus1n = esx1; rel1 = er1; 
  227. att2    = ea2;  dec2   = ed2; sus2 = es2; sus2n = esx2; rel2 = er2;
  228. lf1        = l1f;  lf2    = l2f; 
  229. l1wid    = lw1;  l2wid  = lw2; 
  230. l1sprd    = lv1;  l2sprd = lv2;
  231. f1e        = fe1;  f2e    = fe2; 
  232. f1l        = fl1;  f2l    = fl2;
  233. f0        = fcut; q0        = q;   s0 = s; t0 = fT; u0 = fU; fo1 = fo0; 
  234. trkb0    = pitch * .01 - .1;
  235. p1        = p01; p2    = p02;
  236. trg        = change(gate);
  237. lfo1    = lfo(l1sel,lf1,l1sprd,l1wid,l1p,l1t,trg,sprd,noise1,rsr);
  238. lfo2    = lfo(l2sel,lf2,l2sprd,l2wid,l2p,l2t,trg,sprd,noise1,rsr);
  239. hlfo1   = lfo1; hlfo2   = lfo2;
  240. src     = m1s; x       = m1x;  d       = m1d;
  241. //***********************************************************
  242. // MODULATION MATRIX                                               
  243. //***********************************************************
  244. for(z=1; z<7; z +=1){
  245.          if (z==2) { src = m2s; x = m2x; d = m2d; } 
  246.     else if (z==3) { src = m3s; x = m3x; d = m3d; } 
  247.     else if (z==4) { src = m4s; x = m4x; d = m4d; }
  248.     else if (z==5) { src = m5s; x = m5x; d = m5d; }
  249.     else if (z==6) { src = m6s; x = m6x; d = m6d; }
  250.     if (d!=0 && (d<27 || d>38) && x!=0 && s!=0 ) {
  251.         a = selector(src, henv1, henv2, vel1, vel2, hlfo1, hlfo2,//1-6
  252.             trk0, trk1, trk2, monop, monov, sprd, wheel * .01,    //8-13
  253.             wheel*hlfo1*.01, wheel*hlfo2*.01, bend * .01,        //14-16
  254.             cc1, cc2, cc3, cc4, cc5, cc6                        //17-22
  255.         );
  256.         if         (d==1)  { trem     += x*a;}
  257.         else if (d==2)  { p1    += x*a; p2 += x*a;}
  258.         else if (d==3)  { p1     += x*a;}
  259.         else if (d==4)  { p1    += x*a *.01;} 
  260.         else if (d==5)  { p2    += x*a;}
  261.         else if (d==6)  { p2    += x*a *.01;} 
  262.         else if (d==7)  { w1    =  clip(w1    + x*a *.01, 0,1);} 
  263.         else if (d==8)  { w2    =  clip(w1    + x*a *.01, 0,1);}
  264.         else if (d==9)  { mix2  =  clip(mix2  + x*a *.01, 0,1);}
  265.         else if (d==10) { ring  =  clip(ring  + x*a *.01, 0,1);}
  266.         else if (d==11) { o1f1d =  clip(o1f1d + x*a,      0,100);}   
  267.         else if (d==12) { o1f2d =  clip(o1f2d + x*a,      0,100);}
  268.         else if (d==13) { o2f2d =  clip(o2f2d + x*a,      0,100);}
  269.         else if (d==14) { o2f1d =  clip(o2f1d + x*a,      0,100);}
  270.          else if (d==15) { f0      += x * a;}
  271.         else if (d==16) { q0    = clip(q0  + x*a, 0,100);} 
  272.         else if (d==17) { t0    =  clip(t0 + (x*a * .02 -1),-1,1);}
  273.         else if (d==18) { u0    =  clip(u0 + (x*a * .02 -1),-1,1);}
  274.         else if (d==19) { s0    =  clip(s0 + x*a, 0,100);}
  275.         else if (d==20) { fo1    =  clip(f0 + x*a * .02, 0,2);}
  276.         else if (d==21) { f1e    =  clip(f1e + x*a, 0,100);}
  277.         else if (d==22) { f2e    =  clip(f2e + x*a, 0,100);}
  278.         else if (d==23) { f1l    =  clip(f1l + x*a, 0,100);}
  279.         else if (d==24) { f2l    =  clip(f2l + x*a, 0,100);}
  280.         else if (d==25) { lf1    =  abs(lf1 + lf1 * x*a);} 
  281.         else if (d==26) { l1wid    = clip(l2wid  + x*a * .01, 0,1);}
  282.         else if (d==27) { l1sprd= clip(l1sprd + x*a * .01, 0,1);}
  283.         else if (d==28) { lf1    =  abs(lf1 + lf1 * x*a);}
  284.         else if (d==29) { l1wid = clip(l2wid  + x*a * .01, 0,1);}
  285.         else if (d==30) { l2sprd= clip(l2sprd + x*a * .01, 0,1);}
  286.         else if (d==31) { att1    = max(.003, att1 + att1 * x*a);}
  287.         else if (d==32) { att2    = max(.003, att2 + att2 * x*a);}
  288.         else if (d==33) { dec1    = max(.003, dec1 + dec1 * x*a);}
  289.         else if (d==34) { dec2  = max(.003, dec2 + dec2 * x*a);}
  290.         else if (d==35) { sus1    = clip(es1 + x*a *.01, 0,1);sus1n=1-sus1;}
  291.         else if (d==36) { sus2  = clip(es2 + x*a *.01, 0,1);sus2n=1-sus2;}
  292.         else if (d==37) { rel1  = max(.003, rel1 + rel1 * x*a);}
  293.         else if (d==38) { rel2  = max(.003, rel2 + rel2 * x*a);}
  294.     }
  295. }
  296. //***********************************************************
  297. // ENVELOPES                                               
  298. //***********************************************************
  299. //triggers
  300. env1 = 0;
  301. env2 = 0;
  302. if (trg >0) {
  303.     if (henv1) {            //if trg and env already on, add 25ms decay
  304.         hinc1 = 1;
  305.         elvl = henv1;
  306.     } else { hinc1 = 2; }    //otherwise  skip it
  307.     if (henv2) {
  308.         hinc2 = 1;
  309.         elvl2 = henv2;
  310.     } else { hinc2 = 2; }
  311. } else if (trg < 0) {
  312.     hinc1 = 5;
  313.     hinc2 = 5;
  314.     elvl = henv1;
  315.     elvl2= henv2;
  316. } else {
  317.     //env1
  318.     hinc1 = hinc1 + selector(hinc1, sr_25, att1, dec1, 0, rel1, 0);
  319.     henv1 = selector(floor(hinc1),
  320.         sample (pow25_buf, 1 - wrap(hinc1, 0, 1)) * elvl, 
  321.         sample (pow25_buf, wrap(hinc1, 0, 1)), 
  322.         sample (pow25_buf, 1 - wrap(hinc1, 0, 1)) * sus1n + sus1, 
  323.         sus1, 
  324.         sample (pow25_buf, 1 - wrap(hinc1, 0,1)) * elvl, 
  325.         0);
  326.     env1 = henv1 * vel1;
  327.     //env2
  328.     hinc2 = hinc2 + selector(hinc2, sr_25, att2, dec2, 0, rel2, 0);
  329.     henv2 = selector(floor(hinc2),
  330.         sample (pow25_buf, 1 - wrap(hinc2, 0, 1)) * elvl2, 
  331.         sample (pow25_buf, wrap(hinc2, 0, 1)), 
  332.         sample (pow25_buf, 1 - wrap(hinc2, 0, 1)) * sus2n + sus2, 
  333.         sus2, 
  334.         sample (pow25_buf, 1 - wrap(hinc2, 0, 1)) * elvl2, 
  335.         0);
  336.     //velocity
  337.     env2 = henv2 * vel2;
  338. }
  339. if (henv1){
  340.     //***********************************************************
  341.     // OSCILLATORS                                              
  342.     //***********************************************************
  343.     snc1 = trg || (o1snc)? (change(hosc2) > 0) : 0;
  344.     snc2 = trg || (o2snc)? (change(hosc1) > 0) : 0;
  345.     fc1  = mtof(p1);
  346.     fc1  += hosc2 * fm1;
  347.     fc1  += hosc1 * fb1;
  348.     fc2     = mtof(p2);
  349.     fc2  += hosc1 * fm2;
  350.     fc2  += hosc2 * fb2;
  351.     osc1, hosc1 = oscillator(o1s,w1,fc1,snc1,rsr,srx3,sr3d3);
  352.     osc2, hosc2 = oscillator(o2s,w2,fc2,snc2,rsr,srx3,sr3d3);
  353.     OSCS = mix(osc1, osc2, mix2) + ring * osc1 * osc2;
  354.     //***********************************************************
  355.     // FILTER                                               
  356.     //***********************************************************
  357.     f0     = f0 + f1e * henv1 + f2e * henv2 + f1l * hlfo1 + f2l * hlfo2;
  358.     f0   =  clip(f0, 20, 132);
  359.     f1   = mtof(f0);
  360.     u0    = smoother(u0);
  361.     t0    = smoother(t0);
  362.     //type and pole mixers
  363.     lx   = max(neg(t0),0);
  364.     bx   = 1 - abs(t0);
  365.     hx   = max(t0,0);
  366.     ox   = max(neg(u0),0);
  367.     ox   *=ox;
  368.     f2x  = 1 - abs(u0);
  369.     f4x  = max(u0,0);
  370.     l4x  = f4x * lx;
  371.     b4x  = f4x * bx;
  372.     h4x  = f4x * hx;
  373.     //coefficients
  374.     if(q0!=hq0){
  375.         q1  = (q0 <50)?  q0 *0.018032 : pow(q0 *.01, .3) *1.11;
  376.         q2  = 1 - max(1, q1); 
  377.         q2 *= q2;
  378.         q2 *= -.0925;
  379.         q2  = 1 - q2;
  380.         q3  = 1 - q1;
  381.         q3 += q3;
  382.     }
  383.     hq0 = q0;
  384.     wa  = min(1, sr_flt * q2 * f1); 
  385.     //    wa     = smoother(wa * .01);
  386.     ft1 = 1 / wa;
  387.     d1  = 2 - wa;
  388.     d1 *= ft1;
  389.     d2  = f4x * q1;
  390.     d2  = 1 - d2;
  391.     d2  = min(d2,d1);
  392.     d1  = min(d1,q3); 
  393.     if(s0!=hs0){
  394.         s1 = dbtoa(s0 *.24 -.12);
  395.     }
  396.     hs0 = s0;
  397.     ft1 *= s1;
  398.     ft2  = .25 / ft1;
  399.     ft1 *= ft1; 
  400.     ft1n = neg(ft1);
  401.     //gain table lookup
  402.     lvl  = floor(s0 +.5)* 11312 +floor(f0-19.5)* 101 + q0;
  403.     l2l  = peek(y2,lvl,0,boundmode="clip");
  404.     b2l  = peek(y2,lvl,1,boundmode="clip");
  405.     h2l  = peek(y2,lvl,2,boundmode="clip");
  406.     l4l  = peek(y4,lvl,0,boundmode="clip");
  407.     b4l  = peek(y4,lvl,1,boundmode="clip");
  408.     h4l  = peek(y4,lvl,2,boundmode="clip");
  409.     // main filter
  410.     OUT = filt(OSCS,ft1,ft1n,ft2,wa,d1,d2,lx,bx,hx,f2x,l4x,b4x,h4x);
  411.     //***********************************************************
  412.     // OUTPUT MIXER                                               
  413.     //**********************************************************
  414.     lvl  = l2l * lx + b2l * bx + h2l * hx;
  415.     lvl *= f2x;
  416.     lvl += l4l * l4x + b4l * b4x + h4l * h4x;
  417.     zerocross = OUT==0 || change(OUT<0);
  418.     lvl2 = sah(lvl,zerocross);
  419.     OUT = dcblock(OUT);
  420.     OUT *= lvl2;
  421.     // comb filter
  422.     //OSCS *= 3;
  423.     fdelay.write(OSCS);
  424.     f1 = smoother2(f1);
  425.     fout = fdelay.read(f1, 0, interp="spline");
  426.     x  = 1 - abs(fo1);
  427.     OUT *= x;
  428.     OUT += fout * fo1;
  429.     if(ox >0){
  430.         OUT+= ox * pow(abs(OSCS),1- s0 *.01) * sign(OSCS) * .33333;
  431.     }
  432.     OUT *= env1;
  433.     OUT += trem;
  434.     //waveform pokes to display 
  435.     //synthdata.poke(henv2, voice);
  436.     //synthdata.poke(o1s *128 + floor(w1 *127), voice + 32);
  437.     //synthdata.poke(o2s *128 + floor(w2 *127), voice + 64);
  438.     //synthdata.poke(l1poke + floor(l1wid *127), voice + 96);
  439.     //synthdata.poke(l2poke + floor(l2wid *127), voice + 128);
  440.     out1 = OUT;
  441.     out2 = env1;
  442. } else { 
  443.     out1 = 0;
  444.     out2 = 0;
  445. }

Please check back for additional information.

Release Notes

Version changes will be reported here.

Download

Download: Yofiel SynthCore as Max Source
Title
Yofiel SynthCore as Max Source (Details)
File Type
zip
File Version
2
File Size
26,851.02 Kb
Brief Description:
A demo of sounds from the Yofiel synthcore patch, a complete monophonic synthesizer in Cycling74 gen~. The object's CPU utilization is 0.6% on a 4G...