# Observing sawtooth spectrum

I have measured the output of a triangle wave using a spectrum analyser. This is controlled via digital, but oscillates completely by analogue circuitry. It is from the design of a music synth. I am trying to understand the spectrum completely. I understand the harmonic frequencies, but there are a lot of small spikes in between. What could be causing this?

• The small spikes mean that your waveform is not perfect. The only time they are not present is if you have a mathematical perfect signal. Commented Apr 21, 2018 at 14:30

Let's have a go at rebuilding with MATLAB the signal from the supplied screenshot between -98 dBu and -2 dBu and play it.

1.- Input signal

A=imread('input signal 2.jpg');
A=A(:,:,3);    % blue

B=~imbinarize(A);

figure;
imshow(B);


[Ny,Nx]=size(B);

B2=zeros(size(B));

E=zeros(1,Nx);              % envelope of interest

for k1=1:1:Nx
Ly=B(:,k1);
n1=find(Ly==1);
n1=min(n1);
if ~isempty(n1)
E(k1)=n1;
B2(n1,k1)=1;
end
end

figure;
imshow(B2)


E=Ny-E;                     % flip
n2=find(E>540);         %  remove amplitude outliers
E(n2(2:end))=0;         % do not take DC as outlier
E(1266:end)=[];          % remove frequency outliers

figure;
ax=gca
stem(E);
grid on
xlabel('f[Hz]')
hold on


This stem plot needs Y X alignment to dBu and kHz.

Rewording, this is already the sought envelope, but without amplitude or frequency references.

2.- Y alignment : pixels to dBu

px_per_dB=(620 - 150)/abs(-2-(-98))    %  px/dB
dB_per_px=1/px_per_dB                      %  dB/px

grid_dy=floor(12/dB_per_px)+1  % round up 1px to get accurate DC
grid_ny=floor(Ny/grid_dy)

for k2=1:1:grid_ny
plot(ax,[1 Nx],k2*[grid_dy grid_dy],'Color',[.5 .5 .5]);
% plot([1 Nx],k2*[grid_dy grid_dy],'Color','r');
end

% ny=1 means y(1)=-98
% ny=9*grid_ny means y(9*grid_ny)=-2

ax.YTick=grid_dy*[1:1:9];
ax.YTickLabel=[-98:12:-2];
ylabel(ax,'dBu');

m1=(-2+98)/(9*grid_dy);

E2=m1*E-98;   % E2 contains dBu values


3.- X alignment : pixels to kHz

x=0 : f=0Hz

nf20khz=1091-56   % 1035     % amount pixels at 20kHz

px_per_khz=floor(1035/20)+1
khz_per_px=1/px_per_khz

f=[0:1:Ny-1]*2e4/nf20khz;    % Hz

grid_nx=5;   % draw 5 grid divisions spaced 5kHz
grid_dx=5*px_per_khz

ax.XTick=[0:1:grid_nx]*grid_dx;
ax.XTickLabel=[0:1:grid_nx-1]*5;
xlabel(ax,'f[kHz]');

for k2=1:1:grid_nx
plot(ax,k2*[grid_dx grid_dx],[1 Ny],'Color',[.5 .5 .5])
end


Now we have dBu over kHz, like in the question

4.- dBu to Vrms

E2 contains dBu values

dBu = 20 * log10(Vrms/((600*1e-3)^.5))

Vrms=((600*1e-3)^.5)*10.^(E2/20);


Vrms is spectrum

5.- rebuilding time signal

base cycle

v_rms0=abs(ifft(Vrms));


assume real signal, ignore complex

Fs=20*f(end);                    % assuming 20 samples/(top cycle) sampling
dt=1/Fs                         % time step

t0=[0:1:numel(v_rms0)]*dt;   % possible time reference

v_rms0=v_rms0(1:min(numel(t0),numel(v_rms0)));
t0=t0(1:min(numel(t0),numel(v_rms0)));


how does the base cycle look like

figure
plot(t0,v_rms0);
grid on
xlabel('t');ylabel('v')
title(['v(t) 1 cycle'])


6.- Make signal long enough to hear it

assume cyclic

N=1000  % repeating cycle long enough to be able to hear it on .wav file


amplifying 27dB , v itself as rebuilt seems too weak

v=500*repmat(v_rms0,1,N);
t=[];
for k=1:1:N
t=[t t0(end)*k+t0(2:end)];
end

v=v(1:min(numel(t),numel(v)));
t=t(1:min(numel(t),numel(v)));

audiowrite('test_123.wav',v,floor(Fs))


I have uploaded the track here

2.4 MB .wav file, 5 seconds approx, of rebuilt signal.

7.- Listen Always

It sounds like 2 tones, may be 2 triangulars. Dissonance : sounds an alarm or buzzer.

The in-between spikes you mention to be between the spikes you consider the signal, all those clearly above noise ARE an integral part a signal made by multiple tones and pulses.

When one plays 2 dissonant tones like any 2 tones close in frequency, let's say C and D, or C and D-flat, the resulting frequency spikes are really close in frequency, causing roughly double and multiples above, the sum of frequencies.

It also causes harmonics with difference frequency, and respective multiples.

Also, triangular and sawtooth signals have really populated spectrums in comparison to sin cos tones. Triangular or sawtooth spectrums look like the image in the question. Probably more than 1.

Using logarithmic scale also causes and apparent, yet nor real, increase of relevance of the noise always present.

If you plot the signal in linear Y scale you will see how many spikes, yet present and necessary, are far lower than they seem to be when using dB.

• A brilliant answer. I've re-uploaded the audio file with attribution to SoundCloud, so that it won't get lost. The file hosting service used before discards the data, and this answer is so great I would never want anything to get lost. If you'd like to upload to SoundCloud yourself, feel free, and edit the answer to get the link to point to your own upload of course. Commented Aug 29, 2023 at 16:13
• thanks Kuba :) I just uploaded to the first site I found. The question originator has the audio file, or the scope signal. Next one straight to SoundCloud. Commented Sep 1, 2023 at 12:49

Possible sources:

• Noise? (of the signal, of the measurement, of ...)
• Distortion of the signal? (= deviations from the ideal wave form)
• Calculation errors? (assuming that the FFT was calculated by a µC/DSP/FPGA/...)
• Who nows what else?

Are the little spikes really relevant?

• I'll go with distortion. Note that the first "little" spike (2nd harmonic) is 30 dB down. Commented Apr 21, 2018 at 14:35
• I second WhatRoughBeast: note the noise floor is ~74dB, and the high(er)-frequency peaks go above 60dB. It seems like a "fairly good" waveform. Commented Apr 21, 2018 at 14:55
• so im guessing 30db is inaudible ? is there a rule that I can follow that helps me understand what is acceptable, good or too much ? Commented Apr 21, 2018 at 15:02
• The trick is in the ratios. Sound and loudness are complex subjects and I don't know the rules. If I simplify it a bit (/a lot): 60dB is normal conversation, 30dB is silent library. Thus you have to be able to hear whispering whilst somebody is talking normally. Commented Apr 21, 2018 at 16:15