From d720266b87462b6000db2c9a80b503703b2634ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Pluta?= Date: Tue, 17 Sep 2019 23:07:59 +0200 Subject: [PATCH] Add *.mus files --- examples/adeste.mus | 36 +++ examples/bohemian.mus | 42 ++++ examples/cantina.mus | 120 +++++++++ examples/les_anges.mus | 31 +++ examples/per_crucem.mus | 18 ++ examples/quem_pastores.mus | 31 +++ smnp/library/code/main.mus | 492 +++++++++++++++++++++++++++++++++++++ 7 files changed, 770 insertions(+) create mode 100644 examples/adeste.mus create mode 100644 examples/bohemian.mus create mode 100644 examples/cantina.mus create mode 100644 examples/les_anges.mus create mode 100644 examples/per_crucem.mus create mode 100644 examples/quem_pastores.mus create mode 100644 smnp/library/code/main.mus diff --git a/examples/adeste.mus b/examples/adeste.mus new file mode 100644 index 0000000..63f631e --- /dev/null +++ b/examples/adeste.mus @@ -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); \ No newline at end of file diff --git a/examples/bohemian.mus b/examples/bohemian.mus new file mode 100644 index 0000000..c94a985 --- /dev/null +++ b/examples/bohemian.mus @@ -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); diff --git a/examples/cantina.mus b/examples/cantina.mus new file mode 100644 index 0000000..23d8e9e --- /dev/null +++ b/examples/cantina.mus @@ -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)); diff --git a/examples/les_anges.mus b/examples/les_anges.mus new file mode 100644 index 0000000..8e6d996 --- /dev/null +++ b/examples/les_anges.mus @@ -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); diff --git a/examples/per_crucem.mus b/examples/per_crucem.mus new file mode 100644 index 0000000..6a00e05 --- /dev/null +++ b/examples/per_crucem.mus @@ -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); \ No newline at end of file diff --git a/examples/quem_pastores.mus b/examples/quem_pastores.mus new file mode 100644 index 0000000..dba085b --- /dev/null +++ b/examples/quem_pastores.mus @@ -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); \ No newline at end of file diff --git a/smnp/library/code/main.mus b/smnp/library/code/main.mus new file mode 100644 index 0000000..9614f1c --- /dev/null +++ b/smnp/library/code/main.mus @@ -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, > 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 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, > 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 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 l) { + output = ""; + l as (index, item) ^ { + output = output + item; + if (index < l.size - 1) { + output = output + s; + } + } + + return output; +} + +function random(map<> 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(> 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 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(> 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( a, b, 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( cycles = true, string melody = "beep", list 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); + } +}