Play Canon with Mathematica

Posted 1 year ago
3071 Views
|
8 Replies
|
9 Total Likes
|

I'm a Mathematica novice, so i think there is a lot of space to improve the code.

First I use the Bach's manuscript as the music score, but the output sound is chaos around the middle part.This score fit to play with the instrument, obviously not Mathematica.

After posting this awful version to my Weibo, my friend told me there is a Canon played by Matlab, it's so amazing, the most important its score suits for playing with software, so i decided to translate this score from Matlab to Mathematica.

Matlab code

There are 3 parts in Matlab code.

1.First, tell the computer how to make certain sounds.

There is a part of the code in Matlab (I'm a Chinese student, hopefully my poor English didn't confuse you. I will attach some concepts' wikilink, sorry about that)

% 1/4 notes
do0f = mod4.*cos(2*pi*ScaleTable(21)*f0*t4);
re0f = mod4.*cos(2*pi*ScaleTable(22)*f0*t4);
mi0f = mod4.*cos(2*pi*ScaleTable(23)*f0*t4);
% 1/8 notes
fa0e = mod8.*cos(2*pi*ScaleTable(1)*f0*t8);
so0e = mod8.*cos(2*pi*ScaleTable(2)*f0*t8);
la0e = mod8.*cos(2*pi*ScaleTable(3)*f0*t8);
% 1/16 notes
fa0s = mod16.*cos(2*pi*ScaleTable(1)*f0*t16);
so0s = mod16.*cos(2*pi*ScaleTable(2)*f0*t16);
la0s = mod16.*cos(2*pi*ScaleTable(3)*f0*t16);


For clear to see, I just pick few notes information

i.$\frac{1}{4}$,$\frac{1}{8}$,$\frac{1}{16}$means [the relative duration of a note][4](https://en.wikipedia.org/wiki/Note_value), the duration of Quarter note is twice that of Eighth note, the duration of 8th note is twice that of 16th note. In the Matlab code, the duration depends on $t4,t8, or\space t16$

ii.Obviously, "do0f" means the note's tone. If you plot the the curve of middle A, it will be like that

Middle A's frequency "f" is 440Hz. In the Matlab code, the frequency depends on "$ScaleTable(\space)\times f0$"

iii.mod is a modification function, it makes notes sound more soft. the number behind "mod" means it's duration

So the Matlab code looks more clear! It becomes$$notename=mod4\times cos(2\pi f t)$$ This the way how to make sounds in Matlab.

2.Second, tell the computer musical score

This part is easy to understand, just input the score.

% Base Melody
cello = [do1f do1f so0f so0f la0f la0f mi0f mi0f... fa0f fa0f do0f do0f fa0f fa0f so0f so0f];......
% Long Melody
violin = [mi2f mi2f re2f re2f do2f do2f ti1f ti1f... la1f la1f so1f so1f la1f la1f ti1f ti1f ......


3.Third, arrange the different instruments' sequence

Canon is an very interesting music style, you just need to put the same melody at 3 different time points, and done! (I know I didn't explain it clearly, you can see Canon's wiki link)

It looks beautiful in code

% violin1
v1 = [blkblock violin blkblock blkblock];
% violin2
v2 = [blkblock blkblock violin blkblock];
% violin3
v3 = [blkblock blkblock blkblock violin];

% Combination
s = c1+v1+v2+v3;
sound(s,fs);


Translate to Mathematica

We get all information about all notes and musical score, but it's Matlab code, not Mathematica, we need use Mathematica code translate it.(The Mathematica file at the bottom of the article, it's a little bit long, so I decided not to paste it here)

1. First, make the association between the note name and sound respectively in Mathematica. The output should be like this. I named this association "nametosoundass", remember this name.

2.Next, we should get the list of sequence of every instrument should be play.

i.Input the raw sequence in Matlab to Mathematica, as you can see, there are many characters we don't want to get, such as "...", "%%", return and whitespace

cellonoteinfo =
"do1f do1f so0f so0f la0f%% la0f mi0f mi0f...fa0f%% fa0f do0f do0f fa0f \n
fa0f so0f so0f";


ii.Define a function to delete these unexpected characters

infotonote[info_] :=
StringPartition[StringJoin@StringCases[info, _?LetterQ | _?DigitQ],
4];


iii.Get the sequence

In[1]:= cellonote = infotonote[cellonoteinfo]

Out[1]:= {"do1f", "do1f", "so0f", "so0f", "la0f", "la0f", "mi0f", "mi0f", \
"fa0f", "fa0f", "do0f", "do0f", "fa0f", "fa0f", "so0f", "so0f"}


3.Third, replace the note name in sequence by sound, then we will get the sound in sequence. We use the association "notetosoundass"

cello = Sound[Flatten@Table[Replace[cellonote, notetosoundass, 1], 23], {0}];
vio1 = Sound[Replace[violinnote, notetosoundass, 1], {8}];
vio2 = Sound[Replace[violinnote, notetosoundass, 1], {16}];
vio3 = Sound[Replace[violinnote, notetosoundass, 1], {24}];


0,8,16,24 at the end of code means the insert time of different instruments.

4.Finally, combine it

You can enjoy it here

BTW, this code runs 2 minutes to generate final music, i think it can be better, if you have another idea, glad to see your comment.

Both Matlab and Mathematica code are below.

Attachments:
8 Replies
Sort By:
Posted 1 year ago
 Interesting, but do you know about SoundNote? http://reference.wolfram.com/language/ref/SoundNote.html
Posted 1 year ago
 Yes, actually, my first version was made by SoundNote, but... I think you won't like it, because its score is not suitable for Mathematica. If you want to listen it, you can click here. I'm not sure you can open it, you know, i'm in China. If you like, you can use the score in Matlab and SoundNote to make a Canon, so that you can change the instrument.
Posted 1 year ago
 I think you won't like it, because its score is not suitable for Mathematica. Could you please explain this? How native Mathematica function SoundNote can be not suitable for Mathematica? I am curious to understand what advantage your method brings. Unfortunately I know very little of music theory.
Posted 1 year ago
 You can specify instruments like: Sound[SoundNote["G", 1, "Harpsichord"]]
Posted 1 year ago
 I mean the score of the first version (Bach's manuscript) is not suitable for playing with Mathematica, not the SoundNote function. The second version use another score (Matlab's score).
Posted 1 year ago
 I mean the music score of the first version (Bach's manuscript) is not suitable for playing with Mathematica, not the SoundNote function. The second version use another music score (Matlab's score).