Merge branch 'main' into DarellsAnnex

This commit is contained in:
darrll27 2021-12-06 15:26:58 -08:00 committed by GitHub
commit 8b76754943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 287 additions and 39 deletions

View File

@ -2,18 +2,56 @@
Audio synthesizer project created by ECE 45 students, written using the MATLAB language and MATLAB GUI Audio synthesizer project created by ECE 45 students, written using the MATLAB language and MATLAB GUI
## Contributors
Will add member names shortly Will add member names shortly
## Function Prototypes ## Function Prototypes
Templates to create your own functions.
function x = generate_wave(amplitude, frequency, phase, fs, duration, duty) ### Wave generating function
```
function x = generate_WAVENAME(amplitude, frequency, phase, fs, duration, duty)
% GENERATE_WAVENAME: returns a matrix of sampled WAVENAME wave
fuction x = envelope(input, fs, period, attack , decay, sustain, release) % CONTRIBUTORS:
% Person1: how you contributed
% Person2: how you contributed
% etc
% 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 is a number between 0 and 1
% 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
YOUR CODE HERE
end
end
```
NOTE: duty does not apply to some functions (such as sinusoids)
### Envelope function
```
function x = envelope(input, fs, period, attack , decay, sustain, release)
```
where attack, decay, release are percentages between 0 to 1 of the period where attack, decay, release are percentages between 0 to 1 of the period
sustain is the percentage of the amplitude it should sustain for sustain is the percentage of the amplitude it should sustain for
**envelope can be pitch or amplitude envelope** **envelope can be pitch or amplitude envelope**
### Filter function
```
function output_timedomain = Filter(input_soundin_timedomain, Fs, LOW, MED, HIGH) function output_timedomain = Filter(input_soundin_timedomain, Fs, LOW, MED, HIGH)
```
where LOW, MED, HIGH are user-selected variables of any value. where LOW, MED, HIGH are user-selected variables of any value.
**output should be in time domain for all functions (new sound)** **output should be in time domain for all functions (new sound)**

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@ -40,4 +40,3 @@ x = DarellAmplitudeEnvelope(x, fs, attack,decay,sustain,release); %output new so
%play over 5 counts, should only hear 200hz %play over 5 counts, should only hear 200hz
playtime = 5; playtime = 5;
play_continuous(x, fs, playtime) play_continuous(x, fs, playtime)

34
src/add_sine.m Normal file
View File

@ -0,0 +1,34 @@
function x = add_sine(amplitude, fundamental, harmonics, fs, duration)
% ADD_SINE: Additive sine wave synthesis
%CONTRIBUTORS:
%Benjamin Liou: Original author
% DOCUMENTATION:
% harmonics should ideally be a 1D matrix of:
% overtones: positive integers
% undertones: 1/ positive integers
% example: [1/2, 1, 2, 3]
% NOTE: pitch of the fundamental frequency will still be perceived even
% when the fundamental itself is missing. ex. [4,5,6]
% NOTE: it seems like when MATLAB's built in sound() takes in values,
% magnitudes over 1 get distorted.
% initialize local variables from input arguments
n = fs * duration; % number of samples (length of matrix)
% initialize a one dimensional zero matrix to be populated
x = zeros(1, n);
% populate matrix by adding sine waves
for harmonic = harmonics
x = x + generate_sine(1, fundamental * harmonic, 0, fs, duration);
end
% scale to amplitude
scalar = max(abs(x));
x = x / scalar * amplitude;
end

8
src/amplify.m Normal file
View File

@ -0,0 +1,8 @@
function output = amplify(input, multiplier)
%input: a 1D array representing the sound signal in the time domain
%multiplier: a scalar that multiplier all values in the input array to
% amplify or decrease the volume.
%Returns: input signal scaled by the multiplier in the time domain.
%Author: Conner Hsu
output = input*multiplier;
end

23
src/amplifyFreqRange.m Normal file
View File

@ -0,0 +1,23 @@
function output = amplifyFreqRange(input, fs, low, high, multiplier)
%Amplifies frequencies within a specified range, leaves all other
%frequencies the same.
%By Conner Hsu
%input: 1D array representing the sound signal in the time domain
%fs: sampling frequency
%low: a scalar representing the lower bound of frequencies to be amplified
%high: a scalar representing the upper bound of frequencies to be amplified
%multiplier: a scalar that multiplies frequencies between low and high
%Returns modified signal in the time domain.
len = length(input);
f = fs*(-len/2:len/2-1)/len;
outputW = fftshift(fft(input));
for i = 1:length(outputW)
if (low < abs(f(i)) && abs(f(i)) < high)
outputW(i) = outputW(i)*multiplier;
end
end
output = real(ifft(fftshift(outputW)));
end

40
src/generate_sawtooth.m Normal file
View File

@ -0,0 +1,40 @@
function x = generate_sawtooth(amplitude, frequency, phase, fs, duration, duty)
% generate_sawtooth: returns a matrix of sampled sawtooth wave
% CONTRIBUTORS:
% Ben Zhang: Function author
% 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 is a number between 0 and 1
%duty does not apply for sawtooth wave
% 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
period = 1 / frequency; % period of the wave
% initialize a one dimensional zero matrix to be populated
x = zeros(1, n);
% populate the matrix
for i = 1:n
t = i * dt; % time of the i'th sample
st = mod(frequency * t - phase, 1); % Progression through cycle
slope = 2 * amplitude / period; % the incline slope from start to amplitude
mid = period / 2;
%part before the straght vertical line
if(st < mid)
x(i) = slope * st; % amplitude from start to +amplitude
%part after the straght vertical line
else
x(i) = slope * (st - 0.5) - amplitude; %amplitude from -amplitude to start
end
end

View File

@ -1,15 +1,28 @@
function x = generate_sine(amplitude, frequency, phase, fs, duration, duty) function x = generate_sine(amplitude, frequency, phase, fs, duration, duty)
%GENERATE_SINE:Arthur Lu returns a matrix of sampled sine wave, where the % GENERATE_SINE: returns a matrix of sampled sine wave
% CONTRIBUTORS:
% Arthur Lu: Original author
% Benjamin Liou: refactoring and annotations
% DOCUMENTATION:
% phase shift is in number of periods % phase shift is in number of periods
x = zeros(1, fs * duration); % fs is the sampling frequency: how many sample points per second
A = amplitude; % duration is time in seconds
f = frequency; % duty does not apply for sinusoids
p = phase;
n = fs * duration;
dt = 1 / fs; % 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 for i = 1:n
t = i * dt; t = i * dt; % time at the i'th sample
x(i) = A * sin(2 * pi * f * t - p); x(i) = amplitude * sin(2 * pi * frequency * t - phase);
end end
end end

View File

@ -1,19 +1,40 @@
function x = generate_square(amplitude, frequency, phase, fs, duration, duty) function x = generate_square(amplitude, frequency, phase, fs, duration, duty)
%GENERATE_SINE:Arthur Lu returns a matrix of sampled sine wave, where the % GENERATE_SQUARE: returns a matrix of sampled square wave
% CONTRIBUTORS:
% Arthur Lu: Original author
% Benjamin Liou: refactoring and annotations
% DOCUMENTATION:
% phase shift is in number of periods % phase shift is in number of periods
x = zeros(1, fs * duration); % fs is the sampling frequency: how many sample points per second
A = amplitude; % duration is time in seconds
f = frequency; % duty cycle should be a number between 0 and 1.
p = phase; % duty of 0 or less would return -amplitude for all sample points
n = fs * duration; % duty of 0.25 would return +amplitude for first quarter of each cycle
dt = 1 / fs; % then return -amplitude for the remaining three-fourths
% duty of 1 would return all +amplitude
% 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 for i = 1:n
t = i * dt; t = i * dt; % time at the i'th sample
st = mod(f * t - p, 1);
% periodic ramp from 0 to 1
% progression through a cycle
st = mod(frequency * t - phase, 1);
if(st < duty) if(st < duty)
x(i) = A; x(i) = amplitude;
else else
x(i) = -A; x(i) = -amplitude;
end end
end end
end end

View File

@ -1,19 +1,43 @@
function x = generate_triangle(amplitude, frequency, phase, fs, duration, duty) function x = generate_triangle(amplitude, frequency, phase, fs, duration, duty)
%GENERATE_SINE:Arthur Lu returns a matrix of sampled sine wave, where the % GENERATE_TRIANGLE: returns a matrix of sampled square wave
% CONTRIBUTORS:
% Arthur Lu: Original author
% Benjamin Liou: refactoring and annotations
% DOCUMENTATION:
% phase shift is in number of periods % phase shift is in number of periods
x = zeros(1, fs * duration); % fs is the sampling frequency: how many sample points per second
A = amplitude; % duration is time in seconds
f = frequency; % duty cycle should be a number between 0 and 1.
p = phase; % duty of 0.25 would have positive slope for first quarter of each cycle
n = fs * duration; % then have negative slope for the remaining three-fourths
dt = 1 / fs;
% 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 for i = 1:n
t = i * dt; t = i * dt;
st = mod(f * t - p, 1);
% periodic ramp from 0 to 1
% progression through a cycle
st = mod(frequency * t - phase, 1);
if(st < duty) if(st < duty)
x(i) = A*(1/duty * st - 0.5); slope = amplitude / duty;
intercept = -0.5 * amplitude;
x(i) = slope * st + intercept;
else else
x(i) = A*(-(1/(1-duty))*st + (duty/(1-duty)) + 1 - 0.5); slope = -amplitude / (1 - duty);
intercept = amplitude*( duty/(1-duty) + 0.5);
x(i) = slope * st + intercept;
end end
end end
end end

13
src/generate_white.m Normal file
View File

@ -0,0 +1,13 @@
function x = generate_white(amplitude, fs, duration)
%GENERATE_WHITE: returns a matrix of sampled white noise
%CONTRIBUTORS:
%Benjamin Liou: Original author
%DOCUMENTATION:
% white noise can then be filtered to produce different hues of noises
%time domain matrix of random sample points between +-amplitude
x = amplitude * 2 * (rand(1, fs * duration) - 0.5);
end

29
src/lfo_sine.m Normal file
View File

@ -0,0 +1,29 @@
function x = lfo_sine(amplitude, frequency, phase, fs, duration, input)
% LFO_SINE: modulates an input matrix
% CONTRIBUTORS:
% Benjamin Liou: Original author
% DOCUMENTATION:
% frequency is typically below 20Hz (according to wikipedia)
% fs and duration should be same as input
% 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 lfo, which will be used to modulate the input
lfo = zeros(1, n);
% populate lfo matrix
for i = 1:n
t = i * dt; % time at the i'th sample
lfo(i) = amplitude * sin(2 * pi * frequency * t - phase);
end
% modulate input
x = lfo .* input;
end

6
src/reverse.m Normal file
View File

@ -0,0 +1,6 @@
function output = reverse(input)
%input: a 1D array representing the sound signal in the time domain
%returns: the input signal with its elements in reverse order.
%By Conner Hsu
output = flip(input);
end