|
|
|
06-22-2017, 07:59 PM
|
#1
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
06-22-2017, 08:11 PM
|
#2
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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;
);
);
);
Last edited by Time Waster; 07-03-2017 at 07:30 PM.
Reason: Bug fix
|
|
|
06-22-2017, 08:12 PM
|
#3
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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");
Last edited by Time Waster; 07-03-2017 at 07:32 PM.
Reason: Bug fix
|
|
|
06-23-2017, 02:06 AM
|
#4
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
|
|
|
06-28-2017, 04:06 PM
|
#5
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
So, any comments before I officially add this to the collection?
|
|
|
06-28-2017, 09:53 PM
|
#6
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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.
|
|
|
06-28-2017, 10:50 PM
|
#7
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
06-29-2017, 07:10 AM
|
#8
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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
|
|
|
06-29-2017, 08:50 AM
|
#9
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
|
Quote:
Originally Posted by mschnell
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
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.
|
|
|
06-29-2017, 09:41 AM
|
#10
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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
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/
|
|
|
06-29-2017, 05:13 PM
|
#11
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by Tale
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.
|
|
|
06-29-2017, 05:32 PM
|
#12
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by Bri1
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.
|
|
|
06-29-2017, 07:54 PM
|
#13
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
06-29-2017, 09:14 PM
|
#14
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Tale
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
|
|
|
06-29-2017, 09:19 PM
|
#15
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Time Waster
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.
|
|
|
06-29-2017, 09:36 PM
|
#16
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Time Waster
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
|
|
|
06-29-2017, 10:28 PM
|
#17
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by mschnell
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.
|
|
|
06-29-2017, 11:02 PM
|
#18
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by mschnell
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.
|
|
|
06-29-2017, 11:18 PM
|
#19
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
|
Quote:
Originally Posted by Time Waster
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.
|
|
|
06-29-2017, 11:44 PM
|
#20
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
This is what the bandlimited triangular wave should look like (16 harmonics). Created with addition of sines:
|
|
|
06-30-2017, 01:11 AM
|
#21
|
Human being with feelings
Join Date: Jan 2011
Posts: 445
|
Quote:
Originally Posted by Time Waster
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.
|
|
|
06-30-2017, 04:21 AM
|
#22
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Time Waster
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
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
|
|
|
06-30-2017, 04:33 AM
|
#23
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Tale
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
|
|
|
06-30-2017, 06:21 AM
|
#24
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
06-30-2017, 06:56 AM
|
#25
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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.
|
|
|
07-03-2017, 07:33 PM
|
#26
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
07-04-2017, 04:31 AM
|
#27
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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.
|
|
|
07-04-2017, 05:46 AM
|
#28
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by Bri1
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!
|
|
|
07-04-2017, 05:59 AM
|
#29
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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.
|
|
|
07-04-2017, 06:12 AM
|
#30
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
@Bri1, You have to watch the levels on this module, it can go above 0dB. Are you using the rest of ReaRack with it?
|
|
|
07-04-2017, 07:15 AM
|
#31
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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.. =)
|
|
|
07-04-2017, 07:33 PM
|
#32
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by Bri1
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
|
|
|
07-04-2017, 07:55 PM
|
#33
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
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.
|
|
|
07-04-2017, 10:10 PM
|
#34
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Time Waster
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
|
|
|
07-04-2017, 10:12 PM
|
#35
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by Time Waster
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
|
|
|
07-05-2017, 07:28 AM
|
#36
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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
|
|
|
07-05-2017, 08:26 AM
|
#37
|
Banned
Join Date: Dec 2016
Location: England
Posts: 2,432
|
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. =)
|
|
|
07-05-2017, 04:32 PM
|
#38
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by Bri1
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.
|
|
|
07-05-2017, 04:47 PM
|
#39
|
Human being with feelings
Join Date: Apr 2015
Location: Tucson, AZ
Posts: 373
|
Quote:
Originally Posted by Time Waster
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.
|
|
|
07-05-2017, 07:17 PM
|
#40
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,643
|
Quote:
Originally Posted by mschnell
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.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 11:27 PM.
|