MATLAB files: proj1.m, oct.m
(paste both in work directory and run proj1)

Abstract

In this project I used MATLAB to generate discrete sinusoids
of one octave of musical notes using the sampling frequency of my choice.I then played back the octave at
different multiples of the sampling frequency and observed the change in
pitch.I continued by adding
commands to control note duration and produce octave shifts without changing
the sampling or reconstruction frequency.Lastly, overtones were added to each note, which I used
to play back a short piece of music.

MATLAB Code With
Commentary

Setting
the Sampling and Reconstruction Frequency

Fs1 = 44100; %Set
Sampling Frequency

Fr = Fs1; %Set
Reconstruction Frequency

Fs = Fs1; % The
multiple of the sampling frequency to be used

T = 1/Fs; %Sampling
Period

First, I chose Fs1 to be 44,100 Hz, which is the default
sampling rate for most computer audio cards when recording music or sound
samples.I also chose to hold the
reconstruction frequency, Fr, constant at Fs1 and use Fs as the sampling
frequency that I modify to produce changes in the sound.Fs = Fs1 by default so there is no
change in the sound.If we set Fs
= 2*Fs1 the pitch will go down an octave (cut frequency in half), and if we set
Fs = 0.5*Fs1 the pitch will go up an octave (double the frequency).

The N variable is multiplied by a number in order to produce
notes of a reasonable length in time when output to speakers.By modifying the multiplier one can
effectively change the tempo of the output notes.The array, n, is a function that takes the argument, L,
which scales the length of the array to result in longer or shorter note
duration.L is set to 1 by default
so that there is no duration change.

Generation
of Sinusoids

%Generate
General Sinusoid

%m is
the desired octave, which is transformed into the appropriate multiplier by
the oct function

To
generate the standard sinusoid I started from a standard continuous time signal,
sin(2¹f), and converted it to discrete time using f = nT.I then added an octave shift function
to downsample or upsample respectively.Notice that the note function takes a third argument, fN, that will
determine which musical note is generated by the sinusoid.We see that the sinusoid is construced
as in the following pseudocode:

The
oct and n functions become very useful when creating music because the composer
can change the octave and duration of each note on the spot without having to
create all 88 notes of the standard musical keyboard.Thus, digital keyboards would only need to store 12 sound
samples of each preset in their memory to be able to play all 88 notes.

Setting the Octave

m = 0; %default
input for oct, the octave shift function

%%%%%%%%%%%%
begin oct.m%%%%%%%%%%%%

function y = oct(m)

if m >= 0

y = 2^m;

end

if m < 0

y = 1/2^(-m);

end

%%%%%%%%end
of oct.m%%%%%%%%%%%%%%%%

The
variable m is the desired octave and input for the oct function which generates
the appropriate multiplier to change the octave of a note by downsampling or
upsampling.We see that the note
will be downsampled if the desired octave is greater than or equal to zero and
upsampled if the desired octave is less than zero.So, to move up one octave we enter 1 for m, which is
translated into a 2 by the oct function.To move down one octave we enter -1, which is then translated into 0.5.

The following command plots a middle A note (440Hz)

plot(n(0.04),
A(0, 0.04));

Result: The Note A at 440Hz

The following command plots an A note (440Hz) shifted up
one octave

plot(n(0.04),
A(1, 0.04));

Result: The Note A
at 880Hz

Figure 2.Visual Representation of an Octave Shift Using Downsampling

By
moving up one octave using downsampling we see twice as many cycles of the A
waveform within the same number of samples, which tells us that the output
frequency has doubled to 880 Hz.Notice that downsampling has the same effect on the note as changing the
sampling frequency.Hence, the
advantage of downsampling is that it lets us modify pitch without changing the
sampling or reconstruction frequency.

To
produce a more natural sound I added two overtones to each note.Each note is a sum of three instances
of the general sinusoid defined earlier.The first instance is the note played at its standard frequency in the
desired octave input by the user.The last two instances are the note played at one octave below and one
octave above the input octave.Each
instance is multiplied by either namp to set the amplitude of the natural
frequency or hamp, which sets the amplitude of the harmonic frequencies.By modifying the values of namp and
hamp one can create different mixtures of natural frequencies and overtones,
which is similar to what happens when you pluck a string or create a note
through physical vibration.Thus,
by adding even more overtones and properly tweaking the mixture it becomes
possible to model physical instruments in the digital domain.

The following command plots the middle A note (440Hz) with
no overtones.

hamp = 0;

plot(n(0.04),
A(0, 0.04));

Result:
Simple Sinusoid with a period of 100 samples

The following command plots the middle A note (440Hz) with
two overtones.

hamp = 0.8;

plot(n(0.04),
A(0, 0.04));

Result: A more complex periodic function with a period of
200 samples

Figure 3.Visual Representaion of Overtones in a Note

We see that when harmonics are added the period of the tone
changes to the largest period of its harmonics.

sound(0.25*jbells,
Fr); % the multiplier in front of song sets the master volume

If four C quarter notes are to be played in a bar of music a
pianist knows to press the C key four times equally spaced to create the
appropriate rhythm. However, if MATLAB sees four C quarter notes it will play
them as one continuous note rather than four equally spaces notes.Thus, a quarter rest in my code does
not directly correspond to a quarter rest in actual music.My quarter rest, qr, is used as the
default spacing between notes in order to give rhythm to the song.If an actual quarter rest is required
in the music then I would use a whole rest, which is the same length as a quarter
note, N.If a true whole rest was
required then I would simply use four whole rests.This problem can be fixed by adding a release property to
the notes along with the attack, decay, and sustain properties found on most
synthesizers.

To simplify the composition process I divided the song into several
sequences so I could play them back one at a time until they were ready to be
added together in the song vector, jbells.Also, several of the sequences repeated in the song, which
significantly reduced the amount of notes for me to input.

Lastly, the song is output at Fr using the sound command and
a multiplier in front of the song vector in order to control the volume level.

(While Jingle Bells does not include several instances of
octaves other than 0, I have also prepared a vector that plays all notes from
C(-2) to B(2) for demonstration purposes.)

CONCLUSION

This project was an interesting first step into the musical
capacity of MATLAB.I believe that
would be very possible to model an instrument or create a synthesizer with
MATLAB.Adding envelopes, filters,
and a step sequencer could make for a decent digital music production
tool.Several music languages such
as Csound already exist, but do not require as deep an understanding of
mathematics and programming methods.Thus, further exploration of music in MATLAB could produce ways for
musicians to obtain signal processing and programming skills, while engineers
and programmers could use their technical skills to better understand
music.

(Equally plausible may the capacity of LabVIEW for music,
for it allows easy GUI development and has a programming style similar to
Max/MSP.)