CM0340 Tutorial 5: MATLAB BASIC DSP and Synthesis

advertisement
CM0340 Tutorial 5: MATLAB BASIC DSP
and Synthesis
1
In this tutorial we explain some of the DSP and MATLAB concepts
discussed in the lectures leading up to Digital Audio Synthesis.
We start by looking at basic signal waveforms.
The code that is used over the next few slides is waveforms.m
JJ
II
J
I
Back
Close
Simple Waveforms
2
• Frequency is the number of cycles per second and is measured in
Hertz (Hz)
• Wavelength is inversely proportional to frequency
i.e. Wavelength varies as
1
f requency
JJ
II
J
I
Back
Close
The Sine Wave and Sound
3
The general form of the sine wave we shall use (quite a lot of) is as
follows:
y = A.sin(2π.n.Fw /Fs)
where:
A is the amplitude of the wave,
Fw is the frequency of the wave,
Fs is the sample frequency,
n is the sample index.
JJ
II
J
I
MATLAB function: sin() used — works in radians
Back
Close
MATLAB Sine Wave Radian Frequency
Period
Basic 1 period Simple Sine wave — 1 period is 2π radians
4
% Basic 1 period Simple Sine wave
i=0:0.2:2*pi;
y = sin(i);
figure(1)
plot(y);
% use stem(y) as alternative plot as in lecture notes to
% see sample values
title(’Simple 1 Period Sine Wave’);
JJ
II
J
I
Back
Close
MATLAB Sine Wave Amplitude
Sine Wave Amplitude is -1 to +1.
5
To change amplitude multiply by some gain (amp):
% Now Change amplitude
amp = 2.0;
y = amp*sin(i);
figure(2)
plot(y);
title(’Simple 1 Period Sine Wave Modified Amplitude’);
JJ
II
J
I
Back
Close
MATLAB Sine Wave Frequency
%
%
%
%
%
%
Natural frequency is 2*pi radians
If sample rate is F_s HZ then 1 HZ is 2*pi/F_s
If wave frequency is F_w then freequency is F_w* (2*pi/F_s)
set n samples steps up to sum duration nsec*F_s where nsec is the
duration in seconds
So we get y = amp*sin(2*pi*n*F_w/F_s);
6
F_s = 11025;
F_w = 440;
nsec = 2;
dur= nsec*F_s;
n = 0:dur;
y = amp*sin(2*pi*n*F_w/F_s);
figure(3)
plot(y(1:500));
title(’N second Duration Sine Wave’);
JJ
II
J
I
Back
Close
MATLAB Sine Wave Plot of n cycles
% To plot n cycles of a waveform
7
ncyc = 2;
n=0:floor(ncyc*F_s/F_w);
y = amp*sin(2*pi*n*F_w/F_s);
figure(4)
plot(y);
title(’N Cycle Duration Sine Wave’);
JJ
II
J
I
Back
Close
Cosine, Square and Sawtooth Waveforms
MATLAB functions cos() (cosine), square() and sawtooth()
similar.
8
JJ
II
J
I
Back
Close
MATLAB Cos v Sin Wave
% Cosine is same as Sine (except 90 degrees out of phase)
yc = amp*cos(2*pi*n*F_w/F_s);
figure(5);
hold on
plot(yc,’b’);
plot(y,’r’);
title(’Cos (Blue)/Sin (Red) Plot (Note Phase Difference)’);
hold off;
9
JJ
II
J
I
Back
Close
Relationship Between Amplitude,
Frequency and Phase
10
JJ
II
J
I
Back
Close
Amplitudes of a Sine Wave
% Simple Sin Amplitude Demo
samp_freq = 400;
dur = 800; % 2 seconds
amp = 1; phase = 0; freq = 1;
s1 = mysin(amp,freq,phase,dur,samp_freq);
11
axisx = (1:dur)*360/samp_freq; % x axis in degrees
plot(axisx,s1);
set(gca,’XTick’,[0:90:axisx(end)]);
fprintf(’Initial Wave: \t Amplitude = ...\n’, amp, freq, phase,...);
% change amplitude
amp = input(’\nEnter Ampltude:\n\n’);
s2 = mysin(amp,freq,phase,dur,samp_freq);
hold on;
plot(axisx, s2,’r’);
set(gca,’XTick’,[0:90:axisx(end)]);
The code is sinampdemo.m
JJ
II
J
I
Back
Close
mysin MATLAB code
The above call function mysin.m which a simple modified version
of previous MATLAB sin function to account for phase.
function s = mysin(amp,freq,phase,dur, samp_freq)
% example function to so show how amplitude,frequency and phase
% are changed in a sin function
% Inputs: amp - amplitude of the wave
%
freq - frequency of the wave
%
phase - phase of the wave in degree
%
dur - duration in number of samples
%
samp_freq - sample frequncy
12
x = 0:dur-1;
phase = phase*pi/180;
s = amp*sin( 2*pi*x*freq/samp_freq + phase);
JJ
II
J
I
Back
Close
Amplitudes of a Sine Wave: sinampdemo
output
1
13
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1
0
90
180
270
360
450
540
630
720
JJ
II
J
I
Back
Close
Frequencies of a Sine Wave
% Simple Sin Frequency Demo
samp_freq = 400;
dur = 800; % 2 seconds
amp = 1; phase = 0; freq = 1;
s1 = mysin(amp,freq,phase,dur,samp_freq);
14
axisx = (1:dur)*360/samp_freq; % x axis in degrees
plot(axisx,s1);
set(gca,’XTick’,[0:90:axisx(end)]);
fprintf(’Initial Wave: \t Amplitude = ...\n’, amp, freq, phase,...);
% change amplitude
freq = input(’\nEnter Frequency:\n\n’);
s2 = mysin(amp,freq,phase,dur,samp_freq);
hold on;
plot(axisx, s2,’r’);
set(gca,’XTick’,[0:90:axisx(end)]);
The code is sinfreqdemo.m
JJ
II
J
I
Back
Close
Amplitudes of a Sine Wave: sinfreqdemo
output
1
15
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1
0
90
180
270
360
450
540
630
720
JJ
II
J
I
Back
Close
Phases of a Sine Wave
% Simple Sin Phase Demo
samp_freq = 400;
dur = 800; % 2 seconds
amp = 1; phase = 0; freq = 1;
s1 = mysin(amp,freq,phase,dur,samp_freq);
16
axisx = (1:dur)*360/samp_freq; % x axis in degrees
plot(axisx,s1);
set(gca,’XTick’,[0:90:axisx(end)]);
fprintf(’Initial Wave: \t Amplitude = ...\n’, amp, freq, phase,...);
% change amplitude
phase = input(’\nEnter Phase:\n\n’);
s2 = mysin(amp,freq,phase,dur,samp_freq);
hold on;
plot(axisx, s2,’r’);
set(gca,’XTick’,[0:90:axisx(end)]);
The code is sinphasedemo.m
JJ
II
J
I
Back
Close
Amplitudes of a Sine Wave: sinphasedemo
output
1
17
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1
0
90
180
270
360
450
540
630
JJ
II
J
I
Back
Close
MATLAB Square and Sawtooth Waveforms
% Square and Sawtooth Waveforms created using Radians
ysq = amp*square(2*pi*n*F_w/F_s);
ysaw = amp*sawtooth(2*pi*n*F_w/F_s);
18
figure(6);
hold on
plot(ysq,’b’);
plot(ysaw,’r’);
title(’Square (Blue)/Sawtooth (Red) Waveform Plots’);
hold off;
JJ
II
J
I
Back
Close
Triangular Waveform
MATLAB function sawtooth(t,width = 0.5) can create a
triangular waveform, but its easy to build one ourselves (later we
make a smoother sounding sawtooth in similar fashion):
% Half Frequency
delta = 2*F_w/F_s;
% min and max values of simple waveform
minf=0;maxf=1;
% create triangle wave of centre frequency values
figure(7); hold on
ytri = [];
% plot n cycles
while(length(ytri) < floor(ncyc*F_s/F_w) )
ytri = [ ytri amp*(minf:delta:maxf) ]; %upslope
doplot = input(’\nPlot Figure? y/[n]:\n\n’, ’s’);
if doplot == ’y’,
plot(ytri,’r’);
figure(7);
end
lasti = length(ytri);
ytri = [ ytri amp*(maxf:-delta:minf) ]; %downslope
doplot = input(’\nPlot Figure? y/[n]:\n\n’, ’s’);
if doplot == ’y’,
plot(ytri,’b’);
figure(7);
end
end
title(’Triangular Waveform Plots’); hold off;
19
JJ
II
J
I
Back
Close
Triangular Waveform Display
2
1.8
1.6
20
1.4
1.2
1
0.8
0.6
JJ
II
J
I
0.4
0.2
0
0
5
10
15
20
25
30
35
40
Back
Close
Using these Waveforms
All above waveforms used (as seen in Lecture notes):
• Base waveforms for various forms of synthesis: Subtractive, FM,
Additive
21
• Modulators and Carrier waveforms for various Digital Audio
effects.
– Low Frequency Oscillators (LFO) to vary filter cut-off
frequencies and delay times
JJ
II
J
I
Back
Close
MATLAB filters
Matlab filter() function implements an IIR
(or an FIR no A components).
22
Type help filter:
FILTER One-dimensional digital filter.
Y = FILTER(B,A,X) filters the data in vector X with the
filter described by vectors A and B to create the filtered
data Y. The filter is a "Direct Form II Transposed"
implementation of the standard difference equation:
a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb)
- a(2)*y(n-1) - ... - a(na+1)*y(n-na)
If a(1) is not equal to 1, FILTER normalizes the filter
coefficients by a(1).
FILTER always operates along the first non-singleton dimension,
namely dimension 1 for column vectors and non-trivial matrices,
and dimension 2 for row vectors.
JJ
II
J
I
Back
Close
A Complete IIR System
x(n − 1)
x(n)
T
x(n − 2)
x(n − N + 1)
T
T
23
×
×
b0
×
b1
b2
×
×
bN −2
bN −1
y(n)
+
×
+
×
−aM
y(n − M )
T
+
×
−aM −1
T
+
−aM −2
×
+
−a1
y(n − 1)
Here we extend:
The input delay line up to N − 1 elements and
The output delay line by M elements.
T
JJ
II
J
I
Back
Close
Complete IIR System Algorithm
x(n − 1)
x(n)
x(n − 2)
T
×
×
b0
x(n − N + 1)
T
T
×
b1
b2
×
×
bN −2
bN −1
24
y(n)
+
×
+
×
−aM
y(n − M )
+
×
−aM −1
T
+
−aM −2
T
×
+
−a1
y(n − 1)
T
We can represent the IIR system algorithm by the difference
equation:
y(n) = −
M
X
k=1
ak y(n − k) +
N −1
X
k=0
bk x(n − k)
JJ
II
J
I
Back
Close
Using filter() in Practice
We have two filter banks defined by vectors: A = {ak }, B = {bk }.
We have to specify some values for them.
• We can do this by hand — we could design our own filters
25
• MATLAB provides standard functions to set up A and B for
many common filters.
JJ
II
J
I
Back
Close
Using filter() in Practice:Hand Coding
Recall from lecture notes:
The MATLAB file IIRdemo.m sets up the filter banks as follows:
fg=4000;
fa=48000;
k=tan(pi*fg/fa);
26
b(1)=1/(1+sqrt(2)*k+kˆ2);
b(2)=-2/(1+sqrt(2)*k+kˆ2);
b(3)=1/(1+sqrt(2)*k+kˆ2);
a(1)=1;
a(2)=2*(kˆ2-1)/(1+sqrt(2)*k+kˆ2);
a(3)=(1-sqrt(2)*k+kˆ2)/(1+sqrt(2)*k+kˆ2);
and then applies the difference equation:
for n=1:N
y(n)=b(1)*x(n) + b(2)*xh1 + b(3)*xh2 - a(2)*yh1 - a(3)*yh2;
xh2=xh1;xh1=x(n);
yh2=yh1;yh1=y(n);
end;
JJ
II
J
I
Back
Close
Filtering with IIR: Simple Example Output
This produces the following output:
1
x(n) →
0.5
27
0
−0.5
−1
0
2
4
6
8
10
12
14
16
18
n→
1
y(n) →
0.5
0
−0.5
−1
0
2
4
6
8
10
n→
12
14
16
18
JJ
II
J
I
Back
Close
Using MATLAB to make filters
MATLAB provides a few built-in functions to create ready made
filter parameter A and B :
E.g: butter, buttord, besself, cheby1, cheby2,
ellip, freqz, filter.
For our purposes the Butterworth filter will create suitable filters,
help butter:
28
BUTTER Butterworth digital and analog filter design.
[B,A] = BUTTER(N,Wn) designs an Nth order lowpass digital
Butterworth filter and returns the filter coefficients in length
N+1 vectors B (numerator) and A (denominator). The coefficients
are listed in descending powers of z. The cutoff frequency
Wn must be 0.0 < Wn < 1.0, with 1.0 corresponding to
half the sample rate.
If Wn
order
[B,A]
[B,A]
[B,A]
is a two-element vector, Wn = [W1 W2], BUTTER returns an
2N bandpass filter with passband W1 < W < W2.
= BUTTER(N,Wn,’high’) designs a highpass filter.
= BUTTER(N,Wn,’low’) designs a lowpass filter.
= BUTTER(N,Wn,’stop’) is a bandstop filter if Wn = [W1 W2].
JJ
II
J
I
Back
Close
Using MATLAB to make filters
help buttord:
BUTTORD Butterworth filter order selection.
[N, Wn] = BUTTORD(Wp, Ws, Rp, Rs) returns the order N of the lowest
order digital Butterworth filter that loses no more than Rp dB in
the passband and has at least Rs dB of attenuation in the stopband.
Wp and Ws are the passband and stopband edge frequencies, normalized
from 0 to 1 (where 1 corresponds to pi radians/sample). For example,
Lowpass:
Wp = .1,
Ws = .2
Highpass:
Wp = .2,
Ws = .1
Bandpass:
Wp = [.2 .7], Ws = [.1 .8]
Bandstop:
Wp = [.1 .8], Ws = [.2 .7]
BUTTORD also returns Wn, the Butterworth natural frequency (or,
the "3 dB frequency") to use with BUTTER to achieve the
specifications.
29
JJ
II
J
I
Back
Close
Using MATLAB Filter Example: Subtractive Synthesis Lecture
Example
The example for studying subtractive synthesis, subtract synth.m,
uses the butter and filter MATLAB functions:
% simple low pas filter example of subtractive synthesis
Fs = 22050;
y = synth(440,2,0.9,22050,’saw’);
30
% play sawtooth e.g. waveform
doit = input(’\nPlay Raw Sawtooth? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(1)
plot(y(1:440));
playsound(y,Fs);
end
%make lowpass filter and filter y
[B, A] = butter(1,0.04, ’low’);
yf = filter(B,A,y);
[B, A] = butter(4,0.04, ’low’);
yf2 = filter(B,A,y);
JJ
II
J
I
Back
Close
% play filtererd sawtooths
doit = ...
input(’\nPlay Low Pass Filtered (Low order) ? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(2)
plot(yf(1:440));
playsound(yf,Fs);
end
31
doit = ...
input(’\nPlay Low Pass Filtered (Higher order)? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(3)
plot(yf2(1:440));
playsound(yf2,Fs);
end
%plot figures
doit = input(’\Plot All Figures? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(4)
plot(y(1:440));
hold on
plot(yf(1:440),’r+’);
plot(yf2(1:440),’g-’);
end
JJ
II
J
I
Back
Close
synth.m
The supporting function, synth.m, generates waveforms as we have
seen earlier in this tutorial:
function y=synth(freq,dur,amp,Fs,type)
% y=synth(freq,dur,amp,Fs,type)
%
% Synthesize a single note
%
% Inputs:
% freq - frequency in Hz
% dur - duration in seconds
% amp - Amplitude in range [0,1]
% Fs - sampling frequency in Hz
% type - string to select synthesis type
%
current options: ’fm’, ’sine’, or ’saw’
if nargin<5
error(’Five arguments required for synth()’);
end
N = floor(dur*Fs);
n=0:N-1;
if (strcmp(type,’sine’))
y = amp.*sin(2*pi*n*freq/Fs);
32
JJ
II
J
I
Back
Close
elseif (strcmp(type,’saw’))
T = (1/freq)*Fs;
ramp = (0:(N-1))/T;
y = ramp-fix(ramp);
y = amp.*y;
y = y - mean(y);
% period in fractional samples
elseif (strcmp(type,’fm’))
33
t = 0:(1/Fs):dur;
envel = interp1([0 dur/6 dur/3 dur/5 dur], [0 1 .75 .6 0], 0:(1/Fs):dur);
I_env = 5.*envel;
y = envel.*sin(2.*pi.*freq.*t + I_env.*sin(2.*pi.*freq.*t));
else
error(’Unknown synthesis type’);
end
% smooth edges w/ 10ms ramp
if (dur > .02)
L = 2*fix(.01*Fs)+1; % L odd
ramp = bartlett(L)’; % odd length
L = ceil(L/2);
y(1:L) = y(1:L) .* ramp(1:L);
y(end-L+1:end) = y(end-L+1:end) .* ramp(end-L+1:end);
end
JJ
II
J
I
Back
Close
synth.m (Cont.)
Note the sawtooth waveform generated here has a non-linear up slope:
0.2
0.15
34
0.1
0.05
0
−0.05
−0.1
−0.15
0
10
20
30
40
50
60
70
80
90
100
This is created with:
ramp = (0:(N-1))/T;
y = ramp-fix(ramp);
fix rounds the elements of X to the nearest integers towards zero.
This form of sawtooth sounds slightly less harsh and is more suitable
for audio synthesis purposes.
JJ
II
J
I
Back
Close
Wavetable Synthesis Examples
Simple form as discussed in Lectures is a simple creation one sine
wave and one saw and then some simple cross-fading between the
waves. The simple example , :
% simple
35
example of Wavetable synthesis
f1 = 440; f2 = 500; f3 = 620;
Fs = 22050;
%Create a single sine waves of frequencie f1
y1 = synth(f1,1/f1,0.9,Fs,’sine’);
doit = input(’\nPlay/Plot Raw Sine y1 looped for 10 ...
seconds? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(1)
plot(y1);
loopsound(y1,Fs,10*Fs/f1);
end
%Create a single Saw waves of frequencie f2
y2 = synth(f2,1/f2,0.9,Fs,’saw’);
JJ
II
J
I
Back
Close
doit = input(’\nPlay/Plot Raw saw y2 looped for 10 ...
seconds? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(2)
plot(y2);
loopsound(y2,Fs,10*Fs/f2);
end
36
%concatenate wave
ywave = [y1 , y2];
% Create Cross fade half width of wave y1 for xfade window
xfadewidth = floor(Fs/(f1*2));
ramp1 = (0:xfadewidth)/xfadewidth;
ramp2 = 1 - ramp1;
doit = input(’\nShow Crossfade Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(4)
plot(ramp1);
hold on;
plot(ramp2,’r’);
end;
%apply crossfade centered over the join of y1 and y2
pad = (Fs/f1) + (Fs/f2) - 2.5*xfadewidth;
JJ
II
J
I
Back
Close
xramp1 = [ones(1,1.5*xfadewidth) , ramp2, zeros(1,pad)];
xramp2 = [zeros(1,1.5*xfadewidth) , ramp1, ones(1,pad)];
% Create two period waveforms to fade between
ywave2 = [y1 , zeros(1,Fs/f2)];
ytemp = [zeros(1,Fs/f1), y2];
ywave = ywave2;
% do xfade
37
% add two waves together over the period modulated by xfade ramps
% (recall .* to multiply matrices element by element
% NOT MATRIX mutliplication
ywave2 = xramp1.*ywave2 + xramp2.*ytemp;
doit = input(’\nPlay/Plot Additive Sines together? Y/[N]:\n\n’, ’s’);
if doit == ’y’,
figure(5)
subplot(4,1,1);
plot(ywave);
hold off
set(gca,’fontsize’,18);
ylabel(’Amplitude’);
JJ
II
J
I
Back
Close
title(’Wave 1’);
set(gca,’fontsize’,18);
subplot(4,1,2);
plot(ytemp);
set(gca,’fontsize’,18);
ylabel(’Amplitude’);
title(’Wave 2’);
set(gca,’fontsize’,18);
subplot(4,1,3);
plot(xramp1);
hold on
plot(xramp2,’r’)
hold off
set(gca,’fontsize’,18);
ylabel(’Amplitude’);
title(’Crossfade Masks’);
set(gca,’fontsize’,18);
subplot(4,1,4);
plot(ywave2);
set(gca,’fontsize’,18);
ylabel(’Amplitude’);
title(’WaveTable Synthesis’);
set(gca,’fontsize’,18);
loopsound(ywave2,Fs,10*Fs/(f1 + f2));
end
38
JJ
II
J
I
Back
Close
RECAP: Wavetable synthesis:Dynamic Waveshaping (1)
Simplest idea: Linear crossfading
• Crossfade from one wavetable to the next sequentially.
39
• Crossfade = apply some envelope to smoothly merge waveforms.
JJ
II
J
I
Back
Close
Simple MATLAB Example: Linear Crossfading
% Create Cross fade half width of wave y1 for xfade window
xfadewidth = floor(Fs/(f1*2));
ramp1 = (0:xfadewidth)/xfadewidth;
ramp2 = 1 - ramp1;
40
%apply crossfade centered over the join of y1 and y2
pad = (Fs/f1) + (Fs/f2) - 2.5*xfadewidth;
xramp1 = [ones(1,1.5*xfadewidth) , ramp2, zeros(1,pad)];
xramp2 = [zeros(1,1.5*xfadewidth) , ramp1, ones(1,pad)];
% Create two period waveforms to fade between
ywave2 = [y1 , zeros(1,Fs/f2)];
ytemp = [zeros(1,Fs/f1), y2];
% do xfade
% add two waves together over the period modulated by xfade ramps
ywave2 = xramp1.*ywave2 + xramp2.*ytemp;
JJ
II
J
I
Back
Close
Simple MATLAB Example: Linear Crossfading (Cont.)
Amplitude
Wave 1
1
0
−1
0
20
40
60
80
100
41
0.5
0
−0.5
0
Amplitude
Amplitude
Amplitude
Wave 2
20
40
60
Crossfade Masks
80
100
20
40
60
WaveTable Synthesis
80
100
80
100
1
0.5
0
0
1
0
−1
0
20
40
60
Note: This sort of technique is useful to create an ADSR envelope
in MATLAB
JJ
II
J
I
Back
Close
Download