Old 06-22-2017, 07:59 PM   #1
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default Twin Saw Oscillator

I've been working on a band limited oscillator for ReaRack. My reading on reducing aliasing seemed to suggest that they best way to reduce aliasing was to limit the frequencies in the original waveform, rather than trying to fix it later with oversampling and filtering. I looked at methods such as PolyBLEP and did a lot of experimenting with different types of smooth and/or slope limited waveforms, but in the end I decided that the best thing to do would be to try and create a true bandlimited waveform. I experimented with adding of sine waves, but of course this resulted in very high CPU load, particularly at low frequencies (which is why this method is not generally used). So I decided to attempt to approximate a bandlimited sawtooth waveform. After much trial and error I devised a method which involved transforming a sinc function. (the maths can be found here: https://www.desmos.com/calculator/wleksawmbq ). The resulting waveform is an approximation, so there are still residual frequencies above the cutoff frequency (or harmonic, to be more precise), but it does act as a steep filter with good attenuation. In the method, waveforms with less than five harmonics, the sum of sines method is used. For five or more harmonics the approximation algorithm takes over. The CPU load for the algorithm is about the same as for adding five sine waves, regardless of the number of harmonics.

Once I had succeeded in creating the sawtooth waveform, I could then subtract it from a phase shifted copy of itself to get a square or pulse wave. Furthermore, by varying the cutoff frequency and relative levels of each of the two saw waves, it is possible to create a range of more complex waveforms. Hence the 'Twin Saw' oscillator.

If anyone is interested in giving this oscillator a test run, I would be interested in feedback regarding it's useflness and performance before I add it to the ReaRack collection. See the JSFX code below.


Last edited by Time Waster; 06-25-2017 at 09:54 PM. Reason: Looks like there is too much code to do in one hit.
Time Waster is offline   Reply With Quote
Old 06-22-2017, 08:11 PM   #2
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Here's the first half of the code:

Code:
version: 1.0.1
desc:ReaRack - Twin-Saw Oscillator
noindex: true
author: Malcolm Smith
about: Audio oscillator module for the ReaRack modular JSFX synth system.
changelog: Fixed a bug which prevented note off messages being passed through.
/*Version 1.0.0 (14/6/2017) Initial release.
  Version 1.0.1 (3/07/2107) Fixed a bug which prevented note off messages being passed through.
*/
// Copyright(C) 2017 and later, Malcolm Smith (username 'Time Waster' on REAPER forums).
// License: LGPL - http://www.gnu.org/licenses/lgpl.html

slider1:smodcc=0<0,128,1{Off,0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input (Pitch Modulaton)
slider4:spwcc=0<0,128,1{Off,0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input (Phase Offset Modulaton)
slider2:sfilt1cc=0<0,128,1{Off,0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input (Saw 1 LPF Modulaton)
slider3:sfilt2cc=0<0,128,1{Off,0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input (Saw 2 LPF Modulaton)
slider5:sbalcc=0<0,128,1{Off,0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input (Saw 1/Saw 2 Mix Modulaton)
slider7:sf1type=0<0,2,1{Off,Fixed,Follow}>SAW 1 ------------- Saw 1 Lowpass Filter*
slider8:sn1=128<1,128,1>Saw 1 Filter Cutoff*
slider9:snr1=128<1,128,1>Saw 1 Filter Cutoff Modulation Range*
slider11:sf2type=3<0,3,1{Off,Fixed,Follow,= Saw 1 Lowpass Filter}>SAW 2 ------------- Saw 2 Lowpass Filter*
slider12:sn2=128<1,128,1>Saw 2 Filter Cutoff*
slider13:snr2=128<1,128,1>Saw 2 Filter Cutoff Modulation Range*
slider15:sbal=1.5<1,2,0.001>MIXING ------------------ Saw1/Saw2 Mix*
slider16:sbalr=1.5<1,2,0.001>Saw1/Saw2 Mix Modulation Range*
slider17:spw=0.5<0,1,0.001>Phase Offset*
slider18:spwr=0.5<0,1,0.01>Phase Offset Modulation Range*
// Choose your preferred note naming convention:
//slider6:0<0,128,1{MIDI note,C0,C#0,D0,D#0,E0,F0,F#0,G0,G#0,A0,A#0,B0,C1,C#1,D1,D#1,E1,F1,F#1,G1,G#1,A1,A#1,B1,C2,C#2,D2,D#2,E2,F2,F#2,G2,G#2,A2,A#2,B2,C3,C#3,D3,D#3,E3,F3,F#3,G3,G#3,A3,A#3,B3,C4,C#4,D4,D#4,E4,F4,F#4,G4,G#4,A4,A#4,B4,C5,C#5,D5,D#5,E5,F5,F#5,G5,G#5,A5,A#5,B5,C6,C#6,D6,D#6,E6,F6,F#6,G6,G#6,A6,A#6,B6,C7,C#7,D7,D#7,E7,F7,F#7,G7,G#7,A7,A#7,B7,C8,C#8,D8,D#8,E8,F8,F#8,G8,G#8,A8,A#8,B8,C9,C#9,D9,D#9,E9,F9,F#9,G9,G#9,A9,A#9,B9,C10,C#10,D10,D#10,E10,F10,F#10,G10}>Pitch Settings ----------------------------  Pitch
slider20:spitch=0<0,128,1{Any (MIDI note input),C-1,C#-1,D-1,D#-1,E-1,F-1,F#-1,G-1,G#-1,A-1,A#-1,B-1,C0,C#0,D0,D#0,E0,F0,F#0,G0,G#0,A0,A#0,B0,C1,C#1,D1,D#1,E1,F1,F#1,G1,G#1,A1,A#1,B1,C2,C#2,D2,D#2,E2,F2,F#2,G2,G#2,A2,A#2,B2,C3,C#3,D3,D#3,E3,F3,F#3,G3,G#3,A3,A#3,B3,C4,C#4,D4,D#4,E4,F4,F#4,G4,G#4,A4,A#4,B4,C5,C#5,D5,D#5,E5,F5,F#5,G5,G#5,A5,A#5,B5,C6,C#6,D6,D#6,E6,F6,F#6,G6,G#6,A6,A#6,B6,C7,C#7,D7,D#7,E7,F7,F#7,G7,G#7,A7,A#7,B7,C8,C#8,D8,D#8,E8,F8,F#8,G8,G#8,A8,A#8,B8,C9,C#9,D9,D#9,E9,F9,F#9,G9}>Pitch Settings ---------------------------- Pitch
//slider6:0<0,128,1{MIDI note,C-2,C#-2,D-2,D#-2,E-2,F-2,F#-2,G-2,G#-2,A-2,A#-2,B-2,C-1,C#-1,D-1,D#-1,E-1,F-1,F#-1,G-1,G#-1,A-1,A#-1,B-1,C0,C#0,D0,D#0,E0,F0,F#0,G0,G#0,A0,A#0,B0,C1,C#1,D1,D#1,E1,F1,F#1,G1,G#1,A1,A#1,B1,C2,C#2,D2,D#2,E2,F2,F#2,G2,G#2,A2,A#2,B2,C3,C#3,D3,D#3,E3,F3,F#3,G3,G#3,A3,A#3,B3,C4,C#4,D4,D#4,E4,F4,F#4,G4,G#4,A4,A#4,B4,C5,C#5,D5,D#5,E5,F5,F#5,G5,G#5,A5,A#5,B5,C6,C#6,D6,D#6,E6,F6,F#6,G6,G#6,A6,A#6,B6,C7,C#7,D7,D#7,E7,F7,F#7,G7,G#7,A7,A#7,B7,C8,C#8,D8,D#8,E8,F8,F#8,G8}>Pitch Settings ---------------------------- Pitch
slider21:sharm=0<1,16,1{1 (fundamental),2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Lowest Harmonic*
slider22:soct=0<-4,4,1>Tune (octave)*
slider23:ssemi=0<-12,12,1>Tune (semitone)*
slider24:scent=0<-100,100,1>Fine Tune (cents)*
slider25:sport=0<0,3>Portamento (sec)*
slider26:spitchc=0<-1,1,0.001>Pitch Modulation Centre*
slider27:spitchr=0<-1,1,0.001>Pitch Modulation Range*
slider29:smodaudio=0<0,3,1{Off,Frequency Modulation,Ring Modulation,Amplitude Modulation}>Audio Modulation*
slider30:satt=1.0<0,2,0.001>Output Level*
slider32:sclass=0<0,3,1{None,Master,Slave}>Class
slider33:sgroup=0<0,15,1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Class Group

options:gmem=ReRackTwinSaw

@init

function sawtooth(x p q g n)
(
n <= 0 ? y = 0:
n <= 4 ? (
  y = 0;
  wn = 1;
     while(wn <= n)(
     ny = sin(wn*x)/wn;
     y += ny;
     wn +=1;
     );
  y*=0.541;
  ):
  (
  m=(
    x >= 0 && x < p ? 1 + q*sin(($pi*x)/(2*p)):
    x >= p && x < $pi ? 1.41-((q+1)-1.41)*sin(($pi/(2*($pi-p)))*((x-p)-($pi-p))):
    x >= $pi && x <= tau-p ? 1.41-((q+1)-1.41)*sin(($pi/(2*($pi-p)))*(((tau-x)-p)-($pi-p))):
    x >= tau-p && x <= tau ? 1 + q*sin(($pi*(tau-x))/(2*p));
    );
  
  h = 1-(($pi/2)-(atan(n+1)))*g;
  k1 = (n+1)*(h*(x-$pi)+$pi);
  k2 = (n+1)*(h*($pi-x)+$pi);
  k3 = 0.541*(($pi-x)/2);
  
  x <= $pi ? (
    y = (-1.15*sin(k1)/(k1*m))+ k3;
    ):(
    y = (1.15*sin(k2)/(k2*m))+ k3;
    );
  );
);
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth

Last edited by Time Waster; 07-03-2017 at 07:30 PM. Reason: Bug fix
Time Waster is offline   Reply With Quote
Old 06-22-2017, 08:12 PM   #3
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Here's the second half of the code:

Code:
tau = $pi*2;
freq = 440;
inc = tau*freq/srate;
blkadj = tau*freq/srate;
volcount = ceil(srate/100);
sliderbits = 2^7+2^8+2^9+2^11+2^12+2^13+2^15+2^16+2^17+2^18+9+2^20+2^21+2^22+2^23+2^24+2^25+2^26+2^27+2^28+2^29+2^30;
cutoff = 1;
@slider
////////////////////////////Store slider values/////////////////
group = sgroup*35;

sclass == 1 ? (
  gmem[group+7] = slider7;
  gmem[group+8] = slider8;
  gmem[group+9] = slider9;
  gmem[group+10] = slider10;
  gmem[group+11] = slider11;
  gmem[group+12] = slider12;
  gmem[group+13] = slider13;
  gmem[group+14] = slider14;
  gmem[group+15] = slider15;
  gmem[group+16] = slider16;
  gmem[group+17] = slider17;
  gmem[group+18] = slider18;
  gmem[group+19] = slider19;
  gmem[group+20] = slider20;
  gmem[group+21] = slider21;
  gmem[group+22] = slider22;
  gmem[group+23] = slider23;
  gmem[group+24] = slider24;
  gmem[group+25] = slider25;
  );
  
@block
///////////////////////set slider values (slave mode)/////////////////////
sclass == 2 ? ( 
  slider7 = gmem[group+7];
  slider8 = gmem[group+8];
  slider9 = gmem[group+9];
  slider10 = gmem[group+10];
  slider11 = gmem[group+11];
  slider12 = gmem[group+12];
  slider13 = gmem[group+13];
  slider14 = gmem[group+14];
  slider15 = gmem[group+15];
  slider16 = gmem[group+16];
  slider17 = gmem[group+17];
  slider18 = gmem[group+18];
  slider19 = gmem[group+19];
  slider20 = gmem[group+20];
  slider21 = gmem[group+21];
  slider22 = gmem[group+22];
  slider23 = gmem[group+23];
  slider24 = gmem[group+24];
  slider25 = gmem[group+25];
  
  sliderchange(sliderbits);
);  

/////////////////////////Get slider values//////////////////////////
modcc = smodcc-1;
pwcc = spwcc-1;
filt1cc = sfilt1cc-1;
filt2cc = sfilt2cc-1;
pitch = spitch-1;
pwmodlev = spwr*$pi;
balcc = sbalcc-1;
ln1 = sn1;
ln2 = sn2;
f1type = sf1type;
f2type = sf2type;
tbal = (sbal-1.5)*2;
balr = (sbalr-1.5)*2;
pulsew = spw*$pi;
harm = sharm+1;
detune = 2^(soct + ssemi/12 + scent/1200);
portaval = sport;
modcentre = spitchc;
modlev = spitchr;
modaudio = smodaudio;
voltarget = satt;
volstep = (voltarget-prevol)/volcount;
volstepcount = volcount;

/////////////////////////portamento/////////////////////////
portastep = floor(max(1,((srate/samplesblock)*portaval)));

/////////////////////////Get MIDI inputs/////////////////
// MIDI keyboard pitch control
while (midirecv(offset, msg1, msg2, msg3))
  (  
  // Extract message type and channel
  status = msg1 & $xF0;
  // Is it a note on event?
     status == $x90 ?
      (
       // Get note value
       note = msg2 & $x7F;
       // Calculate frequency and phase position increment
       freq = 2^((note-69)/12)*440*harm*detune;
       blkadjtarget = tau*freq/srate;
       // Adjust for portamento if required
       adjstep = (blkadjtarget - blkadj)/portastep;
       blkadj != blkadjtarget ? ( blkadj += adjstep);
      );
////////////////////////Get modulation CC messages//////// 
  // Extract message type and channel
     status == $xB0 ?
      (
          // Pitch Modulation
          msg2 == modcc ?
         (
          modval = (msg3/63.5) - (1+modcentre);
          modlevel = modval * modlev;
          modadj = tau*freq*modlevel/srate;
          );
          // Pulse Width Modulation
          msg2 == pwcc ?
          (
          pwval = (msg3/127);
          pw = pulsew+pwval*(pwmodlev-pulsew);
          );
          // Filter 1 Modulation
          msg2 == filt1cc ?
          (
          f1val = msg3;
          ln1 = floor(sn1+(f1val*((snr1-sn1)/128)));
          );
          // Filter 2 Modulation
          msg2 == filt2cc ?
          (
          f2val = msg3;
          ln2 = floor(sn2+(f2val*((snr2-sn2)/128)));
          );
          // Mix Modulation
          msg2 == balcc ?
          (
          balval = (msg3/127);
          bal = tbal+balval*(balr-tbal);
          );                 
      );
  //Pass through all
   midisend(offset, msg1, msg2, msg3); 
);

/////////////////////////Slider pitch control//////////////
pitch > -1 ? (
  freq = 2^((pitch-69)/12)*440*harm*detune;
  blkadj = tau*freq/srate;
);

//Set variables to slider values if no modulatuion is required//
modcc == -1 ? (
  modadj = 0;
  modlevel = 0;
  );
pwcc == -1 ? pw = pulsew;
f1type == -1 ? ln1 = sn1;
f2type == -1 ? ln2 = sn2;
balcc == -1 ? bal = tbal;

//@block outputs for modulation smoothing @sample///////////////
modstep = (modadj-premod)/samplesblock;
outmod = premod;
premod = modadj;

pwstep = ((pw-prepw)/samplesblock);
outpw = prepw;
prepw = pw;
modadjspl = modadj;

///////////////////////Cutoff Frequencies///////////////////
cutoff1 = 2^(sqrt(ln1)*1.26287);
cutoff2 = 2^(sqrt(ln2)*1.26287);
// n1 = the number of harmonics for saw 1.
f1type == 0 ? n1 = floor(20000/(freq+(freq*modlevel))); 
f1type == 1 ? n1 = floor(cutoff1/(freq+(freq*modlevel)));
f1type == 2 ? n1 = min(ln1,floor(20000/(freq+(freq*modlevel))));
// n2 = the number of harmonics for saw 2.
f2type == 0 ? n2 = floor(20000/(freq+(freq*modlevel))); 
f2type == 1 ? n2 = floor(cutoff2/(freq+(freq*modlevel)));
f2type == 2 ? n2 = min(ln2,floor(20000/(freq+(freq*modlevel))));
f2type == 3 ? n2 = n1;

g = 0.42;
p1 = tau/n1;
q1 = 1-2/n1;
p2 = tau/n2;
q2 = 1-2/n2;

/////////////////Set Counter/////////////////////////////////
count = 0;

@sample
/////////////////////////Modulation Smoothing////////////////
count > 0 ? (
  modadjspl += modstep;
  pws += pwstep;
  ):(
  modadjspl = outmod;
  pws = outpw;
  );
poffset = (pws/$pi)-0.5;
count += 1;

/////////////////////////Volume Change Smoothing//////////////
vol != voltarget ?
(
  volstepcount >=0 ?
   (
    vol += volstep;
    volstepcount -= 1;
    );
);

//////////////////Set Phase Increment/////////////////////////
modaudio != 1 ? inc = blkadj:( // if FM is selected:
                             inc = blkadj*(1+((spl0+spl1)/2))*10;
                             );

////////////////////////////Define waveform////////////////////
bal < 1 ? y1 = sawtooth(x1,p1,q1,g,n1);
bal > -1 ? y2 = sawtooth(x2,p2,q2,g,n2);
bal1 = bal < 0 ? 1 : 1-bal;
bal2 = bal > 0 ? 1 : 1+bal;
yy=((y1*bal1)-(y2*bal2)-poffset*1.697*min(bal1,bal2))*vol;

cutcount += 1;
cutcount > countlimit? cutcount = countlimit + 1;

//////////////////////Audio output/////////////////////////////
  modaudio == 0 ? (          //Unmodulated waveform
     spl0 = yy+spl0;
     spl1 = yy+spl1;
     )
     :
     (
    modaudio == 2 ? (        //Ring Modulation   
     spl0 = (yy*spl0);
     spl1 = (yy*spl1);
        )
        :
        (
         modaudio == 3 ? (   //Amplitude Modulation
         spl0 = ((0.5+(yy/2))*spl0);
         spl1 = ((0.5+(yy/2))*spl1);           
          )
          :
          (                  //Frequency Modulation
          spl0 = yy;
          spl1 = yy;
         );
      );
   );      

//////////Buffer results for graphics////////
looplen = srate/8;
bufflen = floor(looplen);
  bpos<=bufflen ? (
    bpos[0] = x;
    modaudio == 0 ? (bpos+bufflen)[0] = yy:(bpos+bufflen)[0] = (spl0+spl1)/2;
    );
  
buffcount+=1;
buffcount > looplen ? (
  buffcount-=looplen;
  );
bpos=floor(buffcount);

////////Increment phase position///////////
x += inc+modadjspl;
x >= tau ? x-= tau;
x1 = x - pws;
x1 < 0 ? x1+= tau;
x2 = x + pws;
x2 > tau ? x2-= tau;

prevol = vol;

/////////////////////////////////graphics//////////////////////////////////////
@gfx 500 200

xscl = 38;
yscl = 60;
ox = 25;
oy = 60;

gfx_r = 0;
gfx_g = 1;
gfx_b = 0;
gfx_a = 1; 

//Draw waveform
gx = 1;
while (gx <= bufflen)(
  gfx_x = ox+xscl*gx[0];
  gfx_y = oy+yscl-yscl*(gx+bufflen)[0];
  gfx_setpixel(0,1,0);
  gx+=1;
);

//Draw linework and text
gfx_x=gfx_y=5;
gfx_lineto(gfx_x, gfx_y,0);
gfx_r=gfx_b=0;
gfx_g=gfx_a=1;
gfx_drawstr("Base Frequency = ");
gfx_drawnumber(freq,0);
gfx_drawstr(" Hz");
gfx_x=5;
gfx_y=20;
gfx_drawstr("Saw 1 - No. of Harmonics = ");
gfx_drawnumber(n1,0);
gfx_x=5;
gfx_y=35;
gfx_drawstr("Saw 2 - No. of Harmonics = ");
gfx_drawnumber(n2,0);
gfx_r = 1;
gfx_g = 0;
gfx_a = 0.5;
gfx_x = ox;
gfx_y = oy;
gfx_lineto(ox+(xscl*tau),oy);
gfx_x = ox;
gfx_y = oy+yscl;
gfx_lineto(ox+(xscl*tau),oy+yscl);
gfx_x = ox;
gfx_y = oy+yscl+yscl;
gfx_lineto(ox+(xscl*tau),oy+yscl+yscl);
gfx_a =1;
gfx_x = ox-12;
gfx_y = oy-5;
gfx_drawstr("1");
gfx_x = ox-12;
gfx_y = oy-5+yscl;
gfx_drawstr("0");
gfx_x = ox-20;
gfx_y = oy-5+yscl+yscl;
gfx_drawstr("-1");
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth

Last edited by Time Waster; 07-03-2017 at 07:32 PM. Reason: Bug fix
Time Waster is offline   Reply With Quote
Old 06-23-2017, 02:06 AM   #4
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Now also in the stash: https://stash.reaper.fm/v/31000/TimeW...r-TwinSaw.jsfx
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-28-2017, 04:06 PM   #5
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

So, any comments before I officially add this to the collection?
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-28-2017, 09:53 PM   #6
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

I did not yet try it, but reading about your way to create a saw and a square wave without aliasing is really interesting !!!

Did you use a spectrum analyzer (e.g. include in ReaEQ) to verify that it works ?

I understand that (Obviously) a square wave is created by subtracting a saw of 2*f and half the amplitude from a saw of 1*f (get rid of the uneven harmonics). Modulating the phase between the two seems like promising an interesting effectr.

Obviously with square (and also with saw) it would be grate to have a modulateable width. Is this "Phase Offset" ?

-Michael

Last edited by mschnell; 06-28-2017 at 09:58 PM.
mschnell is online now   Reply With Quote
Old 06-28-2017, 10:50 PM   #7
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Hi Michael,

I used ReaEQ to analyse the spectrum. I was hoping you might use your FFT spectrum analyser on it.

The phase offset does result in variable pulse width for the square/pulse wave and for any other wave shape created by combining the two saws. Unfortunately it's not possible to use this method to vary an individual saw wave to a triangular wave. I was hoping to do that but I would need a different method of emulation to achieve that. As it is I haven't worked out how to emulate a triangular wave yet.

I should mention that using the filtering, the waveform can be reduced down to a single sine wave, so the oscillator can be used to provide a broad palette of harmonic spectrums, even though the triangular wave is missing.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 07:10 AM   #8
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

To create a triangle you theoretically could use a saw, and multiply it with a rectangle and subtract 1/2. (Of course considering the phase)

If all waveforms are wave limited, this should hold.

-Michael
mschnell is online now   Reply With Quote
Old 06-29-2017, 08:50 AM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by mschnell View Post
To create a triangle you theoretically could use a saw, and multiply it with a rectangle and subtract 1/2. (Of course considering the phase)
Hey, I didn't know that one. That is a nice way to construct a (naive) triangle.

Quote:
Originally Posted by mschnell View Post
If all waveforms are wave limited, this should hold.
What is "wave limited"? If you perhaps mean bandlimited... I don't think the resulting waveform will be bandlimited.
Tale is online now   Reply With Quote
Old 06-29-2017, 09:41 AM   #10
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Quote:
If anyone is interested in giving this oscillator a test run, I would be interested in feedback regarding it's useflness and performance before I add it to the ReaRack collection. See the JSFX code below.
Will have a closer look-like this type of stuff.

Quote:
Originally Posted by Tale View Post
Hey, I didn't know that one. That is a nice way to construct a (naive) triangle.


What is "wave limited"? If you perhaps mean bandlimited... I don't think the resulting waveform will be bandlimited.
What do you guys know about partials?
Have either of you looked at image reasynthesis like what harmor vst does?
Harmor does some awesome partial bandwidth filtering+++ the eq sections there are quite unique working at the precision granular level. =)

Pretty sure witti made some image based js already-might be usefull to reamod for new complex waveform reaconstructions >>?
Any thoughts on this page--> https://christianfloisand.wordpress.com/tag/partials/
Bri1 is offline   Reply With Quote
Old 06-29-2017, 05:13 PM   #11
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by Tale View Post
Hey, I didn't know that one. That is a nice way to construct a (naive) triangle.


What is "wave limited"? If you perhaps mean bandlimited... I don't think the resulting waveform will be bandlimited.
I didn't know that either.

If you add band limited waveforms, the result is also bandlimited. Not sure if that applies to multiplication, but should be easy enough to find out.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 05:32 PM   #12
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by Bri1 View Post
Will have a closer look-like this type of stuff.



What do you guys know about partials?
Have either of you looked at image reasynthesis like what harmor vst does?
Harmor does some awesome partial bandwidth filtering+++ the eq sections there are quite unique working at the precision granular level. =)

Pretty sure witti made some image based js already-might be usefull to reamod for new complex waveform reaconstructions >>?
Any thoughts on this page--> https://christianfloisand.wordpress.com/tag/partials/
Just a general comment, additive synthesis is computationally expensive, as is oversampling and filtering, so what I'm trying to do is to use a shortcut method to approximate a bandlimited waveform closely enough to provide adequate filtering of unwanted frequencies above Nyquist. Also, most of the stuff you mention is beyond my current understanding and it looks like a bottomless pit of learning. So in part I'm just being lazy.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 07:54 PM   #13
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

I tried a quick mod of the FX to create a triangular waveform using Michael's suggested method, but unfortunately it doesn't work with the bandlimited waveforms:



Mal.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 09:14 PM   #14
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Tale View Post
What is "wave limited"? If you perhaps mean bandlimited... I don't think the resulting waveform will be bandlimited.
Of course I meant band-limited
While I suppose you are right that multiplying two band-limited signals will create additional harmonics outside the band, it might be worth a try if their amplitude is high enough to do much harm.

Otherwise you could apply your method to create a band-limited saw to a triangle-function.

-Michael
mschnell is online now   Reply With Quote
Old 06-29-2017, 09:19 PM   #15
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Time Waster View Post
I tried a quick mod of the FX to create a triangular waveform using Michael's suggested method, but unfortunately it doesn't work with the bandlimited waveform.
Hmm. As the negative peak looks as it should but the positive looks funny, something (supposedly the phase) seems to have gone wrong and might need special handling (e.g. shifting the phase by a sample). How sos the spectrum look like ? How exactly does the appropriate rectangle wave look like ? Obviously its edge is not exactly where the edge of the saw is.

-Michael

Last edited by mschnell; 06-29-2017 at 09:28 PM.
mschnell is online now   Reply With Quote
Old 06-29-2017, 09:36 PM   #16
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Time Waster View Post
the best way to reduce aliasing was to limit the frequencies in the original waveform, rather than trying to fix it later with oversampling
This of course is a decent suggestion, in case there is an algorithm (straight forward mathematical function of time) to create the band-limited wave-form with a pre-defined frequency limit in infinite time-accuracy (In fact I don't know such an algorithm). But in fact, Oversampling and filtering before re-sampling to the final sampling rate does not "fix anything later" but allows to create the band-limited wave-form with a pre-defined frequency limit in "appropriate" (depending on the oversampling-factor) time-accuracy.

-Michael
mschnell is online now   Reply With Quote
Old 06-29-2017, 10:28 PM   #17
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by mschnell View Post
Hmm. As the negative peak looks as it should but the positive looks funny, something (supposedly the phase) seems to have gone wrong and might need special handling (e.g. shifting the phase by a sample). How sos the spectrum look like ? How exactly does the appropriate rectangle wave look like ? Obviously its edge is not exactly where the edge of the saw is.

-Michael
I experimented with the phase offset, but it doesn't help.

The problem is that neither the edge of the bandlimited saw or square waves are vertical. The function you suggest relies on concurrence of the step changes in the two waveforms to produce the required wave shape. It works with the naive waveforms, but not in cases where the slope of the step change is less than infinite.

The spectrum results as per the waveform in the image above are not bandlimited, I assume due to the discontinuities at the inflection points.

Mal.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 11:02 PM   #18
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by mschnell View Post
This of course is a decent suggestion, in case there is an algorithm (straight forward mathematical function of time) to create the band-limited wave-form with a pre-defined frequency limit in infinite time-accuracy (In fact I don't know such an algorithm). But in fact, Oversampling and filtering before re-sampling to the final sampling rate does not "fix anything later" but allows to create the band-limited wave-form with a pre-defined frequency limit in "appropriate" (depending on the oversampling-factor) time-accuracy.

-Michael
I'm probably being a bit flippant.

As I understand it, the basic process of oversampling and filtering is that you first oversample a naive waveform (and it appears that there are a few way to do that, e.g. zero stuffing), then apply a filter to it (i.e. "fix it later") to create the bandlimited waveform. You then sample the bandlimited waveform at the required samplerate and render that as the final waveform. Also AIUI, there is a trade-off between the degree of oversampling and the steepness of the filter. Please correct me if I'm wrong.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-29-2017, 11:18 PM   #19
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by Time Waster View Post
I tried a quick mod of the FX to create a triangular waveform using Michael's suggested method, but unfortunately it doesn't work with the bandlimited waveforms:

Same results here (testing with both polyBLEP and Fourier series saw * square). However, because the lower half looks OK I also tested what happens if you mirror the lower half to the upper half. This results in less aliasing than a naive triangle, but still more then when using a simple polyBLEP triangle.
Tale is online now   Reply With Quote
Old 06-29-2017, 11:44 PM   #20
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

This is what the bandlimited triangular wave should look like (16 harmonics). Created with addition of sines:

__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-30-2017, 01:11 AM   #21
Aesis
Human being with feelings
 
Join Date: Jan 2011
Posts: 445
Default

Quote:
Originally Posted by Time Waster View Post
I didn't know that either.

If you add band limited waveforms, the result is also bandlimited. Not sure if that applies to multiplication, but should be easy enough to find out.
The result won't apply to multiplied waveforms since that is equivalent to convolving the frequency spectrum.
Aesis is offline   Reply With Quote
Old 06-30-2017, 04:21 AM   #22
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Time Waster View Post
As I understand it, the basic process of oversampling and filtering is that you first oversample a naive waveform (and it appears that there are a few way to do that, e.g. zero stuffing),
Not zero stuffing or simlar, but you "virtually" pick samples from the mathematical construction function in the augmented sample rate and then at that high sample rate calculate a (steep) low pass according the Nyquist demand of the target sample rate. Finally you use a re-sample algorithm (optionally with dithering) to create the final samples.

Quote:
Originally Posted by Time Waster View Post
Also AIUI, there is a trade-off between the degree of oversampling and the steepness of the filter. Please correct me if I'm wrong.
IMHO, the "optimal" steepness of the filter is just a matter of not too much artifacts due to missing the Nyquist demand and not loosing too much useful harmonics of the signal. The oversampling factor just allows for a certain type of filter to be decently calculated. Obviously, a steeper filter will need a higher factor.

-Michael
mschnell is online now   Reply With Quote
Old 06-30-2017, 04:33 AM   #23
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Tale View Post
Same results here (testing with both polyBLEP and Fourier series saw * square).
This seems to be by far worse than just creating some aliasing.
Did you try varying the phase between the waves ?
Could you do Oscilloscope pictures of the saw and square waves ?

-Michael
mschnell is online now   Reply With Quote
Old 06-30-2017, 06:21 AM   #24
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

My conclusion is that there probably isn't a simple way to create a true bandlimited triangular wave using a combination of saw and square/pulse waves. It took me a few months to work out the method for the saw wave. A triangular wave is less useful for synthesis than either the saw or square/pulse, so I've shelved the triangular wave for now, until I come up with some inspiration as to how to approach it.

I was able to create the saw wave using a continuous function and there are no significant discontinuities (apart from at the zero crossing points where it doesn't matter). Although the triangular wave looks simpler than either the saw or square waves, a function to emulate it needs to be continuous at the inflection points at either peak. Not so easy.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 06-30-2017, 06:56 AM   #25
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Quote:
My conclusion is that there probably isn't a simple way to create a true bandlimited triangular wave using a combination of saw and square/pulse waves.
The easiest and most efficieant way is by reasynthesis-image based oscillators {imo}
All standard shapes are known and can be imaged and considering were using sample data-the resolution for these can just be created per project sample rate.

If your actually trying to create a human voice-lets say the phrase "ahhh" I think it's far better resource wise to image that.
Wavetables become easier like this^ easily scanned along the timeline.
Once it's imaged,it can be partial filtered-partials are switched on and off @ certain amplitudes==less to compute overall,and actually more selective refinements with processing in total.

Cockos could look into this for the arrange waveforms as well I reckon.
There can be modes for synthesis qualities on editing playback and super hq for renders.
Bri1 is offline   Reply With Quote
Old 07-03-2017, 07:33 PM   #26
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Just in case anyone is trying to use this module, I found a bug which was preventing note off messages from being passed through, now fixed in the code above and in the stash copy.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-04-2017, 04:31 AM   #27
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Quote:
Just in case anyone is trying to use this module, I found a bug which was preventing note off messages from being passed through, now fixed in the code above and in the stash copy.
Hiyo-um I can't seem to get anything from this atmo.. it saved and compiled ok,but no sound-nothing--I have midi input on the channel but=nothing.
Where did I go wrong? something is missing.... :/
Ohh and 1st main issue' was it is too big for screen resolution used here-there used to be scroll bars for fx windows,but this got changed to make vst windows fit defaults better I think=problem for this js window now.

*EDIT* ahh fixed! - the window sizing is fine here anyways,coz I got 2 screens,but some might not. npz-onto> tests.Thnxxx.

Last edited by Bri1; 07-04-2017 at 04:41 AM.
Bri1 is offline   Reply With Quote
Old 07-04-2017, 05:46 AM   #28
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by Bri1 View Post
Ohh and 1st main issue' was it is too big for screen resolution used here-there used to be scroll bars for fx windows,but this got changed to make vst windows fit defaults better I think=problem for this js window now..
I didn't realise that there used to be scroll bars? I've already put up a feature request to have them put back in!
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-04-2017, 05:59 AM   #29
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Quote:
I didn't realise that there used to be scroll bars? I've already put up a feature request to have them put back in!
Lol sometimes people make stuff-sometimes people break stuff-cockos are no different I guess.
This is quite kool btw on 1st drive=already found potentials here-many thanx. =)
I did notice something using a different asio card -distortion came ealier on output.Might make a video or 2>(only problem there is having to capture using wasapi drivers atmo)

Last edited by Bri1; 07-04-2017 at 06:00 AM. Reason: 1Extra.
Bri1 is offline   Reply With Quote
Old 07-04-2017, 06:12 AM   #30
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

@Bri1, You have to watch the levels on this module, it can go above 0dB. Are you using the rest of ReaRack with it?
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-04-2017, 07:15 AM   #31
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Npz Time Waster- when testing it's standard procedure to wear extra thick rubber wellies and extra thick tin hat.
I believe you might be the 1 to put image synthesis into reaper!?!?!
Have you ever considered teaming with a couple of other scripters/gui makers to possibly achieve that?
Think- image-gain is greyscale-pitch is grey scale(maybe embossed? gl filters could be used I guess?) and the partials are morphed-harmor uses about 512snapshots that are morphed over time.
The fundamentals can be closely preserved.
Might be something else to wastetime with.. =)
Bri1 is offline   Reply With Quote
Old 07-04-2017, 07:33 PM   #32
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by Bri1 View Post
I believe you might be the 1 to put image synthesis into reaper!?!?!
I'm not so sure about that. I think I understand what Harmor is doing, but I don't think my coding or maths skills are really up to it. Recently I had to use calculus for the first time in the 40 odd years since I left school. That was a struggle!

What Harmor is doing, adding partials, is the antithesis of what I'm trying to do with the twin saw oscillator. Adding partials requires high CPU use, which is not good if you want to be able to use a number of oscillators for subtractive synthesis. So the objective of the twin saw oscillator is to approximate a bandlimited waveform without having to add the partials. While developing this I did create an additive oscillator, firstly to test the CPU use and later to use as a reference the development of the twin saw. I've uploaded the additive oscillator here: https://stash.reaper.fm/v/31068/Time...scillator.jsfx
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-04-2017, 07:55 PM   #33
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Here's another oscillator I created along the way to the twin saw: https://stash.reaper.fm/v/31069/TimeW...scillator.jsfx

This is a 'trapezoidal' oscillator. The waveform is basically a deformable square wave. There are three parameters:

Shape - controls the slope of the sides of the waveform, changing it from square through to triangular.

Width - controls the pulse width.

Rake - used to morph from triangular through to sawtooth.

This oscillator is 'semi-bandlimited'. The parameters are limited so that the shape is never less that those of a trapezoid which would approximate the shape of one half of a sine wave at Nyquist frequency. This does seem to have the effect of reducing the amount of aliasing, but it still wasn't good enough, hence the twin saw.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-04-2017, 10:10 PM   #34
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Time Waster View Post
Adding partials requires high CPU use, which is not good ...
I recently did some work with FFT in JSFX. While this is really nice and effective, without doing rather complex additional coding (resulting in taking addition CPU cycles), you get a delay of one FFT window (i.e. the time taken by the lowest frequency supposed to be handled by your code).

I understand that this is not what you want with you synth suite of JKSFXes.

-Michael
mschnell is online now   Reply With Quote
Old 07-04-2017, 10:12 PM   #35
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

Quote:
Originally Posted by Time Waster View Post
Here's another oscillator I created along the way to the twin saw:
I hope to find the time to test the oscillators, soon.
-Michael
mschnell is online now   Reply With Quote
Old 07-05-2017, 07:28 AM   #36
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
Default

In a first test with my crude FFT spectrum analyzer, the band limiting seems to work very well, only very low level of aliasing can be found.

-Michael
mschnell is online now   Reply With Quote
Old 07-05-2017, 08:26 AM   #37
Bri1
Banned
 
Join Date: Dec 2016
Location: England
Posts: 2,432
Default

Quote:
Are you using the rest of ReaRack with it?
^Well I was not then,but have checked them.

Quote:
is the antithesis of what I'm trying to do with the twin saw oscillator.
Fair enough-I thought it might be within your grasp-sorry togo wildly off~topic.

Quote:
Here's another oscillator I created along the way to the twin saw:
This is a 'trapezoidal' oscillator.
Alright-thanks will check it out.

Some feedback- had a session and made vid-on reaview of that,I noticed some curious things going on in the cockos scopes(can upload if wanted.)
Module did not default reset-had to reacompile/reafresh that way.
There is a massive difference when transitioned from 4-5 harmonics-->on the scope anyways it shows that(big jump there?)

Will have another bash at it again sometime-using/check all the mod sources.
Good job-Cheerz. =)
Bri1 is offline   Reply With Quote
Old 07-05-2017, 04:32 PM   #38
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by Bri1 View Post
There is a massive difference when transitioned from 4-5 harmonics-->on the scope anyways it shows that(big jump there?)
I would expect that. Up to 4 harmonics, the waveform is calculated by addition of partials, so there are no frequencies above the highest harmonic (perfectly band limited). Above 4 harmonics the algorithm kicks in, which only approximates the waveform, so there is some aliasing creating some content above the band limit.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Old 07-05-2017, 04:47 PM   #39
C-H
Human being with feelings
 
Join Date: Apr 2015
Location: Tucson, AZ
Posts: 373
Default

Quote:
Originally Posted by Time Waster View Post
I'm not so sure about that. I think I understand what Harmor is doing, but I don't think my coding or maths skills are really up to it. Recently I had to use calculus for the first time in the 40 odd years since I left school. That was a struggle!

What Harmor is doing, adding partials, is the antithesis of what I'm trying to do with the twin saw oscillator. Adding partials requires high CPU use, which is not good if you want to be able to use a number of oscillators for subtractive synthesis. So the objective of the twin saw oscillator is to approximate a bandlimited waveform without having to add the partials. While developing this I did create an additive oscillator, firstly to test the CPU use and later to use as a reference the development of the twin saw. I've uploaded the additive oscillator here: https://stash.reaper.fm/v/31068/Time...scillator.jsfx
Just a guess/question here:

Is Harmor doing a FFT on the waveform fed into it and then adding a set of Sine waves up to a certain harmonic to recreate the sound?
That would result in a band-limited signal coming out of it.
__________________
Stash : M-Audio Oxygen 49 KeyMap
Stash : M-Audio Oxygen 49 v2 KeyMap
C-H is offline   Reply With Quote
Old 07-05-2017, 07:17 PM   #40
Time Waster
Human being with feelings
 
Time Waster's Avatar
 
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
Default

Quote:
Originally Posted by mschnell View Post
In a first test with my crude FFT spectrum analyzer, the band limiting seems to work very well, only very low level of aliasing can be found.

-Michael
Thanks Michael. Can you post some plots? Would be interested to see how it looks.
__________________
Mal, aka The Wasters of Time
Mal's JSFX: ReaRack2 Modular Synth
Time Waster is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 11:27 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.