Merge branch 'add-readme'

This commit is contained in:
Bartłomiej Pluta
2019-09-17 23:15:03 +02:00
46 changed files with 4227 additions and 7 deletions

2366
README.md Normal file

File diff suppressed because it is too large Load Diff

1084
STDLIB.md Normal file

File diff suppressed because it is too large Load Diff

36
examples/adeste.mus Normal file
View File

@@ -0,0 +1,36 @@
println("Adeste Fideles");
println("John Francis Wade");
s1 = [@g, @g:2, @d, @g, @a:2, @d:2, @h, @a, @h, @c5, @h:2, @a, @g];
s2 = [@g:2, @f#, @e, @f#, @g, @a, @h, @f#:2, @e:4d, @d:8, @d:2d, 4];
s3 = [@d5:2, @c5, @h, @c5:2, @h:2, @a, @h, @g, @a, @f#:4d, @e:8, @d];
s4 = [@g, @g, @f#, @g, @a, @g:2, @d, @h, @h, @a, @h, @c5, @h:2, @a];
s5 = [@h, @c5, @h, @a, @g, @f#:2, @g, @c5, @h:2, @a:4d, @g:8, @g:1];
S = s1 + s2 + s3 + s4 + s5;
a1 = [@d, @d:2, @d, @d, @e:2, @d:2, @d, @d, @d, @e, @d:2, @d, @h3];
a2 = [@h3, @c#, @d, @c#, @d, @d, @d, @d, @d:2, @c#:4d, @d:8, @d:2d, 4];
a3 = [@d:2, @e:8, @f#:8, @g, @g, @f#, @g:2, @d, @d, @e, @e, @d:2, @d];
a4 = [@d, @d:1, @d:2d, @d, @d:1, @d:2d];
a5 = [@g, @f#, @g, @d, @d:8, @c#:8, @d:2, @d, @e, @d:2, @d:4d, @h3:8, @h3:1];
A = a1 + a2 + a3 + a4 + a5;
t1 = [@h3, @h3:2, @h3, @h3, @c:2, @a3:2, @g3, @a3, @g3, @g3, @g3:2, @f#3, @g3];
t2 = [@g3:2, @a3, @a3, @a3, @g3, @f#3, @d3, @a3:2, @g3:4d, @f#3:8, @f#3:2d, 4];
t3 = [@h3:2, @c, @d, @c:2, @d:2, @d, @g3, @h3, @c, @a3:2, @f#3];
t4 = [@h3, @h3, @a3, @h3, @c, @h3:2d, @g3, @g3, @f#3, @g3, @a3, @g3:2, @f#3];
t5 = [@d, @d, @d, @a3, @a3, @a3:2, @g3:2, @g3:2, @f#3:4d, @g3:8, @g3:1];
T = t1 + t2 + t3 + t4 + t5;
b1 = [@g3, @g3:2, @h3, @g3, @g3:2, @f#3:2, @g3, @f#3, @g3, @c3, @d3:2, @d3, @e3];
b2 = [@e3:2, @d3, @a2, @d3, @h2, @f#2, @g2, @a2:2, @a2:4d, @d3:8, @d2:2d, 4];
b3 = [@h3:2, @a3, @g3, @a3:2, @g3:2, @f#3, @g3, @e3, @c3, @d3:2, @d3];
b4 = [4, 1, 1, 1, 2, 4];
b5 = [@g3, @a3, @g3, @f#3, @e3, @d3, @c3, @h2, @c3, @d3:2, @d3:4d, @g2:8, @g2:1];
B = b1 + b2 + b3 + b4 + b5;
synth({ tuning -> 431, attack -> 100, decay -> 1.2, overtones -> [0.7, 0, 0.2, 0.1] }, S, A, T, B);

42
examples/bohemian.mus Normal file
View File

@@ -0,0 +1,42 @@
println("Bohemian Rhapsody :: part");
println("by Queen");
m1 = [@d:8, @d:8, @d:2, 8, @b3:8, @c:8, @d:16, @d:16, @d, 4, 8, @d:16, @d:16];
m2 = [@eb:8, @f:8, @eb:8, @d:8, @c, @c:8, @d:8, @eb:16, @f:8, @eb:8d, @d:8, @c, 4, @d:8, @d:8, @d:2, @d:8, @f:8];
m3 = [@a:8d, @g:16, @g:2, 8, @g:8, @b:8, @b:8, @b:8, @b:8, @b:8d, @g:16, @d:8d, @c:16, @c:2, 2];
M1 = [1, 1] + m1 + m2 + m3;
p_B = [@d:8, @f3:8, @b3:8, @d:8, @g:8, @f3:8, @f:8, @f:8];
p_g = [@d:8, @g3:8, @b3:8, @d:8, @a:8, @g3:8, @g:8, @b3:8];
p_c = [@g:8, @c:8, @eb:8, @g:8, @d5:8, @c:8, @c5:8, @c:8];
p_cF = [@b:8, @c:8, @eb:8, @g:8, @a:8, @eb:8, @f:8, @c:8];
p1 = [@eb:8, @c:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @a3:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @g:8];
P1 = p_B + p_B + p_B + p_g + p_c + p_cF + p_B + p_g + p1;
b1 = [@b3:1, @g3:1, @c3:1, @c3:2, @f3:2];
b2 = [@b3:2d, @a3, @g3:1, @c3:2, @h2, @b2, @a2:2, @ab2, @g2];
B1 = [@b3:1, @b3:1] + b1 + b2;
# Eb
m1 = [@g:16, @g:16, @g:2, 8, @f:8, @g:16, @ab:16, @g:2, 4, 8, @g:16, @g:16, @ab:8d, @g:16, @g:8, @f:16, @f:2, @b3:16];
m2 = [@b3:8, @f:8, @f:8, @g:16, @g:8d, @ab:8, @ab:8, @b:16, @ab:16, @ab:8, @g:8, 8, @f:16, @g:16, @b:4d, @f:16, @g:16];
m3 = [@eb:4d, @b3:16, @b3:16, @h3:8, @db:8, @h3:16, @db:16, @h3:8, @b3:2, 2];
M2 = m1 + m2 + m3;
p_Eb = [@b:8, @eb:8, @eb5:8, @eb:8, @b:8, @eb:8, @f:8, @b:8];
p_f = [@ab:8, @f:8, @ab:8, @ab:8, @ab:8, @eb:8, @ab:8, @d:8];
p_B = [@d, @f, @g, @ab];
p_EbB = [@b:8, @eb:8, @eb5:8, @eb:8, @b:8, @d:8, @b:8, @d:8];
p_cf = [@g:8, @c:8, @g:8, @c:8, @h3:2];
P2 = p_Eb + p_c + p_f + p_B + p_EbB + p_cf;
b1 = [@eb3:2d, @d3, @c3:1, @f3:4d, @e3:8, @eb3, @d3, @b2, @b2, @b2, @b2, @eb3:2, @d3:2];
b2 = [@c2:2, @f2:2, @eb2:2, 2];
B2 = b1 + b2;
M = M1 + M2;
P = P1 + P2;
B = B1 + B2;
synth({ tuning -> 432, bpm -> 72, overtones -> [0.5, 0.3, 0.15, 0.05], decay -> 0.8 }, transpose(12, M), P, B);

120
examples/cantina.mus Normal file
View File

@@ -0,0 +1,120 @@
println("Star Wars :: Cantina Band");
println("by John Williams");
cb1 = [@a, @d5, @a, @d5] + [@a:8, @d5, @a:8, 8, @g#:8, @a];
cb2 = [@a:8, @g#:8, @a:8, @g:8, 8, @f#:8, @g:8, @gb:8];
cb3 = [@f:4d, @d:2, 8];
cb4 = [@g:8, 8, @g:4d, @f#:8, @g];
cb5 = [@c5:8, @b, @a, @g:4d];
cb6 = [@c5:8, 8, @c5:4d, @a:8, @g];
cb7 = [@f:4d, @d:2, 8];
cb8 = [@d:2, @f:2, @a:2, @c5:2];
cb9 = [@eb5, @d5, @g#:8, @a, @f:8];
CB1 = cb1 + cb2 + cb3 + cb1 + cb4 + cb5 + cb1 + cb6 + cb7 + cb8 + cb9 + [1];
cb11 = 2 ^ [8, @a5, @f5:8, @a5:8, 8, 4];
cb12 = [8, @a5, @f5:8, @g#5:8, @a5, @f5:8];
cb13 = [@f5:4d, @d5:2, 8];
cb14 = [8, @a5, @f5:8, @g#5:8, @a5, @g5:8];
cb15 = [@g5:2, @c5:2];
cb16 = [@b:8, @d5:8, @f5, @h:8, @d5:8, @f5];
cb17 = [@g#:8, @a5, @d5:2, 8];
cb18 = [@d:8, @f:8, @h:8, @d5:8, @g#:8, @a, @f:8];
cb19 = [@f:2d, 4];
CB2 = cb11 + cb12 + cb13 + cb11 + cb14 + cb15 + cb11 + cb12 + cb13 + cb16 + cb17 + cb18 + cb19;
cb20 = [@f, 8, @ab, @f:8, @g];
cb21 = [8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @d:8];
cb22 = [@f, 8, @ab, @f:8, @g];
cb23 = [@f:8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @f:8];
cb24 = [@g:8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @d:8];
cb25 = [@f:8, @f:8, @ab:8, @f:8, @ab:8, @f, @f:8, @f:2d, 4];
CB3 = cb20 + cb21 + cb22 + cb21 + cb22 + cb21 + cb23 + cb24 + cb22 + cb21 + cb22 + cb21 + cb22 + cb21 + cb25;
cb26 = [@c5, 8, @e5:8, 4, @g5];
cb27 = [@g5:8, @g5, @g5:8, @g5, @e5:8, @c5:8];
cb28 = [@f5, @f5:8, @f5:8, @f5:8, @g5, @a5:8, @a5:1];
cb29 = [@e5, @e5, @g5:8, @g5, @c5:8];
cb30 = [@c5:8, @e5, @c5:8, @e5, @g5];
cb31 = [@f5, @f5:8, @f5, @g5, @a5:8, @a5:1];
cb32 = [@b5, @b5, @d6, @b5:8, @db6:8];
cb33 = [@db6:8, @db6:8, @b5, @db6, @b5];
cb34 = [@f5, @f5, @f5:8, @ab5, @d6:8, @d6:1];
cb35 = [8, @b, @d5:8, @g5, @g5];
cb36 = [8, @e5, 8, @e5, @e5];
cb37 = [8, @f5, @f5:8, @f5, @f5:8, @f5:8];
cb38 = [@f5:8, @f5, @f5:8, @f5:8, @f5:8, @f5];
CB4 = cb26 + cb27 + cb28 + cb29 + cb30 + cb31 + cb32 + cb33 + cb34 + cb35 + cb36 + cb37 + cb38;
cb39 = [@ab:8, @gb:8, @ab:8, @gb:8, @ab:8, @gb:8, @ab:8, @gb:8];
cb40 = [@ab:8, @db5, @ab:8, @db5, @ab:8, @db5:8];
cb41 = [8, @ab:8, @b:8, @h:8, @c5:8, @h:8, @b:8, 8];
cb42 = [@ab:8, @db5, @ab:8, @db5, @ab:8, @a:8];
cb43 = [@b:8, @a:8, @b:4d, @a:8, @b:8, @a:8];
cb44 = [@b:8, @a:8, @b:8, @h:8, @c5:8, 8, @gb:8, @g:8];
cb45 = [@b:8, @a:8, @b:4d, @a:8, @b:8, @h:8];
cb46 = [@c5:8, @g:8, @e:8, @c:8, 8, @c:8, @db:8, @c:8];
cb47 = [@db:8, @b3, @db:8, @fb:8, @db, @fb:8];
cb48 = [@f:8, @e:8, @f:8, @gb:8, @g:8, @c, @g:8];
cb49 = [@ab:8, @g:8, @ab:8, @a:8, @b:8, @a:8, @b:8, @h:8];
cb50 = [@c5:8, @c5:8, 4, @c5:8, @c5:8, 4];
cb51 = [@c5, @e5:2, @f5:8, @db5:8];
cb52 = [@ab:8, @f:8, @fb:8, @eb:8, @d:8, 4, @gb:8];
cb53 = [@c5:8, @c5, @gb:8, @c5:8, @c5, @h:8];
cb54 = [@c5:8, @c5, @h:8, @c5:8, @c5, @c5:8];
cb55 = [@db5:8, @fb:8, @db5:4d, @fb:8, @db5:8, @fb:8];
cb56 = [@db5:8, @fb:8, @db5:8, @fb:8, @eb:8, @c5, @c5:8];
cb57 = [@db5:8, @fb:8, @db5:8, @fb:8, @eb:8, @c5, @h3:8];
cb58 = [@b3:8, @db:8, @gb:8, @b:8, @c:8, @e:8, @g:8, @c5:8];
cb59 = [@db5:8, @db, @c:8, @db, 4];
cb60 = [4, @a3, @b3, @a3, @b3, @a3, @gb3:8, @f3:8, @d3:8, 8];
cb61 = [8, @a3, @a3, @a3, @a3, @a3, @a3:8, @a3:8, @a3];
CB5 = cb39 + cb40 + cb41 + cb39 + cb42 + cb43 + cb44 + cb39 + cb42 + cb45 + cb46 + cb47 + cb48 + cb49 + cb50 + cb50 + cb51 + cb52 + cb53 + cb54 + cb55 + cb56 + cb55 + cb56 + cb55 + cb57 + cb58 + cb59 + cb60 + cb60 + cb60;
CB = CB1 + CB2 + CB3 + (2 ^ CB4) + CB5;
b1 = (3 ^ [@d3, 4, @a2, 4]) + [@f3, 4, @c3, 4, @d3, 4, @a2, 4, @d3, 4, @a2, 4, @g2, 4, @g2, 4];
b2 = [@c3, @d3, @d#3, @e3, @d3, 4, @a2, 4, @d3, 4, @a2, 4, @c3, 4, @c3, 4];
b3 = [@f3, 4, @c3, 4, @b2, 4, @b2, 4, @f3, 4, @d3, 4, @g3, 4, @c3, 4, @f3, @e3, @d3, @c3];
B1 = b1 + b2 + b3;
b4 = (3 ^ [@d3, 4, @a2, 4]) + [@d3:4d, @g#2:4d, @a2];
b5 = (3 ^ [@d3, 4, @a2, 4]) + [@eb3:2, @c3, @c3];
b6 = (4 ^ [@d3, 4, @a2, 4]);
b7 = [@b2:8, @b2:8, 4, @h2:8, @h2:8, 4, @c3:4d, @d3:8, 8, @d3:8, @d3, @g2, 4, @c3:4d, @f3:4d, @e3, @d3, @c3];
B2 = b4 + b5 + b6 + b7;
b8 = 3 ^ [@d3, @c3, @b2, @a2, @g2, @f2, @e2, @d2];
b9 = [@d3, 4, 2, 2, 4, @a2];
b10 = [@d3, @b2, @a2, @a2, @d3:8, 8, 4, 2];
B3 = b8 + b9 + b8 + b10;
b11 = [@c3, 4, @g2, 4, @c3, 8, @b2:4d, @g2, @f2, 4, @c3, 4, @f3, 8, @e3:4d, @d3];
b12 = [@c3, 4, @g3, 4, @c3, 8, @b2:4d, @g2, @f2, 4, @c3, 4, @d3, 8, @f#2:4d, @a2];
b13 = [@b2, 4, @b2, 4, @h2, 4, @h2, 4, @c3, 4, @c3, 4, @d3, 8, @d3:4d, @f#2];
b14 = [@g2, 4, @d3, 4, @c3, 8, @c3:4d, @g3, @f3, 4, @db3, 4, @f3, @f3, @e3, @d3];
B4 = b11 + b12 + b13 + b14;
b15 = [@db3, @c3, @b2, @ab2, @gb2, @f2, @eb2, @db2, @db3, @b2, @a2, @ab2];
b16 = [@db3, @c3, @b2, @ab2, @gb2, @f2, @eb2, @db2, @eb2, @e2, @f2, @gb2];
b17 = [@e2, @d2, @h2, @ab2, @h2, @ab2, @f2, @eb2, @db2, @c2, @b1, @ab1];
# ^ or B?
b18 = [@gb2, @gb2, @gb2, @db3, @c3, @c3, @e3, @g3, @gb3, @gb3, @g3, @g3];
b19 = [@ab3, @db3, @c3, @c3, @f3, @c3, @gb3, @gb3, @c3, 4, @c3, 4];
b20 = [@f3, 4, @f3, 4, @c3, @c3, 4, @db3:8, @f3:8, @ab3:8, @a3:8, @b3:8, @h3:8, @c:8, 8, 8, 16, @g3:16];
b21 = [@c3, 4, @c3, 4, @f3, 4, @f3, 4, @gb2, 4, @ab2, 4, @a2, 4, @db3, 4, @gb2, 4, @ab2, 4, @a2, 4, @db3, 4, @d, 4, @eb, 4];
b22 = [@e3, 4, @f3, 4, @gb3, 4, @g3, 4, @db3, 4, @db3, 4];
B5 = b15 + b16 + b17 + b18 + b19 + b20 + b21 + b22;
B = B1 + B2 + B3 + (2 ^ B4) + B5;
synth({ tuning -> 432, bpm -> 270 }, flat(CB), flat(B));

31
examples/les_anges.mus Normal file
View File

@@ -0,0 +1,31 @@
println("Les Anges dans nos campagnes");
s = [@a, @a, @a, @c5, @c5:4d, @b:8, @a:2, @a, @g, @a, @c5, @a:4d, @g:8, @f:2];
sc = [@c5:2, @d5:8, @c5:8, @b:8, @a:8, @b:2, @c5:8, @b:8, @a:8, @g:8, @a:2, @b:8, @a:8, @g:8, @f:8, @g:4d, @c:8, @c:2, @f, @g, @a, @b];
sca = [@a:2, @g, 4];
scb = [@a:2, @g:2, @f:2d, 4];
S = flat(2^s, sc, sca, sc, scb);
a = [@f, @f, @e, @e, @g, @e, @f:2, @f, @e, @f, @f, @f, @e, @f:2];
ac = [@f, @a:8, @g:8, @f:2d, @g:8, @f:8, @e:2d, @f:8, @e:8, @d:2, @c:4d, @c:8, @c:2, @c, @e, @f, @g];
aca = [@f:2, @e, 4];
acb = [@f:2, @e:2, @c:2d, 4];
A = flat(2^a, ac, aca, ac, acb);
t = [@c, @c, @c, @c, @d, @c, @c:2, @c, @c, @c, @c, @c:4d, @b3:8, @a3:2];
tc = [@a3:2, @d:1, @c:1, @b3:2, @g3, @f3, @e3:2, @f3, @c, @c, @d];
tca = [@c:2, @c, 4];
tcb = [@c:2d, @b3, @a3:2d, 4];
T = flat(2^t, tc, tca, tc, tcb);
b = [@f3, @f3, @a3, @a3, @g3, @c3, @f3:2, @f3, @c3, @f3, @a3, @c, @c3, @f3:2];
bc = [@f3:2, @d3, @f3, @g3:2, @c3, @e3, @f3:2, @b2, @d3, @e3, @d3, @c3, @b2, @a2, @c3, @f3, @b2];
bca = [@c3:2, @c3, 4];
bcb = [@c3:1, @f3:2d, 4];
B = flat(2^b, bc, bca, bc, bcb);
synth({ tuning -> 432, overtones -> [0.6, 0.3, 0.07, 0.03], attack -> 200, decay -> 0.6 }, S, A, T, B);

18
examples/per_crucem.mus Normal file
View File

@@ -0,0 +1,18 @@
println("Per Crucem - canon");
d1 = [@d:2, @d:2, @c:2, @f:4d, @f:8, @f, @f, @e, @d, @e:2, @d:2];
d2 = [@d:8, @f:8, @a:8, @d5:8, @b:8, @a:8, @g, @c:8, @e:8, @g:8, @c5:8, @a:8, @g:8, @f, @b3:8, @d:8, @f:8, @b:8, @g:8, @f:8, @e, @a, @e, @f:2];
d3 = [@a:2, @b:2, @c5:2, @a:4d, @a:8, @b, @f, @g, @g, @a, @e, @f:2];
d4 = [@d5:8, @c5:8, @b:8, @a:8, @g:8, @a:8, @b, @c5:8, @b:8, @a:8, @g:8, @f:8, @g:8, @a, @b:8, @a:8, @g:8, @f:8, @e:8, @f:8, @g, @a, @e, @f:2];
d5 = [@d5:2, @d5:2, @c5:2, @c5:2, @d5:8, @c5:8, @b:8, @a:8, @b, @b, @a:2, @a:2];
d6 = [@d:8, @d:8, @d:8, @d:8, @g:8, @g:8, @g, @c:8, @c:8, @c:8, @c:8, @f:8, @f:8, @f, @b3:8, @b3:8, @b3:8, @b3:8, @e:8, @e:8, @e, @a3, @a3, @d:2];
p = [1, 1, 1, 1];
S = d1 + d2 + d3 + d4 + d5 + d6 + d1 + d2 + d3;
A = p + d1 + d2 + d3 + d4 + d5 + d6 + d1 + d2;
T = p + p + d1 + d2 + d3 + d4 + d5 + d6 + d1;
B = p + p + p + d1 + d2 + d3 + d4 + d5 + d6;
wv = wave(S, A, transpose(-12, T), transpose(-12, B));
synth(wv);

View File

@@ -0,0 +1,31 @@
println("Narodził się nam Zbawiciel / Quem pastores laudavere");
println("mel.: XIV w.");
println("sł.: XV - XVI w.");
println("harm.: Bartłomiej Pluta");
s1 = [@f:2, @a, @c5:2, @a, @c5:2, @d5, @c5, @g:2];
s2 = [@a:2, @c5, @b:2, @g, @f:2, @d, @e, @c:2];
s3 = [@a:2, @b, @c5:2, @d5, @c5:2, @g, @a, @f:2];
s4 = [@b:2, @b, @a, @g, @a, @f, @d, @e, @f:2d];
a1 = [@c:2, @f, @g:2, @f, @f, @g, @f, @f, @f, @e];
a2 = [@f, @e, @eb, @d:2, @c, @d:2, @d, @c, @c, @b3];
a3 = [@c:2, @c, @f, @d, @g, @g:2, @e, @e, @d:2];
a4 = [@f:2, @f, @f, @e, @f, @c:2, @c, @c:2d];
t1 = [@a, @b, @c5, @c5, @b, @c5, @a:2, @b, @a, @c5:2];
t2 = [@c5:2, @a, @b:2, @c5, @d5, @c, @b, @g, @g:2];
t3 = [@f, @a, @g, @a:2, @b, @b:2, @g, @g, @a:2];
t4 = [@d5, @db5, @db5, @c5, @b, @a, @g:2, @b, @a:2d];
b1 = [@f:2, @f, @e:2, @f, @f:2, @f, @c, @c:2];
b2 = [@f:2, @f#, @g, @f, @e, @d, @f, @g, @c, @e:2];
b3 = [@f:2, @e, @f, @f#, @g, @e, @d, @c, @c#, @d, @c];
b4 = [@b3:2, @b, @c:2, @c, @c:2, @c, @f:2d];
S = s1 + s2 + s3 + s4;
A = a1 + a2 + a3 + a4;
T = transpose(-12, t1 + t2 + t3 + t4);
B = transpose(-12, b1 + b2 + b3 + b4);
synth({ overtones -> [0.6, 0.25, 0.1] + (2 ^ 0.0) + [0.05], attack -> 50, decay -> 1 }, S, A, T, B);

BIN
img/notes/cd4fga8c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
img/notes/cdef.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
img/notes/poly1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
img/notes/poly2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
img/notes/starwars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
img/notes/twinkle1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
img/notes/twinkle2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
img/notes/twinkle3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
img/plots/a_127.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
img/plots/a_1overtone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
img/plots/a_2overtones.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
img/plots/a_3overtones.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
img/plots/a_440.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
img/plots/attack0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
img/plots/attack1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
img/plots/attack10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
img/plots/attack100.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
img/plots/attack5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
img/plots/c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
img/plots/decay0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
img/plots/decay05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
img/plots/decay1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
img/plots/decay10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
img/plots/decay5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
img/plots/default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
img/plots/spectrum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
img/schemas/wait_fsm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -113,11 +113,11 @@ def LoopParser(input):
return Parser.allOf( return Parser.allOf(
ExpressionWithoutLoopParser, ExpressionWithoutLoopParser,
Parser.optional(loopParameters), Parser.optional(loopParameters),
Parser.terminal(TokenType.DASH, createNode=Operator.withValue), Parser.terminal(TokenType.CARET, createNode=Operator.withValue),
StatementParser, StatementParser,
Parser.optional(loopFilter), Parser.optional(loopFilter),
createNode=Loop.loop, createNode=Loop.loop,
name="dash-loop" name="caret-loop"
)(input) )(input)

492
smnp/library/code/main.mus Normal file
View File

@@ -0,0 +1,492 @@
function flat(list lists...) {
return _flat(lists as l ^ _flat(l, []), []);
}
function _flat(list l, list output) {
l as elem ^ {
if (typeOf(elem) == list) {
output = _flat(elem, output);
} else {
output = output + [elem];
}
}
return output;
}
extend note as n {
function withOctave(integer octave) {
return Note(n.pitch, octave, n.duration, n.dot);
}
function withDuration(integer duration) {
return Note(n.pitch, n.octave, duration, n.dot);
}
function withDot(bool dot) {
return Note(n.pitch, n.octave, n.duration, dot);
}
function toIntRepr() {
return n.octave * 12 + _pitchToNumber(n.pitch);
}
function transpose(integer value) {
return noteFromIntRepr(n.toIntRepr() + value, n.duration, n.dot);
}
}
function noteFromIntRepr(integer intRepr, integer duration, bool dot) {
pitch = _numberToPitch(mod(intRepr, 12));
octave = Integer(intRepr / 12);
return Note(pitch, octave, duration, dot);
}
function mod(integer a, integer b) {
return a - b * Integer(a/b);
}
function _pitchToNumber(string pitch) {
return _keysToIntMapper(
"C",
"CIS",
"D",
"DIS",
"E",
"F",
"FIS",
"G",
"GIS",
"A",
"AIS",
"H"
).get(pitch);
}
function _keysToIntMapper(keys...) {
return Map(keys as (i, key) ^ [key, i]);
}
function _numberToPitch(integer number) {
return ["C", "CIS", "D", "DIS", "E", "F", "FIS", "G", "GIS", "A", "AIS", "H"].get(number);
}
function transpose(integer value, <note, integer, list<note, integer>> notes...) {
if (notes.size == 1) {
first = notes.get(0);
if (typeOf(first) == integer) {
return first;
} else if (typeOf(first) == note) {
return first.transpose(value);
} else if (typeOf(first) == list) {
return _transpose(value, first);
}
}
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
output = [];
notes as n ^ {
if (typeOf(n) == integer) {
output = output + [n];
} else if (typeOf(n) == note) {
output = output + [n.transpose(value)];
} else if (typeOf(n) == list) {
output = output + [_transpose(value, n)];
}
}
return output;
}
function _transpose(integer value, list<note, integer> notes) {
output = [];
notes as n ^ {
if (typeOf(n) == integer) {
output = output + [n];
} else if (typeOf(n) == note) {
output = output + [n.transpose(value)];
}
}
return output;
}
function transposeTo(note target, <note, integer, list<note, integer>> notes...) {
if (notes.size == 1) {
first = notes.get(0);
if (typeOf(first) == integer) {
return first;
} else if (typeOf(first) == note) {
return _transposeTo(target, notes).get(0);
} else if (typeOf(first) == list) {
return _transposeTo(target, first);
}
}
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
return _transposeTo(target, notes);
}
if (lists) {
return notes as n ^ _transposeTo(target, n);
}
}
function _transposeTo(note target, list<note, integer> notes) {
if (notes.size == 0) {
throw "Provide list with one note at least";
}
firstNote = notes.get(0);
semitones = semitones(firstNote, target);
return transpose(semitones, notes);
}
function tuplet(integer n, integer m, note notes...) {
if (n != notes.size) {
throw "Expected " + n.toString() + " notes exactly, whereas " + notes.size.toString() + " was passed";
}
return notes as x ^ x.withDuration(x.duration * n / m);
}
extend list as l with function contains(expectedValue) {
return (l as value ^ value % value == expectedValue).size > 0;
}
extend map as m {
function containsKey(expectedKey) {
return m.keys.contains(expectedKey);
}
function containsValue(expectedValue) {
return m.values.contains(expectedValue);
}
function contains(key, value) {
if (m.keys.contains(key)) {
return m.get(key) == value;
}
return false;
}
}
function sample(items...) {
if (items.size == 0) {
throw "Provide one item at least";
}
if (items.size == 1 and typeOf(items) == list) {
return items.get(0).get(rand(0, items.get(0).size-1));
}
return items.get(rand(0, items.size-1));
}
extend string as s with function join(list<string> l) {
output = "";
l as (index, item) ^ {
output = output + item;
if (index < l.size - 1) {
output = output + s;
}
}
return output;
}
function random(map<string><> items...) {
accumulator = 0;
items as (index, item) ^ {
if (item.size != 2) {
throw "Expected lists with two items: percent and value";
}
if (not item.containsKey("percent")) {
throw "Item " + (index+1).toString() + " does not have 'percent' key";
}
if (not item.containsKey("value")) {
throw "Item " + (index+1).toString() + " does not have 'value' key";
}
accumulator = accumulator + item.get("percent");
}
if (accumulator != 100) {
throw "Sum of first element of each item must be equal to 100";
}
accumulator = 0;
random = rand(0, 99);
items as item ^ {
accumulator = accumulator + item.get("percent");
if (random < accumulator) {
return item.get("value");
}
}
}
function semitones(<note, integer, list<note, integer>> notes...) {
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
return _semitones(notes);
}
if (lists) {
output = [];
notes as n ^ {
output = output + [_semitones(n)];
}
#if (output.size == 1) {
# return output.get(0)
#}
return output;
}
return [];
}
function _semitones(list<note, integer> notes) {
onlyNotes = notes as n ^ n % typeOf(n) == note;
if (onlyNotes.size == 2 and typeOf(onlyNotes.get(0)) == note and typeOf(onlyNotes.get(1)) == note) {
first = onlyNotes.get(0);
second = onlyNotes.get(1);
return second.toIntRepr() - first.toIntRepr();
}
if (onlyNotes.size < 2) {
throw "Provide 2 notes at least to evaluate semitones between them";
}
output = [];
range(1, onlyNotes.size-1) as i ^ {
output = output + [onlyNotes.get(i).toIntRepr() - onlyNotes.get(i-1).toIntRepr()];
}
return output;
}
function stringInterval(integer semitones) {
return [
"1",
"2m",
"2M",
"3m",
"3M",
"4",
"5d/4A",
"5",
"6m",
"6M",
"7m",
"7M"
].get(semitones);
}
function interval(<note, integer, list<note, integer>> notes...) {
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
semitones = _semitones(notes);
if (typeOf(semitones) == list) {
return semitones as n ^ stringInterval(n);
} else {
return stringInterval(semitones);
}
}
if (lists) {
output = [];
notes as n ^ {
semitones = _semitones(n);
if (typeOf(semitones) == list) {
output = output + [_semitones(n) as semitone ^ stringInterval(semitone)];
} else {
output = output + [stringInterval(semitones)];
}
}
#if (output.size == 1) {
# return output.get(0);
#}
return output;
}
return [];
}
function noteRange(note a, note b, string filter = "all") {
filters = {
"all" -> [ "C", "CIS", "D", "DIS", "E", "F", "FIS", "G", "GIS", "A", "AIS", "H" ],
"diatonic" -> [ "C", "D", "E", "F", "G", "A", "H" ],
"chromatic" -> [ "CIS", "DIS", "FIS", "GIS", "AIS" ]
};
if (not filters.containsKey(filter)) {
throw "Unknown filter: '" + filter + "'";
}
notes = range(a.toIntRepr(), b.toIntRepr()) as intRepr ^ noteFromIntRepr(intRepr, a.duration, a.dot);
return notes as n ^ n % filters.get(filter).contains(n.pitch);
}
function range(<integer, float> a, <integer, float> b, <integer, float> step = 1) {
if (not (step > 0)) {
throw "Step should be greater than 0";
}
if (a > b) {
throw "Upper range value should be greater than lower or equal to";
}
output = [];
i = a;
i <= b ^ {
output = output + [i];
i = i + step;
}
return output;
}
function alert(<integer, bool> cycles = true, string melody = "beep", list<float, integer> overtones = [0.5, 0.0, 0.0, 0.5]) {
if (not [integer, bool].contains(typeOf(cycles))) {
throw "Provide 'true' or number of cycles as first argument";
}
if (typeOf(cycles) == integer) {
if (cycles < 1) {
throw "Number of cycles cannot be less than 1";
}
}
if (typeOf(cycles) == bool) {
if (not cycles) {
throw "Provide 'true' or number of cycles as first argument";
}
}
notes = {
"beep" -> [@c5:16, 32, @c5:16, 3],
"s1" -> noteRange(@c5:32, @g5:32),
"s2" -> _upDown(noteRange(@c5:32, @g5:32)),
"s3" -> [@a5:16, @d5:16],
"semitone" -> [@c5:16, @db5:16]
};
if (not notes.containsKey(melody)) {
throw "Unknown melody '" + melody + "'. Available: 'beep', 's1', 's2', 's3' and 'semitone'";
}
config = {
bpm -> 120,
decay -> 0.5,
attack -> 200,
overtones -> overtones
};
wave = wave(config, notes.get(melody));
cycles ^ synth(wave);
}
function _upDown(list l) {
return l + -l;
}
function metronome(integer bpm = 120, integer beats = 4, countMeasures = false) {
accent = wave({
overtones -> flat([0.5, 0.1, 10^0, 0.1, 10^0, 0.1, 20^0, 0.1, 25^0, 0.05, 25^0, 0.05]),
attack -> 0,
decay -> 5,
bpm -> bpm
}, @c);
beat = wave({
overtones -> flat([0.5, 10^0, 0.3, 10^0, 0.2]),
attack -> 0,
decay -> 100,
bpm -> bpm
}, @c);
measure = 1;
true ^ {
if (countMeasures) {
println(measure);
measure = measure + 1;
}
synth(accent);
beats - 1 ^ synth(beat);
}
}

View File

@@ -47,7 +47,7 @@ def getValueAccordingToType(value, type):
raise ValueError() raise ValueError()
raise RuntimeException(f"Type {type.value.name.lower()} is not suuported", None) raise RuntimeException(f"Type {type.value.name.lower()} is not supported", None)
except ValueError: except ValueError:
raise RuntimeException(f"Invalid value '{value}' for type {type.value.name.lower()}", None) raise RuntimeException(f"Invalid value '{value}' for type {type.value.name.lower()}", None)

View File

@@ -51,7 +51,7 @@ class ReturnEvaluator(Evaluator):
# Disclaimer # Disclaimer
# Exception system usage to control program execution flow is really bad idea. # Exception system usage to control program execution flow is really bad idea.
# However because of lack of 'goto' instruction equivalent in Python # However because of lack of 'goto' instruction equivalent in Python
# there is to need to use some mechanism to break function execution on 'return' statement # there is a need to use some mechanism to break function execution on 'return' statement
# and immediately go to Environment's method 'invokeFunction()' or 'invokeMethod()', # and immediately go to Environment's method 'invokeFunction()' or 'invokeMethod()',
# which can handle value that came with exception and return it to code being executed. # which can handle value that came with exception and return it to code being executed.
else: else:

View File

@@ -18,4 +18,4 @@ class PowerEvaluator(Evaluator):
if not right.type in supportedTypes: if not right.type in supportedTypes:
raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type", node.right.pos) raise RuntimeException(f"Operator '{node.operator.value}' is supported only by {[t.name.lower() for t in supportedTypes]} type", node.right.pos)
return Type.integer(int(left.value ** right.value)) return Type.float(float(left.value ** right.value))

View File

@@ -36,7 +36,7 @@ tokenizers = (
defaultTokenizer(TokenType.SLASH), defaultTokenizer(TokenType.SLASH),
defaultTokenizer(TokenType.MINUS), defaultTokenizer(TokenType.MINUS),
defaultTokenizer(TokenType.PLUS), defaultTokenizer(TokenType.PLUS),
defaultTokenizer(TokenType.DASH), defaultTokenizer(TokenType.CARET),
defaultTokenizer(TokenType.DOTS), defaultTokenizer(TokenType.DOTS),
defaultTokenizer(TokenType.AMP), defaultTokenizer(TokenType.AMP),
defaultTokenizer(TokenType.DOT), defaultTokenizer(TokenType.DOT),

View File

@@ -21,7 +21,7 @@ class TokenType(Enum):
SLASH = '/' SLASH = '/'
MINUS = '-' MINUS = '-'
PLUS = '+' PLUS = '+'
DASH = '^' CARET = '^'
DOTS = '...' DOTS = '...'
AMP = '&' AMP = '&'
DOT = '.' DOT = '.'