-
Notifications
You must be signed in to change notification settings - Fork 0
/
pitch_shifter.m
169 lines (130 loc) · 3.99 KB
/
pitch_shifter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
% ------------- SETUP ------------- %
% Circular buffer length
l = 1024;
% Shifting factor
% 0.8 for low pitch
% 1 for normal voice
% 1.65 for high pitch
shift_factor = 0.8;
% Read .wav file
% Test audio file is a recitation of The Gettysburg Address
filename = 'gettysburg.wav';
% [samples,fs] = audioread(filename);
% Test sine wave to better visualize effect of shifting & filtering
fs = 45000;
x = linspace(0,1,fs);
samples = sin(2*pi*440*x);
% ------------- BUFFERS AND POINTERS ------------- %
% Create 2 buffers for left data, and two buffers for right data
% Initialize buffers to zero
l_buf_0 = zeros(1, l);
l_buf_1 = zeros(1, l);
r_buf_0 = zeros(1, l);
r_buf_1 = zeros(1, l);
% Output array of shifted samples
% In hardware implementation, samples will be streamed to Avalon bus
% Output
out_left = zeros(length(samples),1);
out_right = zeros(length(samples),1);
% Read and write pointers for l_buf_0, l_buf_1, r_buf_0, and r_buf_1
% Initialize w_0 to 1. MATLAB arrays start at 1.
% Initialize w_1 to 180 deg shifted cell.
% l_buf write
l_w_0 = 1;
l_w_1 = floor(l/2);
% l_buf read
l_r_0 = 1;
l_r_1 = 1;
% r_buf write
r_w_0 = 1;
r_w_1 = floor(l/2);
% r_buf read
r_r_0 = 1;
r_r_1 = 1;
% Indexing for read pointers
l_i_0= 0;
l_i_1= 0;
r_i_0= 0;
r_i_1= 0;
% ------------- ALGORITHM ------------- %
% Read one sample at a time from the array of samples
% Simulate reading one sample from a register in hardware
for i=1:length(samples)
% LEFT BUFFER
% Add the sample to l_buf_1 at address l_w_1
% Advance l_w_1
l_buf_0(l_w_0) = samples(i);
l_w_0 = mod(i, l) + 1;
% Add the sample to l_buf_2
% Advance l_w_2
l_buf_1(l_w_1) = samples(i);
l_w_1 = mod(i+floor(l/2), l) + 1;
% Read from l_buf_1 at address l_r_1
l_i_0= l_i_0 + shift_factor;
l_r_0 = mod(floor(l_i_0), l) + 1;
% Read from l_buf_2 at address l_r_2
l_i_1= l_i_1 + shift_factor;
l_r_1 = mod(floor(l_i_1), l) + 1;
% RIGHT BUFFER
% Add the sample to r_buf_0 at address r_w_0
% Advance l=r_w_0
r_buf_0(r_w_0) = samples(i);
r_w_0 = mod(i, l) + 1;
% Add the sample to r_buf_1
% Advance r_w_1
r_buf_1(r_w_1) = samples(i);
r_w_1 = mod(i + floor(l/2), l) + 1;
% Read from r_buf_0 at address r_r_0
r_i_0= r_i_0 + shift_factor;
r_r_0 = mod(floor(r_i_0), l) + 1;
% Read from l_buf_1 at address l_r_1
r_i_1= r_i_1 + shift_factor;
r_r_1 = mod(floor(r_i_1), l) + 1;
out_left(i) = 0.5*(l_buf_0(l_r_0) + l_buf_1(l_r_1));
out_right(i) = 0.5*(r_buf_0(r_r_0) + r_buf_1(r_r_1));
end
% ------------- WAVEFORM VIZUALIZATION & SOUND------------- %
% Listen to the original audio
% sound(out_left, fs);
% ------------- VISUALIZE PITCH-SHIFT ------------- %
% Filter only in the human voice range using 4th order Butterworth filter
fc = 3500;
[b,a] = butter(4, fc/(fs/2));
out_filtered = filter(b, a, out_left);
% Plot the original audio waveform
figure
plot(samples, 'LineWidth', 1, 'Color', '#0b2852');
hold on;
% Plot the time-shifted, filtered audio waveform
plot(out_filtered, 'LineWidth', 1, 'Color', '#629df5')
% Style plot
[t,s] = title("Pitch-shifting", 'Shift-factor = 0.8 (low-pitch)');
grid;
t.FontSize = 16;
s.FontAngle = 'italic';
lgd = legend('Original audio','Pitch-shifted audio');
lgd.FontSize = 14;
% Visualize a given domain of the sine wave
xlim([1000, 1500]);
ylim([-1.15, 1.15]);
% Listen to the pitch-shifted audio
% sound(out_filtered, fs);
% ------------- VISUALIZE FILTERING ------------- %
% Plot the pitch-shifted, unfiltered audio waveform
figure
plot(out_left, 'LineWidth', 1, 'Color', '#0b2852');
hold on;
% Plot the time-shifted, filtered audio waveform
plot(out_filtered, 'LineWidth', 1, 'Color', '#629df5')
% Style plot
[t,s] = title("Filtering", 'Butterworth Filter 3.5 kHz');
grid;
t.FontSize = 16;
s.FontAngle = 'italic';
lgd = legend('Unfilted output','Filtered output');
lgd.FontSize = 14;
% Visualize a given domain of the sine wave
xlim([1000, 1100]);
ylim([-1.15, 1.15]);
% Listen to the pitch-shifted audio
sound(out_filtered, fs);