-
Notifications
You must be signed in to change notification settings - Fork 0
/
vocalSynth.m
158 lines (125 loc) · 4.39 KB
/
vocalSynth.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
function vocalSynth()
%--------------------------------------------------------------------------
% Control FM Synthesizer with Sound
%--------------------------------------------------------------------------
% DESCRIPTION:
% Detect RMS & Pitch of the input audio to control syth parameters:
% RMS --> Carrier amplitude, modulator amplitude, modulator frequency
% Pitch --> Carrier Frequency, modulator frequency
% CKChen 2021, NYU
clc
clear
close all
clear sound
%--------------------------------------------------------------------------
% Set Audio I/O
%--------------------------------------------------------------------------
% !! Please Set audio device in line 29 to the correct one currently using
% if the default option does not work.
deviceReader = audioDeviceReader;
deviceWriter = audioDeviceWriter;
fs = deviceReader.SampleRate;
bufferSz = deviceReader.SamplesPerFrame;
%devices = getAudioDevices(deviceWriter);
%devices;
%deviceReader.Device = " (2- CalDigit Thunderbolt 3 Audio)";
deviceReader.Device = "Default";
deviceWriter.SampleRate = fs;
% GUI
fig = [];
btn = [];
plotRMS = [];
textPitch = [];
plotProcessed = [];
audioRMS = [];
audioPE = [];
createGUI()
%--------------------------------------------------------------------------
% Functions
%--------------------------------------------------------------------------
function createGUI()
fig = figure('Name','Voice Controlled FM Synthesizer',...
'Position',[500 200 1080 720]);
btn = uicontrol('String','Start',...
'Style','togglebutton',...
'Callback',@startAudio,...
'Position',[360 20 360 20]);
subplot(2,1,1);
plotRMS = plot(zeros(1,bufferSz),'r');
xlim([0 bufferSz]); ylim([-1 1]);
ylabel('RMS');
title('RMS & Pitch Analysis');
textPitch = text(540,0,'- Hz',...
'HorizontalAlignment','center',...
'VerticalAlignment','middle',...
'FontSize',50,...
'Color','k');
subplot(2,1,2);
plotProcessed = plot(zeros(1,bufferSz),'b');
xlim([0 bufferSz]); ylim([-1 1]);
ylabel('Magnitude');
title('FM Synthesis');
end
function startAudio(h,~)
btn.String = 'Stop';
while true
try
audioIn = deviceReader();
audioProcessed = processing(audioIn);
if ~btn.Value
break;
end
plotRMS.YData = audioRMS;
textPitch.String = [sprintf('%.2f',audioPE),' Hz'];
plotProcessed.YData = audioProcessed;
deviceWriter(audioProcessed);
drawnow
catch
break;
end
end
stopAudio();
end
function stopAudio(h,~)
try
btn.Value = 0;
btn.String = 'Start';
release(deviceReader);
release(deviceWriter);
catch
end
end
function processedOutput = processing(signal)
audioRMS = movingRMS(signal);
audioPE = pitchEstimation(signal);
processedOutput = fmSynth(audioPE,audioRMS,bufferSz);
end
function rmsOutput = movingRMS(signal)
movRMS = dsp.MovingRMS;
rmsOutput = movRMS(signal);
end
function f0 = pitchEstimation(signal)
winLength = length(signal);
overlapLength = 0;
[f0,~] = pitch(signal,fs,'WindowLength',winLength,'OverlapLength',overlapLength);
end
function [fmOutput] = fmSynth(freqVector,ampVector,duration)
% Gate noise floor lower than 0.01 RMS
if ampVector < 0.01
ampVector = 0;
end
% Carrier Amplitude & Frequency
ac = mean(ampVector) * 20;
fc = freqVector;
% Modulator Amplitude & Frequency
am = ac / 20;
fm = ac * fc / (fs / 2) * 2;
y = zeros(duration,1);
for i=1:(duration-1)
y(i) = ac * cos(2 * pi * fc * i/fs + am/fm * sin(2 * pi * fm * i/fs));
end
win = hamming(duration);
y = y .* win; % Limit harsh noise created by level difference
fmOutput = y;
end
end