Merge branch 'main' into DarellsAnnex
This commit is contained in:
commit
8b76754943
46
README.md
46
README.md
@ -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
|
||||||
fuction x = envelope(input, fs, period, attack , decay, sustain, release)
|
```
|
||||||
|
function x = generate_WAVENAME(amplitude, frequency, phase, fs, duration, duty)
|
||||||
|
% GENERATE_WAVENAME: returns a matrix of sampled WAVENAME wave
|
||||||
|
|
||||||
|
% 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
BIN
src/.DS_Store
vendored
Binary file not shown.
@ -39,5 +39,4 @@ release = 0.1;
|
|||||||
x = DarellAmplitudeEnvelope(x, fs, attack,decay,sustain,release); %output new sound in time domain
|
x = DarellAmplitudeEnvelope(x, fs, attack,decay,sustain,release); %output new sound in time domain
|
||||||
%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
34
src/add_sine.m
Normal 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
8
src/amplify.m
Normal 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
23
src/amplifyFreqRange.m
Normal 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
40
src/generate_sawtooth.m
Normal 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
|
@ -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
|
||||||
%phase shift is in number of periods
|
|
||||||
x = zeros(1, fs * duration);
|
% CONTRIBUTORS:
|
||||||
A = amplitude;
|
% Arthur Lu: Original author
|
||||||
f = frequency;
|
% Benjamin Liou: refactoring and annotations
|
||||||
p = phase;
|
|
||||||
n = fs * duration;
|
% DOCUMENTATION:
|
||||||
dt = 1 / fs;
|
% phase shift is in number of periods
|
||||||
|
% fs is the sampling frequency: how many sample points per second
|
||||||
|
% duration is time in seconds
|
||||||
|
% duty does not apply for sinusoids
|
||||||
|
|
||||||
|
|
||||||
|
% 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
|
||||||
|
|
||||||
|
@ -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
|
||||||
%phase shift is in number of periods
|
|
||||||
x = zeros(1, fs * duration);
|
% CONTRIBUTORS:
|
||||||
A = amplitude;
|
% Arthur Lu: Original author
|
||||||
f = frequency;
|
% Benjamin Liou: refactoring and annotations
|
||||||
p = phase;
|
|
||||||
n = fs * duration;
|
% DOCUMENTATION:
|
||||||
dt = 1 / fs;
|
% 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 1.
|
||||||
|
% duty of 0 or less would return -amplitude for all sample points
|
||||||
|
% duty of 0.25 would return +amplitude for first quarter of each cycle
|
||||||
|
% 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
|
||||||
|
@ -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
|
||||||
%phase shift is in number of periods
|
|
||||||
x = zeros(1, fs * duration);
|
% CONTRIBUTORS:
|
||||||
A = amplitude;
|
% Arthur Lu: Original author
|
||||||
f = frequency;
|
% Benjamin Liou: refactoring and annotations
|
||||||
p = phase;
|
|
||||||
n = fs * duration;
|
% DOCUMENTATION:
|
||||||
dt = 1 / fs;
|
% 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 1.
|
||||||
|
% duty of 0.25 would have positive slope for first quarter of each cycle
|
||||||
|
% then have negative slope for the remaining three-fourths
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% 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
13
src/generate_white.m
Normal 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
29
src/lfo_sine.m
Normal 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
6
src/reverse.m
Normal 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
|
Reference in New Issue
Block a user