Merge branch 'main' of https://github.com/ltcptgeneral/ece45-project
This commit is contained in:
commit
cef36db11f
BIN
App/app.mlapp
BIN
App/app.mlapp
Binary file not shown.
14
README.md
14
README.md
@ -57,10 +57,10 @@ where LOW, MED, HIGH are user-selected variables of any value.
|
|||||||
|
|
||||||
## Useful websites
|
## Useful websites
|
||||||
|
|
||||||
- https://learningsynths.ableton.com
|
- [Learning Synths](https://learningsynths.ableton.com)
|
||||||
- https://learningsynths.ableton.com/en/playground
|
- [Learning Synths Playground](https://learningsynths.ableton.com/en/playground)
|
||||||
- https://blog.demofox.org/diy-synthesizer/
|
- [DIY Synthesisers](https://blog.demofox.org/diy-synthesizer/)
|
||||||
- http://portaudio.com/
|
- [Port Audio (audio I/O library)](http://portaudio.com/)
|
||||||
- https://ccrma.stanford.edu/software/stk/
|
- [Synthesis ToolKit in C++](https://ccrma.stanford.edu/software/stk/)
|
||||||
- https://cycling74.com/products/max
|
- [Max](https://cycling74.com/products/max)
|
||||||
- http://msp.ucsd.edu/software.html
|
- [Software by Miller Puckette](http://msp.ucsd.edu/software.html)
|
||||||
|
BIN
src/.DS_Store
vendored
BIN
src/.DS_Store
vendored
Binary file not shown.
@ -1,3 +1,14 @@
|
|||||||
|
%Written by Darell
|
||||||
|
%Creates a Linear Amplitude Envelope
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
% fs is the sampling frequency
|
||||||
|
% attack, decay, release are in percentages of the period
|
||||||
|
% sustain is in the percentage of amplitude
|
||||||
|
|
||||||
function output = DarellAmplitudeEnvelope(input, Fs, attack,decay,sustain,release) %percentages for attack, decay, sustain, release
|
function output = DarellAmplitudeEnvelope(input, Fs, attack,decay,sustain,release) %percentages for attack, decay, sustain, release
|
||||||
len = length(input);
|
len = length(input);
|
||||||
T = (len-1)/Fs;
|
T = (len-1)/Fs;
|
@ -1,3 +1,15 @@
|
|||||||
|
%Written by Darell
|
||||||
|
%uses fourier transform to get the series of all signals
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
% fs is the sampling frequency
|
||||||
|
% y is the signal input
|
||||||
|
% LOW and HIGH are used for the band of frequency
|
||||||
|
% MEDIUM IS NOT USED
|
||||||
|
|
||||||
function output_y = DarellbandpassFilter(y,Fs,LOW,MED,HIGH)
|
function output_y = DarellbandpassFilter(y,Fs,LOW,MED,HIGH)
|
||||||
Len = length(y);
|
Len = length(y);
|
||||||
F = Fs * (-Len/2 : (Len/2 - 1))/Len ;
|
F = Fs * (-Len/2 : (Len/2 - 1))/Len ;
|
@ -1,10 +0,0 @@
|
|||||||
function output = FilterSelect(input,Fs,LOW,MED,HIGH,number)
|
|
||||||
if(number == "Option 1")
|
|
||||||
output = DarellbandpassFilter(input,Fs,LOW,MED,HIGH);
|
|
||||||
elseif(number == "Option 2")
|
|
||||||
output = amplifyFreqRange(input, Fs, LOW, MED, HIGH);
|
|
||||||
else
|
|
||||||
output = input;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
BIN
src/Helper/.DS_Store
vendored
Normal file
BIN
src/Helper/.DS_Store
vendored
Normal file
Binary file not shown.
20
src/Helper/Equalizer_Darell.m
Normal file
20
src/Helper/Equalizer_Darell.m
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
% fs is the sampling frequency
|
||||||
|
% input is the signal input
|
||||||
|
% EQplot is the curve generated by the EQ in the app. it should look like /----\ when everthing is set to 1
|
||||||
|
|
||||||
|
|
||||||
|
function output = Equalizer_Darell(input,EQplot,Fs)
|
||||||
|
%It's an EQ written by Darell
|
||||||
|
% Split into frequencies and multiply by EQ
|
||||||
|
Mod_Freq = fftshift(fft(input));
|
||||||
|
filtered_Mod_Freq = fftshift(Mod_Freq .* EQplot);
|
||||||
|
output = real(ifft(filtered_Mod_Freq));
|
||||||
|
%plot(output);
|
||||||
|
end
|
||||||
|
|
92
src/Helper/MIDIDarell.m
Normal file
92
src/Helper/MIDIDarell.m
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
function output = MIDIDarell(dur,Fs)
|
||||||
|
%Darell Chua Yun Da
|
||||||
|
% Detailed explanation goes here
|
||||||
|
|
||||||
|
freq = [330 350 370 392 415 440 466 494 523 554];
|
||||||
|
charls = ["q" "w" "e" "r" "t" "y" "u" "i" "o" "p"];
|
||||||
|
bytedur = 0.5;
|
||||||
|
x = 0:1/Fs:bytedur;
|
||||||
|
yz0 = zeros([1,(length(x)-1)]);
|
||||||
|
y = [yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0
|
||||||
|
yz0];
|
||||||
|
|
||||||
|
for c = 1:length(freq)
|
||||||
|
for i=1:length(x)
|
||||||
|
y(c,i) = 0.5*sin(2*pi*freq(c)*x(i));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Len = dur*Fs;
|
||||||
|
output = zeros([1,Len]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(gcf,'CurrentCharacter', '@');
|
||||||
|
figure(1)
|
||||||
|
|
||||||
|
tStart = tic;
|
||||||
|
tEnd = toc(tStart);
|
||||||
|
figure(1)
|
||||||
|
|
||||||
|
while(tEnd <= dur)
|
||||||
|
title("Midi Popup")
|
||||||
|
drawnow
|
||||||
|
char = get(gcf,'CurrentCharacter');
|
||||||
|
while (char == '@' && tEnd <= dur)
|
||||||
|
figure(1)
|
||||||
|
char = get(gcf,'CurrentCharacter');
|
||||||
|
tEnd = toc(tStart);
|
||||||
|
drawnow
|
||||||
|
end
|
||||||
|
|
||||||
|
n = round((tEnd/dur)*Len);
|
||||||
|
|
||||||
|
endt = tEnd + bytedur;
|
||||||
|
overt = tEnd + bytedur/3;
|
||||||
|
if overt> dur
|
||||||
|
endt = dur;
|
||||||
|
end
|
||||||
|
if endt > dur
|
||||||
|
endt = dur;
|
||||||
|
end
|
||||||
|
endn = round(endt*Fs);
|
||||||
|
|
||||||
|
charno = 0;
|
||||||
|
for i=1:length(freq)
|
||||||
|
if char == charls(i)
|
||||||
|
charno = i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if charno > 0
|
||||||
|
sound(y(charno,:),Fs);
|
||||||
|
oldout = output(n:endn);
|
||||||
|
output(n:endn) = oldout + y(charno,1:(endn-n+1));
|
||||||
|
while(tEnd < overt)
|
||||||
|
tEnd = toc(tStart);
|
||||||
|
drawnow
|
||||||
|
end
|
||||||
|
figure(1)
|
||||||
|
plot(output);
|
||||||
|
title("Midi Popup")
|
||||||
|
drawnow
|
||||||
|
set(gcf,'CurrentCharacter', '@')
|
||||||
|
else
|
||||||
|
figure(1)
|
||||||
|
drawnow
|
||||||
|
set(gcf,'CurrentCharacter', '@')
|
||||||
|
end
|
||||||
|
tEnd = toc(tStart);
|
||||||
|
end
|
||||||
|
figure(1)
|
||||||
|
plot(output);
|
||||||
|
sound(output,Fs);
|
||||||
|
drawnow();
|
||||||
|
end
|
||||||
|
|
BIN
src/NotWorking/.DS_Store
vendored
Normal file
BIN
src/NotWorking/.DS_Store
vendored
Normal file
Binary file not shown.
103
src/PitchEnvelope/DarellAnneLinearPitchEnvelope.m
Normal file
103
src/PitchEnvelope/DarellAnneLinearPitchEnvelope.m
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
%Written by Darell and Anne
|
||||||
|
%If there is a frequency of 200Hz:
|
||||||
|
%1. it needs to ramp up a frequency from 0Hz to the 200Hz over the attack time
|
||||||
|
%2. It needs to ramp down to a set sustained frequency over the decay time e.g. 160Hz < 200Hz
|
||||||
|
%3. It maintains this 160Hz until the release time
|
||||||
|
%4. Release time: It decays from 160Hz further all the way back to 0Hz.
|
||||||
|
%This envelope uses linear calculations
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
% Person2: Anne
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
% fs is the sampling frequency
|
||||||
|
% attack, decay, release are in percentages of the period
|
||||||
|
% sustain is in the percentage of amplitude
|
||||||
|
|
||||||
|
function output = DarellAnneLinearPitchEnvelope(input, Fs, attack,decay,sustain,release) %percentages for attack, decay, sustain, release
|
||||||
|
len = length(input);
|
||||||
|
T = (len-1)/Fs;
|
||||||
|
attacktime = attack * T * Fs;
|
||||||
|
decaytime = attacktime + decay * T * Fs;
|
||||||
|
sustaintime = (T - (release * T)) * Fs;
|
||||||
|
|
||||||
|
output = zeros([1,len]);
|
||||||
|
|
||||||
|
tcounter = 1;
|
||||||
|
%attack phase
|
||||||
|
curr = attacktime;
|
||||||
|
x = 1:len;
|
||||||
|
y = x .* 0;
|
||||||
|
g = x .* 0;
|
||||||
|
while tcounter <= curr
|
||||||
|
ncount = round((tcounter^2)/(2*curr)+ curr/2);
|
||||||
|
y(tcounter) = ncount; %For Debug Purposes
|
||||||
|
output(tcounter) = input(ncount);
|
||||||
|
tcounter = tcounter+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
%decay phase
|
||||||
|
prevcur = curr;
|
||||||
|
tcounter = prevcur;
|
||||||
|
curr = decaytime;
|
||||||
|
while tcounter <= curr
|
||||||
|
|
||||||
|
t = round(tcounter-prevcur);
|
||||||
|
dur = round(curr-prevcur);
|
||||||
|
dsus = (1-sustain);
|
||||||
|
|
||||||
|
dn = (1 - (dsus)*t/(2*dur))*t;
|
||||||
|
ncount = round(prevcur + dn);
|
||||||
|
tcounter = round(tcounter);
|
||||||
|
|
||||||
|
y(tcounter) = ncount; %For Debug Purposes
|
||||||
|
output(tcounter) = input(ncount);
|
||||||
|
tcounter = tcounter+1;
|
||||||
|
end
|
||||||
|
hold on
|
||||||
|
plot(x,y)
|
||||||
|
plot(x,g)
|
||||||
|
hold off
|
||||||
|
%sustain phase
|
||||||
|
prevncount = ncount;
|
||||||
|
prevcur = curr;
|
||||||
|
tcounter = prevcur;
|
||||||
|
curr = sustaintime;
|
||||||
|
while tcounter <= curr
|
||||||
|
t = round(tcounter-prevcur);
|
||||||
|
ncount = round(sustain*(t) + prevncount);
|
||||||
|
tcounter = round(tcounter);
|
||||||
|
|
||||||
|
y(tcounter) = ncount; %For Debug Purposes
|
||||||
|
output(tcounter) = input(ncount);
|
||||||
|
tcounter = tcounter+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
%release phase
|
||||||
|
prevncount = ncount;
|
||||||
|
prevcur = curr;
|
||||||
|
tcounter = prevcur;
|
||||||
|
curr = Fs;
|
||||||
|
while tcounter <= curr
|
||||||
|
t = round(tcounter-prevcur);
|
||||||
|
dur = round(curr-prevcur);
|
||||||
|
|
||||||
|
dn = (sustain - (sustain)*t/(2*dur))*t;
|
||||||
|
ncount = round(prevncount + dn);
|
||||||
|
|
||||||
|
%ncount = round(prevncount + ((curr-prevcur)*(tcounter-prevcur)/(curr))*(1-log(tcounter+1-prevcur)/log(curr-prevcur)));
|
||||||
|
|
||||||
|
%ncount = round(curr*(1-log(tcounter)/log(prevcur)) + prevncount);
|
||||||
|
|
||||||
|
tcounter = round(tcounter);
|
||||||
|
y(tcounter) = ncount; %For Debug Purposes
|
||||||
|
if ncount > len
|
||||||
|
output(tcounter) = 0;
|
||||||
|
else
|
||||||
|
output(tcounter) = input(ncount);
|
||||||
|
end
|
||||||
|
tcounter = tcounter+1;
|
||||||
|
end
|
||||||
|
plot(x,y) %For Debug Purposes
|
||||||
|
end
|
@ -4,6 +4,7 @@
|
|||||||
%2. It needs to ramp down to a set sustained frequency over the decay time e.g. 160Hz < 200Hz
|
%2. It needs to ramp down to a set sustained frequency over the decay time e.g. 160Hz < 200Hz
|
||||||
%3. It maintains this 160Hz until the release time
|
%3. It maintains this 160Hz until the release time
|
||||||
%4. Release time: It decays from 160Hz further all the way back to 0Hz.
|
%4. Release time: It decays from 160Hz further all the way back to 0Hz.
|
||||||
|
%This envelope uses logarithmic calculations
|
||||||
|
|
||||||
% CONTRIBUTORS:
|
% CONTRIBUTORS:
|
||||||
% Person1: Darell
|
% Person1: Darell
|
@ -1,3 +1,11 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
function output = AmpEnvelopeSelect(input, Fs, attack,decay,sustain,release,number)
|
function output = AmpEnvelopeSelect(input, Fs, attack,decay,sustain,release,number)
|
||||||
if(number == "Option 1")
|
if(number == "Option 1")
|
||||||
output = DarellAmplitudeEnvelope(input, Fs, attack,decay,sustain,release);
|
output = DarellAmplitudeEnvelope(input, Fs, attack,decay,sustain,release);
|
26
src/Select/FilterSelect.m
Normal file
26
src/Select/FilterSelect.m
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
|
function output = FilterSelect(input,Fs,LOW,MED,HIGH,number)
|
||||||
|
if(number == "Option 1")
|
||||||
|
output = DarellbandpassFilter(input,Fs,LOW,MED,HIGH);
|
||||||
|
elseif(number == "Option 2")
|
||||||
|
output = amplifyFreqRange(input, Fs, LOW, MED, HIGH);
|
||||||
|
elseif(number == "Option 3")
|
||||||
|
output = epic_effect_schluep(input, Fs, LOW, MED, HIGH);
|
||||||
|
elseif(number == "Option 4")
|
||||||
|
output = muffled_effect_schluep(input, Fs, LOW, MED, HIGH);
|
||||||
|
elseif(number == "Option 5")
|
||||||
|
output = seperate_prevalent_schluep(input, Fs, LOW, MED, HIGH);
|
||||||
|
elseif(number == "Option 6")
|
||||||
|
output = bandreject_filter(input, Fs, LOW, HIGH);
|
||||||
|
else
|
||||||
|
output = input;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
20
src/Select/LFOSelect.m
Normal file
20
src/Select/LFOSelect.m
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
|
function output = LFOSelect(amplitude, frequency, phase, fs, duration, input,number)
|
||||||
|
%UNTITLED Summary of this function goes here
|
||||||
|
% Detailed explanation goes here
|
||||||
|
if(number == "Option 1")
|
||||||
|
output = lfo_sawtooth(amplitude, frequency, phase, fs, duration, input);
|
||||||
|
elseif(number == "Option 2")
|
||||||
|
output = lfo_sine(amplitude, frequency, phase, fs, duration, input);
|
||||||
|
else
|
||||||
|
output = input;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
19
src/Select/OffsetSelect.m
Normal file
19
src/Select/OffsetSelect.m
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
|
function output = OffsetSelect(input,value,number)
|
||||||
|
if(number == "Option 1")
|
||||||
|
output = Meghaj_Echo(input, value);
|
||||||
|
elseif(number == "Option 2")
|
||||||
|
output = Petha_Hsu_PitchOffset(input, value);
|
||||||
|
else
|
||||||
|
output = input;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
@ -1,6 +1,16 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
function output = PitchEnvelopeSelect(input, Fs, attack,decay,sustain,release,number)
|
function output = PitchEnvelopeSelect(input, Fs, attack,decay,sustain,release,number)
|
||||||
if(number == "Option 1")
|
if(number == "Option 1")
|
||||||
output = DarellAnnePitchEnvelope(input, Fs, attack,decay,sustain,release);
|
output = DarellAnnePitchEnvelope(input, Fs, attack,decay,sustain,release);
|
||||||
|
elseif(number == "Option 2")
|
||||||
|
output = DarellAnneLinearPitchEnvelope(input, Fs, attack,decay,sustain,release);
|
||||||
else
|
else
|
||||||
output = input;
|
output = input;
|
||||||
end
|
end
|
@ -1,3 +1,11 @@
|
|||||||
|
%Written by Darell
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Person1: Darell
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
%Pass-through function used by app
|
||||||
|
|
||||||
function output = SoundGeneratorSelect(amplitude, frequency, phase, fs, duration, duty,number)
|
function output = SoundGeneratorSelect(amplitude, frequency, phase, fs, duration, duty,number)
|
||||||
if(number == "Option 1")
|
if(number == "Option 1")
|
||||||
output = generate_sine(amplitude, frequency, phase, fs, duration, duty);
|
output = generate_sine(amplitude, frequency, phase, fs, duration, duty);
|
||||||
@ -8,7 +16,9 @@ function output = SoundGeneratorSelect(amplitude, frequency, phase, fs, duration
|
|||||||
elseif(number == "Option 4")
|
elseif(number == "Option 4")
|
||||||
output = generate_sawtooth(amplitude, frequency, phase, fs, duration, duty);
|
output = generate_sawtooth(amplitude, frequency, phase, fs, duration, duty);
|
||||||
elseif(number == "Option 5")
|
elseif(number == "Option 5")
|
||||||
output = generate_white(amplitude, frequency, phase, fs, duration, duty);
|
output = generate_white(amplitude, fs, duration);
|
||||||
|
elseif(number == "Option 6")
|
||||||
|
output = generate_halfCircles(amplitude, frequency, phase, fs, duration, duty);
|
||||||
else
|
else
|
||||||
output = 0;
|
output = 0;
|
||||||
end
|
end
|
46
src/generate_heartbeat.m
Normal file
46
src/generate_heartbeat.m
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
function x = generate_heartbeat(amplitude, frequency, phase, fs, duration, duty)
|
||||||
|
% GENERATE_SINE: returns a matrix of sampled heart monitor wave
|
||||||
|
|
||||||
|
% CONTRIBUTORS:
|
||||||
|
% Alex Nguyen: Original Author
|
||||||
|
% Conner Hsu: Reviewed Code and Assisted in polishing
|
||||||
|
|
||||||
|
% DOCUMENTATION:
|
||||||
|
% phase shift is in number of periods
|
||||||
|
% fs is the sampling frequency: how many sample points per second
|
||||||
|
% duration is time in seconds
|
||||||
|
% duty cycle should be a number between 0 and 0.5.
|
||||||
|
% duty of 0 or less would return 0 for all sample points
|
||||||
|
% duty of 0.5 or less would return a heartbeat signal since there would be
|
||||||
|
% equal amount of space within 1 period to have the right and left sides be equal
|
||||||
|
% duty of greater than 0.5 but less than 1 would return a slope starting at that duty i.e.
|
||||||
|
% the left side but leaving little room to the right side
|
||||||
|
% duty of between 1 and 2 would give a sawtooth wave in the +amplitude.
|
||||||
|
% duty greater than 2 would return 0 for all sample points
|
||||||
|
|
||||||
|
|
||||||
|
% initialize local variables from input arguments
|
||||||
|
n = fs * duration; % number of samples (length of matrix)
|
||||||
|
dt = 1 / fs; % sampling period: time between two sample points
|
||||||
|
|
||||||
|
|
||||||
|
% initialize a one dimensional zero matrix to be populated
|
||||||
|
x = zeros(1, n);
|
||||||
|
|
||||||
|
% populate the matrix
|
||||||
|
for i = 1:n
|
||||||
|
t = i * dt; % time at the i'th sample
|
||||||
|
st = mod(frequency * t - phase, 1);
|
||||||
|
|
||||||
|
if (duty-(duty / 2) < st && st < duty)
|
||||||
|
slope = amplitude / duty;
|
||||||
|
intercept = -0.5 * amplitude;
|
||||||
|
x(i) = slope * st + intercept;
|
||||||
|
elseif (duty < st && st < duty+(duty / 2))
|
||||||
|
slope = amplitude / duty;
|
||||||
|
intercept = -amplitude;
|
||||||
|
x(i) = slope * st + (1.5 * intercept);
|
||||||
|
else
|
||||||
|
x(i) = 0;
|
||||||
|
end
|
||||||
|
end
|
Reference in New Issue
Block a user