2
$\begingroup$

I'm trying to convert sawtooth wave calculation formula to Octave/Matlab language. Here are the original formulas. My Desmos take is here. I've got formulas for triangle wave and square wave working but, sawtooth won't work in either way like showed in Desmos sheet (two last formulas there).

Here's my Octave code (active saw calculation is simplified version of the above equation in comments):

function saw = saw_wave_trig(fs, f0, s, m, w)
% fs = sample rate
% f0 = fundamental frequency
% s  = 'sharpness'
% w  = 'width'
% m  = 'tooth direction'
% example: saw = saw_wave_trig(44100, 440, 0.03, -2, 1);

t = 0:1/fs:1;
##saw = m .* ((1.+ triangle_wave_trig(fs, (2*(f0/w)+1)/4, s, w) .* ...
##              square_wave_trig(fs, f0/2, s, w))./2) ... 
##     .- sign(m);

##saw =  m .* ...
##            (1 .+ ...
##                  ((1.-(2.*acos((1-s) .* sin((2*pi*((2*(f0/w)+1)/4)).*t')))./pi) .* ...
##                       (2 .* atan(sin((2*pi*(f0/w/2)) .* t')./s))./pi)) ./ ... 
##                         2 .- sign(m);

saw = (4.*asin((s-1).*sin((pi*t'.*(2*f0+w))./ ...
        (2*w))).*acot(s*csc((pi*f0.*t')./w)))./pi^2-sign(m)-1;
     
audiowrite('test_saw_trig_wave.wav',saw, fs);
plot(t, saw);

which (the commented calculations as well) produces kind of morph from negative side triangle wave to correct looking sawtooth wave, as seen in attached plot (Audacity used):

enter image description here

So, as my knowledge in math and Octave/Matlab is quite limited, there sure is some basics done wrong in my Octave/Matlab code. Maybe the multiplication of triangle and square needs to be done differently?

Any help in solving this is appreciated.

NOTE! This method is part of the experiment I'm doing with various methods out there to synthesize sawtooth (and other type) waves for audio use.

EDIT: Here are those triangle_wave_trig() and square_wave_trig() functions (f1() and f2() in Desmos sheet) which of both works correctly:

function tri = triangle_wave_trig(fs, f0, s, w) 
% fs = sample rate 
% f0 = fundamental frequency 
% s  = 'sharpness' 
% w  = 'width' 
% example: tri = triangle_wave_trig(44100, 440, 0.03, 1); 
 
  t = 0:1/fs:1; 
  tri = 1 .- (2 .* acos((1 - s) .* sin((2 * pi * (f0 / w)) .* t')) ./ pi); 
  
  audiowrite('test_triangle_wave.wav',tri, fs); 
  plot(t, tri);

function sqw = square_wave_trig(fs, f0, s, w)
% fs = sample rate
% f0 = fundamental frequency
% s  = 'sharpness'
% w  = 'width'
% example: sqw = square_wave_trig(44100, 440, 0.03, 1);

  t = 0:1/fs:1;
  sqw = 2.0 .* (atan(sin((2 * pi * (f0 / w)) .* t') ./ s) ./ pi);

  audiowrite('test_square_wave_trig.wav',sqw, fs);
  plot(t, sqw);
  hold on;
  plot(t, square(2*pi*f0*t'));

sqw = square_wave_trig(44100, 440, 0.03, 1); looks like this:

enter image description here

and generated wave file looks OK (same with the triangle wave function).

$\endgroup$
4
  • $\begingroup$ Any reason not to use Matlab's sawtooth function directly? $\endgroup$
    – MBaz
    Commented May 27, 2021 at 22:15
  • $\begingroup$ Hmm... to synthesise sawtooth waves for audio use? No, this is experimenting I'm doing with various methods out there (I would use BLEPs in real work). $\endgroup$
    – Juha P
    Commented May 28, 2021 at 2:48
  • $\begingroup$ Is your sampling rate large enough? I would start with fs = 20*f0. $\endgroup$
    – MBaz
    Commented May 28, 2021 at 13:01
  • $\begingroup$ Sampling rate should be OK (edited my post). $\endgroup$
    – Juha P
    Commented May 28, 2021 at 13:38

1 Answer 1

1
$\begingroup$

OK, got this solved by @omersayli (dsprelated).

I had put the variable t to a wrong location in both (triangle and square wave) formulas. Here's the correct formula for calculation of saw:

saw = -(2.*m.*asin((s-1)*cos((pi*f0*t)/w)).*acot(s.*csc((pi*f0*t)/w)))./pi^2.-sign(m).+m./2;
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.